Skip to content

Commit

Permalink
refactor: simplify network classes inheritance
Browse files Browse the repository at this point in the history
Co-authored-by: Tuditi <[email protected]>
  • Loading branch information
nicole-obrien and Tuditi committed Apr 30, 2024
1 parent a24b72c commit aaa0456
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 163 deletions.
146 changes: 0 additions & 146 deletions packages/shared/src/lib/core/network/classes/base-evm-network.class.ts

This file was deleted.

150 changes: 143 additions & 7 deletions packages/shared/src/lib/core/network/classes/evm-network.class.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,147 @@
import { NetworkType } from '../enums'
import { IEvmNetwork, IPureEvmNetworkConfiguration } from '../interfaces'
import { BaseEvmNetwork } from './base-evm-network.class'
import { writable, Writable } from 'svelte/store'

export class EvmNetwork extends BaseEvmNetwork implements IEvmNetwork {
public readonly type = NetworkType.Evm
import Web3 from 'web3'

constructor(chainConfiguration: IPureEvmNetworkConfiguration) {
super(chainConfiguration)
import { EVM_CONTRACT_ABIS } from '@core/layer-2/constants'
import { ContractType } from '@core/layer-2/enums'
import { Contract } from '@core/layer-2/types'

import { IAccountState } from '@core/account'
import { IError } from '@core/error/interfaces'
import { NETWORK_STATUS_POLL_INTERVAL } from '@core/network/constants'
import { updateErc721NftsOwnership } from '@core/nfts/actions'
import { getActiveProfile } from '@core/profile/stores'
import { BASE_TOKEN_ID, IBaseToken, ITokenBalance, TokenTrackingStatus } from '@core/token'
import { getOrRequestTokenFromPersistedTokens } from '@core/token/actions'
import { Converter } from '@core/utils'
import features from '@features/features'
import { CoinType } from '@iota/sdk/out/types'
import { ChainId, NetworkHealth, NetworkNamespace, NetworkType } from '../enums'
import { IBaseEvmNetworkConfiguration, IBlock, IEvmNetwork } from '../interfaces'
import { EvmNetworkId, EvmNetworkType, Web3Provider } from '../types'

export class EvmNetwork implements IEvmNetwork {
public readonly provider: Web3Provider

public readonly id: EvmNetworkId
public readonly namespace: NetworkNamespace.Evm
public readonly chainId: ChainId
public readonly coinType: CoinType
public readonly name: string
public readonly baseToken: IBaseToken
public readonly explorerUrl: string | undefined
public readonly rpcEndpoint: string
public readonly type: EvmNetworkType = NetworkType.Evm

public health: Writable<NetworkHealth> = writable(NetworkHealth.Operational)
public statusPoll: number | undefined

constructor({
id,
namespace,
chainId,
coinType,
baseToken,
name,
explorerUrl,
rpcEndpoint,
}: IBaseEvmNetworkConfiguration) {
try {
const _rpcEndpoint = new URL(rpcEndpoint).href
this.provider = new Web3(`${_rpcEndpoint}`)

this.id = id
this.namespace = namespace
this.chainId = chainId
this.coinType = coinType
this.baseToken = baseToken
this.name = name
this.explorerUrl = explorerUrl
this.rpcEndpoint = _rpcEndpoint

void this.startStatusPoll()
} catch (err) {
console.error(err)
throw new Error('Failed to construct EVM Network!')
}
}

startStatusPoll(): void {
this.statusPoll = window.setInterval(() => {
this.getLatestBlock()
.then(() => this.health.set(NetworkHealth.Operational))
.catch(() => this.health.set(NetworkHealth.Disconnected))
}, NETWORK_STATUS_POLL_INTERVAL)
}

destroy(): void {
clearInterval(this.statusPoll)
}

getContract(type: ContractType, address: string): Contract {
const abi = EVM_CONTRACT_ABIS[type]
if (!abi) {
throw new Error(`Unable to determine contract type "${type}"`)
}
return new this.provider.eth.Contract(abi, address)
}

async getGasPrice(): Promise<bigint | undefined> {
try {
const gasPrice = await this.provider.eth.getGasPrice()
return BigInt(gasPrice)
} catch {
return undefined
}
}

async getLatestBlock(): Promise<IBlock> {
const number = await this.provider.eth.getBlockNumber()
return this.provider.eth.getBlock(number)
}

async getBalance(account: IAccountState): Promise<ITokenBalance | undefined> {
const evmAddress = account.evmAddresses?.[this.coinType]
if (!evmAddress) {
return
}

if (features.collectibles.erc721.enabled) {
void updateErc721NftsOwnership(account, this.id)
}

const rawBalance = await this.provider.eth.getBalance(evmAddress)
const tokenBalance = { [BASE_TOKEN_ID]: Converter.bigIntLikeToBigInt(rawBalance) }

const erc20Balances = await this.getErc20BalancesForAddress(evmAddress)
for (const [tokenId, balance] of Object.entries(erc20Balances)) {
await getOrRequestTokenFromPersistedTokens(tokenId, this.id)
tokenBalance[tokenId] = Number.isNaN(Number(balance)) ? BigInt(0) : balance
}

return tokenBalance
}

async getErc20BalancesForAddress(evmAddress: string): Promise<ITokenBalance> {
const trackedTokens = getActiveProfile()?.trackedTokens?.[this.id] ?? {}
const erc20TokenBalances: ITokenBalance = {}
for (const [erc20Address, trackingStatus] of Object.entries(trackedTokens)) {
try {
if (trackingStatus === TokenTrackingStatus.Untracked) {
continue
}

const contract = this.getContract(ContractType.Erc20, erc20Address)
if (!contract || !this.coinType) {
continue
}
const rawBalance = await contract.methods.balanceOf(evmAddress).call()
erc20TokenBalances[erc20Address] = Converter.bigIntLikeToBigInt(rawBalance)
} catch (err) {
const error = (err as IError)?.message ?? err
console.error(error)
}
}
return erc20TokenBalances
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { IIscChain, IIscChainConfiguration, IIscChainMetadata } from '../interfaces'
import { Converter } from '@core/utils'
import { BaseEvmNetwork } from './base-evm-network.class'
import { EvmNetwork } from './evm-network.class'
import { IAccountState } from '@core/account/interfaces'
import { ITokenBalance } from '@core/token/interfaces'
import { fetchIscAssetsForAccount } from '@core/layer-2/utils'
import { getActiveProfileId } from '@core/profile/stores'
import { NetworkType } from '@core/network/enums'

export class IscChain extends BaseEvmNetwork implements IIscChain {
export class IscChain extends EvmNetwork implements IIscChain {
private readonly _chainApi: string
private _metadata: IIscChainMetadata | undefined

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { IBaseToken } from '@core/token'
import { Writable } from 'svelte/store'
import { NetworkHealth, NetworkNamespace } from '../enums'
import { NetworkHealth, NetworkNamespace, NetworkType } from '../enums'
import { NetworkId } from '../types'

export interface IBaseNetwork {
type: NetworkType
health: Writable<NetworkHealth>

startStatusPoll(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { ContractType } from '@core/layer-2/enums'
import { Contract } from '@core/layer-2/types'
import { ITokenBalance } from '@core/token/interfaces'
import { ChainId, NetworkNamespace, NetworkType } from '../enums'
import { EvmNetworkId, Web3Provider } from '../types'
import { EvmNetworkId, EvmNetworkType, Web3Provider } from '../types'
import { IBaseNetwork, IBaseNetworkMetadata } from './base-network.interface'
import { IBlock } from './block.interface'
import { IIscChainMetadata } from './isc-chain-metadata.interface'

export interface IIscChain extends Omit<IEvmNetwork, 'type'> {
export interface IIscChain extends IEvmNetwork {
type: NetworkType.Isc
apiEndpoint: string
aliasAddress: string
Expand All @@ -17,8 +17,8 @@ export interface IIscChain extends Omit<IEvmNetwork, 'type'> {
getMetadata(): Promise<IIscChainMetadata>
}

export interface IEvmNetwork extends Omit<IBaseNetwork, 'type'>, IBaseNetworkMetadata {
type: NetworkType.Evm
export interface IEvmNetwork extends IBaseNetwork, IBaseNetworkMetadata {
type: EvmNetworkType
id: EvmNetworkId
namespace: NetworkNamespace.Evm
chainId: ChainId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import { NetworkId } from '../types'
import { IIscChainConfiguration } from './evm-network-configuration.interface'
import { IBaseNetwork, IscChain, IStardustNetworkMetadata } from '@core/network'

export interface IStardustNetwork
extends Omit<IBaseNetwork, 'type'>,
Omit<IStardustNetworkMetadata, 'chainConfigurations'> {
export interface IStardustNetwork extends IBaseNetwork, Omit<IStardustNetworkMetadata, 'chainConfigurations'> {
type: NetworkType.Stardust
namespace: NetworkNamespace.Stardust
bech32Hrp: string
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { NetworkType } from '../enums'

export type EvmNetworkType = NetworkType.Evm | NetworkType.Isc
1 change: 1 addition & 0 deletions packages/shared/src/lib/core/network/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './evm-network.type'
export * from './network-id.type'
export * from './network-metadata.type'
export * from './network.type'
Expand Down

0 comments on commit aaa0456

Please sign in to comment.