Skip to content

Commit

Permalink
enhancement: dont await confirmation of eth transaction (#2827)
Browse files Browse the repository at this point in the history
* enhancement: dont await confirmation of eth transaction

* refactor: evmConfirmationPoll to use subscribe

* fix: supports block polling/subscription, prevents race condition

* refactor: average block time and blocks until confirmed

* pr review fixes

---------

Co-authored-by: Nicole O'Brien <[email protected]>
  • Loading branch information
jeeanribeiro and nicole-obrien authored Sep 20, 2024
1 parent 67b2f34 commit f1e6392
Show file tree
Hide file tree
Showing 21 changed files with 247 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function updateActivityByTransactionId(
export function updateActivityByActivityId(
accountIndex: number,
activityId: string,
partialBaseActivity: Partial<BaseStardustActivity>
partialBaseActivity: Partial<BaseStardustActivity | BaseEvmActivity>
): void {
allAccountActivities.update((state) => {
const activity = state[accountIndex]?.find((_activity) => _activity.id === activityId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ export async function generateBaseEvmActivity(

const subject = direction === ActivityDirection.Outgoing ? recipient : sender
const isInternal = isSubjectInternal(recipient)
const timestamp = transaction.timestamp ?? (await getTimeStamp(transaction.blockNumber, evmNetwork))
const timestamp = transaction.blockNumber
? await getTimeStamp(transaction.blockNumber, evmNetwork)
: transaction.timestamp

// For native token transfers on L2, gasUsed is 0. Therefor we fallback to the estimatedGas
// https://discord.com/channels/397872799483428865/930642258427019354/1168854453005332490
Expand Down
44 changes: 37 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,10 +1,6 @@
import { getAddressFromAccountForNetwork, IAccountState } from '@core/account'
import { IError } from '@core/error/interfaces'
import {
AVERAGE_BLOCK_TIME_IN_SECONDS,
ETHEREUM_CONFIRMATION_THRESHOLD,
NETWORK_STATUS_POLL_INTERVAL,
} from '@core/network/constants'
import { NETWORK_STATUS_POLL_INTERVAL } from '@core/network/constants'
import { getPersistedErc721NftsForNetwork, updateErc721NftsOwnership } from '@core/nfts/actions'
import { Nft } from '@core/nfts/interfaces'
import { buildNftFromPersistedErc721Nft } from '@core/nfts/utils'
Expand Down Expand Up @@ -40,8 +36,8 @@ export class EvmNetwork implements IEvmNetwork {
public readonly novesIndexerUrl: string | undefined
public readonly rpcEndpoint: string
public readonly type: EvmNetworkType = NetworkType.Evm
public readonly averageBlockTimeInSeconds: number = AVERAGE_BLOCK_TIME_IN_SECONDS
public readonly blocksUntilConfirmed: number = ETHEREUM_CONFIRMATION_THRESHOLD
public averageBlockTimeInSeconds: number | undefined
public readonly blocksUntilConfirmed: number

public health: Writable<NetworkHealth> = writable(NetworkHealth.Operational)
public statusPoll: number | undefined
Expand All @@ -59,6 +55,7 @@ export class EvmNetwork implements IEvmNetwork {
blockscoutIndexerUrl,
novesIndexerUrl,
rpcEndpoint,
blocksUntilConfirmed,
}: IBaseEvmNetworkConfiguration) {
try {
const _rpcEndpoint = new URL(rpcEndpoint).href
Expand All @@ -74,6 +71,8 @@ export class EvmNetwork implements IEvmNetwork {
this.blockscoutIndexerUrl = blockscoutIndexerUrl
this.novesIndexerUrl = novesIndexerUrl
this.rpcEndpoint = _rpcEndpoint
this.blocksUntilConfirmed = blocksUntilConfirmed
void this.setAverageBlockTime(3)

void this.startStatusPoll()
} catch (err) {
Expand All @@ -82,6 +81,37 @@ export class EvmNetwork implements IEvmNetwork {
}
}

private async setAverageBlockTime(blockCount = 10): Promise<void> {
this.averageBlockTimeInSeconds = await this.getAverageBlockTime(blockCount)
}

private async getAverageBlockTime(blockCount = 10): Promise<number | undefined> {
try {
const latestBlockNumber = await this.provider.eth.getBlockNumber()
const blocks: { timestamp: bigint }[] = []

// Fetch the latest `blockCount` blocks
for (let i = 0; i < blockCount; i++) {
const block = await this.provider.eth.getBlock(Number(latestBlockNumber - BigInt(i)))
blocks.push(block)
}

// Calculate the time differences between consecutive blocks
let totalTime = BigInt(0)
for (let i = 1; i < blocks.length; i++) {
const timeDiff = blocks[i - 1].timestamp - blocks[i].timestamp
totalTime += timeDiff
}

// Calculate the average time difference
const averageBlockTime = totalTime / BigInt(blocks.length - 1)

return Number(averageBlockTime)
} catch (error) {
console.error('Error calculating average block time:', error)
}
}

async getNftsForAccount(account: IAccountState): Promise<Nft[]> {
// ERC721 NFTs
const evmAddress = getAddressFromAccountForNetwork(account, this.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { Converter } from '@core/utils'
import { BigIntLike } from '@ethereumjs/util'
import { IIscChain, IIscChainConfiguration, IIscChainMetadata } from '../interfaces'
import { NftStandard } from '@core/nfts/enums'
import { ISC_CONFIRMATION_THRESHOLD } from '@core/network/constants'
import { IExplorerConfig } from '@auxiliary/explorer'

export class IscChain extends EvmNetwork implements IIscChain {
Expand All @@ -28,7 +27,6 @@ export class IscChain extends EvmNetwork implements IIscChain {
public readonly apiEndpoint: string
public readonly aliasAddress: string
public readonly type = NetworkType.Isc
public readonly blocksUntilConfirmed = ISC_CONFIRMATION_THRESHOLD

constructor(chainConfiguration: IIscChainConfiguration) {
const { rpcEndpoint, aliasAddress, apiEndpoint } = chainConfiguration
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const ETHEREUM_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.Ethereum],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.Ethereum],
rpcEndpoint: 'https://ethereum-rpc.publicnode.com',
blocksUntilConfirmed: 6,
}

// Ethereum L2s
Expand All @@ -41,6 +42,7 @@ export const ARBITRUM_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.Arbitrum],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.Arbitrum],
rpcEndpoint: 'https://arbitrum-one-rpc.publicnode.com',
blocksUntilConfirmed: 6,
}

export const BASE_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
Expand All @@ -54,6 +56,7 @@ export const BASE_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.Base],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.Base],
rpcEndpoint: 'https://base-rpc.publicnode.com',
blocksUntilConfirmed: 6,
}

export const BLAST_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
Expand All @@ -67,6 +70,7 @@ export const BLAST_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.Blast],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.Blast],
rpcEndpoint: 'https://blast-rpc.publicnode.com',
blocksUntilConfirmed: 6,
}

export const OPTIMISM_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
Expand All @@ -80,6 +84,7 @@ export const OPTIMISM_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.Optimism],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.Optimism],
rpcEndpoint: 'https://optimism-rpc.publicnode.com',
blocksUntilConfirmed: 6,
}

export const IMMUTABLE_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
Expand All @@ -93,6 +98,7 @@ export const IMMUTABLE_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.Immutable],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.Immutable],
rpcEndpoint: 'https://rpc.immutable.com',
blocksUntilConfirmed: 6,
}

// BNB Mainnet
Expand All @@ -107,6 +113,7 @@ export const BNB_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
coinType: DEFAULT_COIN_TYPE[SupportedNetworkId.Bnb] ?? 0,
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.Bnb],
rpcEndpoint: 'https://bsc-dataseed1.binance.org/',
blocksUntilConfirmed: 3,
}

// Ethereum Sepolia Testnet
Expand All @@ -122,6 +129,7 @@ export const SEPOLIA_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.Sepolia],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.Sepolia],
rpcEndpoint: 'https://ethereum-sepolia-rpc.publicnode.com',
blocksUntilConfirmed: 2,
}

// Ethereum L2 Testnets
Expand All @@ -137,6 +145,7 @@ export const ARBITRUM_TESTNET_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguratio
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.ArbitrumSepoliaTestnet],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.ArbitrumSepoliaTestnet],
rpcEndpoint: 'https://sepolia-rollup.arbitrum.io/rpc',
blocksUntilConfirmed: 2,
}

export const BASE_TESTNET_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
Expand All @@ -150,6 +159,7 @@ export const BASE_TESTNET_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration =
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.BaseSepoliaTestnet],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.BaseSepoliaTestnet],
rpcEndpoint: 'https://sepolia.base.org',
blocksUntilConfirmed: 2,
}

export const BLAST_TESTNET_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
Expand All @@ -163,6 +173,7 @@ export const BLAST_TESTNET_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration =
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.BlastSepoliaTestnet],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.BlastSepoliaTestnet],
rpcEndpoint: 'https://sepolia.blast.io',
blocksUntilConfirmed: 2,
}

export const OPTIMISM_TESTNET_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
Expand All @@ -176,6 +187,7 @@ export const OPTIMISM_TESTNET_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguratio
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.OptimismSepoliaTestnet],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.OptimismSepoliaTestnet],
rpcEndpoint: 'https://sepolia.optimism.io',
blocksUntilConfirmed: 2,
}

export const IMMUTABLE_TESTNET_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
Expand All @@ -189,6 +201,7 @@ export const IMMUTABLE_TESTNET_NETWORK_CONFIGURATION: IPureEvmNetworkConfigurati
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.ImmutableTestnet],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.ImmutableTestnet],
rpcEndpoint: 'https://rpc.testnet.immutable.com',
blocksUntilConfirmed: 2,
}

// BNB Testnets
Expand All @@ -203,6 +216,7 @@ export const BNB_TESTNET_NETWORK_CONFIGURATION: IPureEvmNetworkConfiguration = {
coinType: DEFAULT_COIN_TYPE[SupportedNetworkId.BnbTestnet] ?? 0,
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.BnbTestnet],
rpcEndpoint: 'https://data-seed-prebsc-1-s1.binance.org:8545',
blocksUntilConfirmed: 1,
}

export const KNOWN_EVM_MAINNET_NETWORKS_CONFIGURATIONS: Readonly<IPureEvmNetworkConfiguration[]> = [
Expand All @@ -229,6 +243,26 @@ export const KNOWN_EVM_NETWORKS_CONFIGURATIONS: Readonly<IPureEvmNetworkConfigur
...KNOWN_EVM_MAINNET_NETWORKS_CONFIGURATIONS,
...KNOWN_EVM_TESTNET_NETWORKS_CONFIGURATIONS,
]
type SupportedEvmNetworkId = keyof typeof SupportedL1EvmNetworkId | keyof typeof SupportedL2EvmNetworkId

export const DEFAULT_EVM_NETWORK_CONFIGURATION: Readonly<{
[key in SupportedEvmNetworkId]: IPureEvmNetworkConfiguration
}> = {
[SupportedL1EvmNetworkId.Ethereum]: ETHEREUM_NETWORK_CONFIGURATION,
[SupportedL2EvmNetworkId.Arbitrum]: ARBITRUM_NETWORK_CONFIGURATION,
[SupportedL2EvmNetworkId.Base]: BASE_NETWORK_CONFIGURATION,
[SupportedL2EvmNetworkId.Blast]: BLAST_NETWORK_CONFIGURATION,
[SupportedL2EvmNetworkId.Optimism]: OPTIMISM_NETWORK_CONFIGURATION,
[SupportedL2EvmNetworkId.Immutable]: IMMUTABLE_NETWORK_CONFIGURATION,
[SupportedL1EvmNetworkId.Bnb]: BNB_NETWORK_CONFIGURATION,
[SupportedL1EvmNetworkId.BnbTestnet]: BNB_TESTNET_NETWORK_CONFIGURATION,
[SupportedL1EvmNetworkId.Sepolia]: SEPOLIA_NETWORK_CONFIGURATION,
[SupportedL2EvmNetworkId.ArbitrumSepoliaTestnet]: ARBITRUM_TESTNET_NETWORK_CONFIGURATION,
[SupportedL2EvmNetworkId.BaseSepoliaTestnet]: BASE_TESTNET_NETWORK_CONFIGURATION,
[SupportedL2EvmNetworkId.BlastSepoliaTestnet]: BLAST_TESTNET_NETWORK_CONFIGURATION,
[SupportedL2EvmNetworkId.OptimismSepoliaTestnet]: OPTIMISM_TESTNET_NETWORK_CONFIGURATION,
[SupportedL2EvmNetworkId.ImmutableTestnet]: IMMUTABLE_TESTNET_NETWORK_CONFIGURATION,
}

export const DEFAULT_EVM_NETWORK_CONFIGURATIONS_FOR_STARDUST_NETWORK: Readonly<{
[key in StardustNetworkId]: IPureEvmNetworkConfiguration[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const IOTA_EVM_CHAIN_CONFIGURATION: IIscChainConfiguration = {
apiEndpoint: 'https://api.evm.iotaledger.net/',
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.IotaEvm],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.IotaEvm],
blocksUntilConfirmed: 0,
}

const SHIMMER_EVM_CHAIN_CONFIGURATION: IIscChainConfiguration = {
Expand All @@ -36,6 +37,7 @@ const SHIMMER_EVM_CHAIN_CONFIGURATION: IIscChainConfiguration = {
apiEndpoint: 'https://api.evm.shimmer.network/',
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.ShimmerEvm],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.ShimmerEvm],
blocksUntilConfirmed: 0,
}

const IOTA_TESTNET_EVM_CHAIN_CONFIGURATION: IIscChainConfiguration = {
Expand All @@ -51,6 +53,7 @@ const IOTA_TESTNET_EVM_CHAIN_CONFIGURATION: IIscChainConfiguration = {
apiEndpoint: 'https://api.evm.testnet.iotaledger.net/',
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.IotaTestnetEvm],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.IotaTestnetEvm],
blocksUntilConfirmed: 0,
}

// exported as used in tests
Expand All @@ -67,6 +70,7 @@ export const TESTNET_EVM_CHAIN_CONFIGURATION: IIscChainConfiguration = {
apiEndpoint: 'https://api.evm.testnet.shimmer.network/',
explorer: DEFAULT_EXPLORER_CONFIGS[SupportedNetworkId.TestnetEvm],
blockscoutIndexerUrl: DEFAULT_BLOCKSCOUT_INDEXER_URLS[SupportedNetworkId.TestnetEvm],
blocksUntilConfirmed: 0,
}

export const DEFAULT_ISC_CHAINS_CONFIGURATIONS: Readonly<{ [id in StardustNetworkId]?: IIscChainConfiguration }> = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const FAILED_CONFIRMATION = -1
3 changes: 1 addition & 2 deletions packages/shared/src/lib/core/network/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
* CAUTION: If this file is exported in alphabetical order, it will
* break the dependency flow. It MUST be exported first!
*/
export * from './average-block-time-in-seconds.constant'
export * from './base-token-supply-for-network.constant'
export * from './confirmation-threshold.constant'
export * from './failed-confirmation.constant'
export * from './default-coin-type.constant'
export * from './default-bech32-hrp.constant'
export * from './default-blockscout-indexer-urls.constant'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ export interface IBaseEvmNetworkConfiguration {
blockscoutIndexerUrl?: string
novesIndexerUrl?: string
rpcEndpoint: string
blocksUntilConfirmed: number
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export interface IEvmNetwork extends IBaseNetwork, IBaseNetworkMetadata {

provider: Web3Provider

averageBlockTimeInSeconds: number
averageBlockTimeInSeconds: number | undefined
blocksUntilConfirmed: number

blockscoutIndexerUrl?: string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AppStage } from '@core/app/enums'

export const PROFILE_VERSION: Record<AppStage, number> = {
[AppStage.ALPHA]: 26,
[AppStage.ALPHA]: 27,
[AppStage.BETA]: 1,
[AppStage.PROD]: 15,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { DEFAULT_EVM_NETWORK_CONFIGURATION, DEFAULT_ISC_CHAINS_CONFIGURATIONS, StardustNetworkId } from '@core/network'
import { IPersistedProfile } from '@core/profile/interfaces'

export function alphaProfileMigration26To27(existingProfile: unknown): Promise<void> {
const profile = existingProfile as IPersistedProfile & {
network: {
id: StardustNetworkId
}
}

profile.network.chainConfigurations.forEach((chainConfiguration) => {
chainConfiguration.blocksUntilConfirmed =
DEFAULT_ISC_CHAINS_CONFIGURATIONS[profile.network.id]?.blocksUntilConfirmed ?? 0
})

profile.evmNetworks.forEach((evmNetwork) => {
evmNetwork.blocksUntilConfirmed = DEFAULT_EVM_NETWORK_CONFIGURATION[evmNetwork.id]?.blocksUntilConfirmed ?? 0
})

return Promise.resolve()
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { alphaProfileMigration22To23 } from './alpha-profile-migration-22-to-23'
import { alphaProfileMigration23To24 } from './alpha-profile-migration-23-to-24'
import { alphaProfileMigration24To25 } from './alpha-profile-migration-24-to-25'
import { alphaProfileMigration25To26 } from './alpha-profile-migration-25-to-26'
import { alphaProfileMigration26To27 } from './alpha-profile-migration-26-to-27'
import { alphaProfileMigration3To4 } from './alpha-profile-migration-3-to-4'
import { alphaProfileMigration4To5 } from './alpha-profile-migration-4-to-5'
import { alphaProfileMigration5To6 } from './alpha-profile-migration-5-to-6'
Expand Down Expand Up @@ -59,4 +60,5 @@ export const ALPHA_PROFILE_MIGRATION_MAP: ProfileMigrationMap = {
// ^^^ release 1.1.3 ^^^
24: alphaProfileMigration24To25,
25: alphaProfileMigration25To26,
26: alphaProfileMigration26To27,
}
Loading

0 comments on commit f1e6392

Please sign in to comment.