From cf7b9594305eafd53436063c0b32002f787bb276 Mon Sep 17 00:00:00 2001 From: Lukas Kotol Date: Mon, 22 Jan 2024 17:16:03 +0100 Subject: [PATCH] ALL-4357 Add Holesky testnet subscription --- CHANGELOG.md | 6 + package.json | 2 +- src/connector/tatum.connector.ts | 14 +- src/dto/Currency.ts | 44 +- src/dto/Network.ts | 504 ++++++++++++++++++- src/e2e/e2e.constant.ts | 11 + src/e2e/e2e.util.ts | 3 +- src/e2e/rpc/evm/eth/tatum.rpc.beacon.spec.ts | 2 +- src/e2e/rpc/evm/evm.e2e.utils.ts | 12 +- src/e2e/rpc/evm/evm.rpc.spec.ts | 57 +-- src/e2e/tatum.notification.spec.ts | 22 + src/e2e/tatum.spec.ts | 15 +- src/service/notification/subscribe.ts | 6 +- src/util/constant.ts | 51 -- src/util/index.ts | 1 - src/util/network.utils.spec.ts | 39 ++ src/util/network.utils.ts | 21 + src/util/tatum.utils.ts | 30 -- src/util/util.shared.ts | 1 + 19 files changed, 694 insertions(+), 147 deletions(-) create mode 100644 src/util/network.utils.spec.ts create mode 100644 src/util/network.utils.ts delete mode 100644 src/util/tatum.utils.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f892fc6d0..343279c9d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [4.2.5] - 2024.1.31 + +### Added + +- Added support for Holesky Ethereum testnet for subscriptions. + ## [4.2.4] - 2024.1.25 ### Fixed diff --git a/package.json b/package.json index f0034c2888..b33d5181d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tatumio/tatum", - "version": "4.2.4", + "version": "4.2.5", "description": "Tatum JS SDK", "author": "Tatum", "repository": "https://github.com/tatumio/tatum-js", diff --git a/src/connector/tatum.connector.ts b/src/connector/tatum.connector.ts index 23a1015010..05fc0c2835 100644 --- a/src/connector/tatum.connector.ts +++ b/src/connector/tatum.connector.ts @@ -1,3 +1,4 @@ +import process from 'process' import { Container, Service } from 'typedi' import { JsonRpcCall } from '../dto' import { ApiVersion } from '../service' @@ -134,16 +135,21 @@ export class TatumConnector { } } + private getBaseUrl() { + const config = Container.of(this.id).get(CONFIG) + if (process.env.TATUM_URL) { + return process.env.TATUM_URL + } + return config.version === ApiVersion.V3 ? Constant.TATUM_API_URL.V3 : Constant.TATUM_API_URL.V4 + } + private getUrl({ path, params, basePath, }: GetUrl) { const config = Container.of(this.id).get(CONFIG) - const url = new URL( - path || '', - basePath || (config.version === ApiVersion.V3 ? Constant.TATUM_API_URL.V3 : Constant.TATUM_API_URL.V4), - ) + const url = new URL(path || '', basePath || this.getBaseUrl()) if (params) { Object.keys(params) diff --git a/src/dto/Currency.ts b/src/dto/Currency.ts index 458e42a2ba..d0c5b05891 100644 --- a/src/dto/Currency.ts +++ b/src/dto/Currency.ts @@ -2,9 +2,51 @@ import { Network } from './Network' export enum Currency { ETH = 'ETH', + SOL = 'SOL', + XRP = 'XRP', + MATIC = 'MATIC', + CELO = 'CELO', + KLAY = 'KLAY', BTC = 'BTC', - DOGE = 'DOGE', LTC = 'LTC', + BCH = 'BCH', + DOGE = 'DOGE', + TRON = 'TRON', + BSC = 'BSC', + TEZOS = 'TEZOS', + EON = 'EON', + CHZ = 'CHZ', + ALGO = 'ALGO', + ADA = 'ADA', + VET = 'VET', + FLOW = 'FLOW', + XDC = 'XDC', + XLM = 'XLM', + BNB = 'BNB', + ONE = 'ONE', + EOS = 'EOS', + AVAX = 'AVAX', + FTM = 'FTM', + ARB = 'ARB', + OP = 'OP', + NEAR = 'NEAR', + RSK = 'RSK', + AURORA = 'AURORA', + XOS = 'XOS', + ZCASH = 'ZCASH', + ZEC = 'ZEC', + PALM = 'PALM', + ZIL = 'ZIL', + ETC = 'ETC', + FLR = 'FLR', + SGB = 'SGB', + ISLM = 'ISLM', + ZEN = 'ZEN', + GNO = 'GNO', + CRO = 'CRO', + KCS = 'KCS', + EGLD = 'EGLD', + DOT = 'DOT', } export function networkToCurrency(network: Network): Currency { diff --git a/src/dto/Network.ts b/src/dto/Network.ts index 8b39f4a2c5..9fe11f0728 100644 --- a/src/dto/Network.ts +++ b/src/dto/Network.ts @@ -1,3 +1,5 @@ +import { Currency } from './Currency' + export enum Network { // Mainnets ALGORAND_ALGOD = 'algorand-mainnet-algod', @@ -345,13 +347,13 @@ export const isSameGetBlockNetwork = (network: Network) => export enum MappedNetwork { HORIZEN_EON = 'horizen-eon-mainnet', - DOGECOIN_MAINNET = 'dogecoin-mainnet', + DOGECOIN = 'dogecoin-mainnet', DOGECOIN_TESTNET = 'dogecoin-testnet', } export const MAPPED_NETWORK = { [Network.HORIZEN_EON]: MappedNetwork.HORIZEN_EON, - [Network.DOGECOIN]: MappedNetwork.DOGECOIN_MAINNET, + [Network.DOGECOIN]: MappedNetwork.DOGECOIN, [Network.DOGECOIN_TESTNET]: MappedNetwork.DOGECOIN_TESTNET, } @@ -359,3 +361,501 @@ export const NATIVE_PREFIX_MAPPING: { [key: string]: string } = { [Network.KLAYTN]: 'klay_', [Network.KLAYTN_BAOBAB]: 'klay_', } + +/** + * Describes additional info about every chain in a system. + * @param testnet - If true - chain is testnet. + * @param currency - Currency of the chain. + * @param alternativeCurrencies - Alternative currencies of the chain, for case we have few currencies meaning the same chain. + * @param defaultTestnet - If true - this chain is default testnet among others for this currency. + * @param defaultMainnet - If true - this chain is default mainnet among others for this currency. + * @param chainId - Network id. + */ +export type NetworkMetadata = { + testnet: boolean + currency: Currency + alternativeCurrencies?: Currency[] + defaultTestnet?: boolean + defaultMainnet?: boolean + chainId?: number +} + +export const NETWORK_METADATA: Record = { + [Network.ETHEREUM_SEPOLIA]: { + currency: Currency.ETH, + testnet: true, + defaultTestnet: true, + chainId: 11155111, + }, + [Network.ETHEREUM_HOLESKY]: { + currency: Currency.ETH, + testnet: true, + chainId: 17000, + }, + [Network.ETHEREUM]: { + currency: Currency.ETH, + testnet: false, + defaultMainnet: true, + chainId: 1, + }, + [Network.ETHEREUM_GOERLI]: { + currency: Currency.ETH, + testnet: true, + chainId: 5, + }, + [Network.POLYGON_MUMBAI]: { + currency: Currency.MATIC, + testnet: true, + defaultTestnet: true, + chainId: 80001, + }, + [Network.POLYGON]: { + currency: Currency.MATIC, + testnet: false, + defaultMainnet: true, + chainId: 137, + }, + [Network.KLAYTN_BAOBAB]: { + currency: Currency.KLAY, + testnet: true, + defaultTestnet: true, + chainId: 1001, + }, + [Network.KLAYTN]: { + currency: Currency.KLAY, + testnet: false, + defaultMainnet: true, + chainId: 8217, + }, + [Network.SOLANA_DEVNET]: { + currency: Currency.SOL, + testnet: true, + defaultTestnet: true, + }, + [Network.SOLANA]: { + currency: Currency.SOL, + testnet: false, + defaultMainnet: true, + }, + [Network.CELO]: { + currency: Currency.CELO, + testnet: false, + chainId: 42220, + }, + [Network.CELO_ALFAJORES]: { + currency: Currency.CELO, + testnet: true, + defaultTestnet: true, + chainId: 44787, + }, + [Network.ALGORAND_ALGOD_TESTNET]: { + currency: Currency.ALGO, + testnet: true, + defaultTestnet: true, + }, + [Network.ALGORAND_ALGOD]: { + currency: Currency.ALGO, + testnet: false, + defaultMainnet: true, + }, + [Network.ALGORAND_INDEXER_TESTNET]: { + currency: Currency.ALGO, + testnet: true, + }, + [Network.ALGORAND_INDEXER]: { + currency: Currency.ALGO, + testnet: false, + }, + [Network.BITCOIN]: { + currency: Currency.BTC, + testnet: false, + }, + [Network.BITCOIN_TESTNET]: { + currency: Currency.BTC, + testnet: true, + defaultTestnet: true, + }, + [Network.LITECOIN]: { + currency: Currency.LTC, + testnet: false, + }, + [Network.LITECOIN_TESTNET]: { + currency: Currency.LTC, + testnet: true, + }, + [Network.CARDANO_ROSETTA]: { + currency: Currency.ADA, + testnet: false, + defaultMainnet: true, + }, + [Network.CARDANO_ROSETTA_PREPROD]: { + currency: Currency.ADA, + testnet: true, + defaultTestnet: true, + }, + [Network.VECHAIN_TESTNET]: { + currency: Currency.VET, + testnet: true, + defaultTestnet: true, + }, + [Network.VECHAIN]: { + currency: Currency.VET, + testnet: false, + }, + [Network.XRP]: { + currency: Currency.XRP, + testnet: false, + }, + [Network.XRP_TESTNET]: { + currency: Currency.XRP, + testnet: true, + defaultTestnet: true, + }, + [Network.FLOW]: { + currency: Currency.FLOW, + testnet: false, + }, + [Network.FLOW_TESTNET]: { + currency: Currency.FLOW, + testnet: true, + defaultTestnet: true, + }, + [Network.XINFIN]: { + currency: Currency.XDC, + testnet: false, + chainId: 50, + }, + [Network.XINFIN_TESTNET]: { + currency: Currency.XDC, + testnet: true, + defaultTestnet: true, + chainId: 51, + }, + [Network.TRON]: { + currency: Currency.TRON, + testnet: false, + chainId: 728126428, + }, + [Network.TRON_SHASTA]: { + currency: Currency.TRON, + testnet: true, + defaultTestnet: true, + chainId: 2494104990, + }, + [Network.BINANCE_SMART_CHAIN]: { + currency: Currency.BSC, + testnet: false, + defaultMainnet: true, + chainId: 56, + }, + [Network.BINANCE_SMART_CHAIN_TESTNET]: { + currency: Currency.BSC, + testnet: true, + defaultTestnet: true, + chainId: 97, + }, + [Network.BITCOIN_CASH]: { + currency: Currency.BCH, + testnet: false, + }, + [Network.BITCOIN_CASH_TESTNET]: { + currency: Currency.BCH, + testnet: true, + defaultTestnet: true, + }, + [Network.STELLAR]: { + currency: Currency.XLM, + testnet: false, + }, + [Network.STELLAR_TESTNET]: { + currency: Currency.XLM, + testnet: true, + defaultTestnet: true, + }, + [Network.BNB]: { + currency: Currency.BNB, + testnet: false, + defaultMainnet: true, + }, + [Network.DOGECOIN]: { + currency: Currency.DOGE, + testnet: false, + }, + [Network.DOGECOIN_TESTNET]: { + currency: Currency.DOGE, + testnet: true, + defaultTestnet: true, + }, + [Network.HARMONY_ONE_SHARD_0]: { + currency: Currency.ONE, + testnet: false, + chainId: 1666600000, + }, + [Network.HARMONY_ONE_TESTNET_SHARD_0]: { + currency: Currency.ONE, + testnet: true, + defaultTestnet: true, + chainId: 1666700000, + }, + [Network.EOS]: { + currency: Currency.EOS, + testnet: false, + defaultMainnet: true, + }, + [Network.EOS_TESTNET]: { + currency: Currency.EOS, + testnet: true, + defaultTestnet: true, + }, + [Network.AVALANCHE_C]: { + currency: Currency.AVAX, + testnet: false, + defaultMainnet: true, + chainId: 43114, + }, + [Network.AVALANCHE_C_TESTNET]: { + currency: Currency.AVAX, + testnet: true, + defaultTestnet: true, + chainId: 43113, + }, + [Network.AVALANCHE_X]: { + currency: Currency.AVAX, + testnet: false, + }, + [Network.AVALANCHE_X_TESTNET]: { + currency: Currency.AVAX, + testnet: true, + }, + [Network.AVALANCHE_P]: { + currency: Currency.AVAX, + testnet: false, + }, + [Network.AVALANCHE_P_TESTNET]: { + currency: Currency.AVAX, + testnet: true, + }, + [Network.FANTOM]: { + currency: Currency.FTM, + testnet: false, + chainId: 250, + }, + [Network.FANTOM_TESTNET]: { + currency: Currency.FTM, + testnet: true, + defaultTestnet: true, + chainId: 4002, + }, + [Network.ARBITRUM_NOVA]: { + currency: Currency.ARB, + testnet: false, + defaultMainnet: true, + chainId: 42170, + }, + [Network.ARBITRUM_NOVA_TESTNET]: { + currency: Currency.ARB, + testnet: true, + defaultTestnet: true, + chainId: 421613, + }, + [Network.ARBITRUM_ONE]: { + currency: Currency.ARB, + testnet: false, + chainId: 42161, + }, + [Network.OPTIMISM]: { + currency: Currency.OP, + testnet: false, + defaultMainnet: true, + chainId: 10, + }, + [Network.OPTIMISM_TESTNET]: { + currency: Currency.OP, + testnet: true, + defaultTestnet: true, + }, + [Network.NEAR]: { + currency: Currency.NEAR, + testnet: false, + }, + [Network.NEAR_TESTNET]: { + currency: Currency.NEAR, + testnet: true, + defaultTestnet: true, + }, + [Network.RSK]: { + currency: Currency.RSK, + testnet: false, + }, + [Network.RSK_TESTNET]: { + currency: Currency.RSK, + testnet: true, + defaultTestnet: true, + }, + [Network.AURORA]: { + currency: Currency.AURORA, + testnet: false, + chainId: 1313161554, + }, + [Network.AURORA_TESTNET]: { + currency: Currency.AURORA, + testnet: true, + defaultTestnet: true, + chainId: 1313161555, + }, + [Network.OASIS]: { + currency: Currency.XOS, + testnet: false, + chainId: 42262, + }, + [Network.OASIS_TESTNET]: { + currency: Currency.XOS, + testnet: true, + defaultTestnet: true, + chainId: 42261, + }, + [Network.TEZOS]: { + currency: Currency.TEZOS, + testnet: false, + defaultMainnet: true, + }, + [Network.TEZOS_TESTNET]: { + currency: Currency.TEZOS, + testnet: true, + defaultTestnet: true, + }, + [Network.ZCASH]: { + currency: Currency.ZCASH, + alternativeCurrencies: [Currency.ZEC], + testnet: false, + }, + [Network.ZCASH_TESTNET]: { + currency: Currency.ZCASH, + alternativeCurrencies: [Currency.ZEC], + testnet: true, + defaultTestnet: true, + }, + [Network.PALM]: { + currency: Currency.PALM, + testnet: false, + }, + [Network.PALM_TESTNET]: { + currency: Currency.PALM, + testnet: true, + defaultTestnet: true, + }, + [Network.ZILLIQA]: { + currency: Currency.ZIL, + testnet: false, + }, + [Network.ZILLIQA_TESTNET]: { + currency: Currency.ZIL, + testnet: true, + defaultTestnet: true, + }, + [Network.ETHEREUM_CLASSIC]: { + currency: Currency.ETC, + testnet: false, + defaultMainnet: true, + chainId: 61, + }, + [Network.FLARE]: { + currency: Currency.FLR, + testnet: false, + chainId: 14, + }, + [Network.FLARE_COSTON_2]: { + currency: Currency.FLR, + testnet: true, + defaultTestnet: true, + chainId: 114, + }, + [Network.FLARE_SONGBIRD]: { + currency: Currency.SGB, + testnet: false, + chainId: 19, + }, + [Network.FLARE_COSTON]: { + currency: Currency.SGB, + testnet: true, + defaultTestnet: true, + chainId: 16, + }, + [Network.HAQQ]: { + currency: Currency.ISLM, + testnet: false, + chainId: 11235, + }, + [Network.HAQQ_TESTNET]: { + currency: Currency.ISLM, + testnet: true, + defaultTestnet: true, + chainId: 54211, + }, + [Network.HORIZEN_EON]: { + currency: Currency.ZEN, + testnet: false, + chainId: 7332, + }, + [Network.HORIZEN_EON_GOBI]: { + currency: Currency.ZEN, + testnet: true, + defaultTestnet: true, + chainId: 1663, + }, + [Network.CHILIZ]: { + currency: Currency.CHZ, + testnet: false, + chainId: 88888, + }, + [Network.GNOSIS]: { + currency: Currency.GNO, + testnet: false, + chainId: 100, + }, + [Network.GNOSIS_TESTNET]: { + currency: Currency.GNO, + testnet: true, + chainId: 69, + }, + [Network.CRONOS]: { + currency: Currency.CRO, + testnet: false, + chainId: 25, + }, + [Network.CRONOS_TESTNET]: { + currency: Currency.CRO, + testnet: true, + chainId: 338, + }, + [Network.KUCOIN]: { + currency: Currency.KCS, + testnet: false, + chainId: 321, + }, + [Network.KUCOIN_TESTNET]: { + currency: Currency.KCS, + testnet: true, + chainId: 322, + }, + [Network.MULTIVERSX]: { + currency: Currency.EGLD, + testnet: false, + chainId: 1, + }, + [Network.MULTIVERSX_TESTNET]: { + currency: Currency.EGLD, + testnet: true, + chainId: 2, + }, + [Network.POLKADOT]: { + currency: Currency.DOT, + testnet: false, + chainId: 0, + }, + [Network.POLKADOT_TESTNET]: { + currency: Currency.DOT, + testnet: true, + chainId: 0, + }, +} diff --git a/src/e2e/e2e.constant.ts b/src/e2e/e2e.constant.ts index 91db0c4941..1b81ae87e9 100644 --- a/src/e2e/e2e.constant.ts +++ b/src/e2e/e2e.constant.ts @@ -16,6 +16,7 @@ export const AddressEventNetworks = [ Network.DOGECOIN_TESTNET, Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.POLYGON, Network.POLYGON_MUMBAI, Network.CELO, @@ -42,6 +43,7 @@ export const IncomingNativeTxNetworks = [ Network.DOGECOIN_TESTNET, Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.POLYGON, Network.POLYGON_MUMBAI, Network.CELO, @@ -68,6 +70,7 @@ export const OutgoingNativeTxNetworks = [ Network.LITECOIN_TESTNET, Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.POLYGON, Network.POLYGON_MUMBAI, Network.CELO, @@ -90,6 +93,7 @@ export const OutgoingNativeTxNetworks = [ export const OutgoingFailedNetworks = [ Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.POLYGON, Network.POLYGON_MUMBAI, Network.CELO, @@ -104,6 +108,7 @@ export const OutgoingFailedNetworks = [ export const PaidFeeNetworks = [ Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.POLYGON, Network.POLYGON_MUMBAI, Network.CELO, @@ -122,6 +127,7 @@ export const PaidFeeNetworks = [ export const FungibleTxNetworks = [ Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.POLYGON, Network.POLYGON_MUMBAI, Network.CELO, @@ -140,6 +146,7 @@ export const FungibleTxNetworks = [ export const NftNetworks = [ Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.POLYGON, Network.POLYGON_MUMBAI, Network.CELO, @@ -158,6 +165,7 @@ export const NftNetworks = [ export const MultitokenNetworks = [ Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.POLYGON, Network.POLYGON_MUMBAI, Network.CELO, @@ -171,6 +179,7 @@ export const MultitokenNetworks = [ export const FailedTxPerBlockNetworks = [ Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.POLYGON, Network.POLYGON_MUMBAI, Network.CELO, @@ -189,6 +198,7 @@ export const FailedTxPerBlockNetworks = [ export const ContractAddressLogEventNetworks = [ Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.POLYGON, Network.POLYGON_MUMBAI, Network.CELO, @@ -202,6 +212,7 @@ export const ContractAddressLogEventNetworks = [ export const InternalTxNetworks = [ Network.ETHEREUM, Network.ETHEREUM_SEPOLIA, + Network.ETHEREUM_HOLESKY, Network.CELO, Network.CELO_ALFAJORES, Network.TEZOS, diff --git a/src/e2e/e2e.util.ts b/src/e2e/e2e.util.ts index 111d9052d5..e3fb9edbb2 100644 --- a/src/e2e/e2e.util.ts +++ b/src/e2e/e2e.util.ts @@ -15,6 +15,7 @@ export const e2eUtil = { getAddress: (network: Network): string => { switch (network) { case Network.ETHEREUM_SEPOLIA: + case Network.ETHEREUM_HOLESKY: return '0xdb4C3b4350EE869F2D0a2F43ce0292865E2Aa149' case Network.CELO_ALFAJORES: return '0xdf083B077F1FD890fC71feCaBbd3F68F94cD21Bf' @@ -80,7 +81,7 @@ export const e2eUtil = { address, }) if (error) { - console.log(error) + await tatum.destroy() throw new Error(error.message.join(',')) } diff --git a/src/e2e/rpc/evm/eth/tatum.rpc.beacon.spec.ts b/src/e2e/rpc/evm/eth/tatum.rpc.beacon.spec.ts index dc2a4e77bd..2c98efe53e 100644 --- a/src/e2e/rpc/evm/eth/tatum.rpc.beacon.spec.ts +++ b/src/e2e/rpc/evm/eth/tatum.rpc.beacon.spec.ts @@ -23,7 +23,7 @@ describe('Beacon', () => { it('should get block headers', async () => { const tatum = await EvmE2eUtils.initTatum(network, process.env.V4_API_KEY_TESTNET) - const { data } = await tatum.rpc.beacon.v1.getBlockHeaders({ slot: '1' }) + const { data } = await tatum.rpc.beacon.v1.getBlockHeaders({ slot: '1000' }) await tatum.destroy() expect(data).toBeDefined() }) diff --git a/src/e2e/rpc/evm/evm.e2e.utils.ts b/src/e2e/rpc/evm/evm.e2e.utils.ts index 5c9a80aa8f..648d0e71d0 100644 --- a/src/e2e/rpc/evm/evm.e2e.utils.ts +++ b/src/e2e/rpc/evm/evm.e2e.utils.ts @@ -1,14 +1,12 @@ import { BigNumber } from 'bignumber.js' import { Network } from '../../../dto' import { BaseEvm, TatumSDK } from '../../../service' +import { NetworkUtils } from '../../../util/network.utils' import { RpcE2eUtils } from '../rpc.e2e.utils' -interface evmE2eI { +interface EvmE2eI { network: Network apiKey?: string - expected: { - chainId: number - } data?: { estimateGas?: any } @@ -18,8 +16,8 @@ interface evmE2eI { export const EvmE2eUtils = { initTatum: async (network: Network, apiKey?: string) => TatumSDK.init(RpcE2eUtils.initConfig(network, apiKey)), - e2e: (evmE2eI: evmE2eI) => { - const { network, expected, data, skipEstimateGas, apiKey } = evmE2eI + e2e: (evmE2eI: EvmE2eI) => { + const { network, data, skipEstimateGas, apiKey } = evmE2eI it('eth_blockNumber', async () => { const tatum = await EvmE2eUtils.initTatum(network, apiKey) const { result } = await tatum.rpc.blockNumber() @@ -33,7 +31,7 @@ export const EvmE2eUtils = { const { result } = await tatum.rpc.chainId() tatum.rpc.destroy() - expect(result?.toNumber()).toBe(expected.chainId) + expect(result?.toNumber()).toBe(NetworkUtils.getChainId(network)) }) if (!skipEstimateGas) { diff --git a/src/e2e/rpc/evm/evm.rpc.spec.ts b/src/e2e/rpc/evm/evm.rpc.spec.ts index 5ec87baf1c..2d85650f0a 100644 --- a/src/e2e/rpc/evm/evm.rpc.spec.ts +++ b/src/e2e/rpc/evm/evm.rpc.spec.ts @@ -2,43 +2,40 @@ import { Network } from '../../../dto' import { EvmE2eUtils } from './evm.e2e.utils' const testNetworks = [ - { network: Network.CELO, expected: { chainId: 42220 } }, - { network: Network.CELO_ALFAJORES, expected: { chainId: 44787 } }, - { network: Network.ARBITRUM_ONE, expected: { chainId: 42161 } }, - { network: Network.ARBITRUM_NOVA, expected: { chainId: 42170 }, apiKey: process.env.V3_API_KEY_MAINNET }, + { network: Network.CELO }, + { network: Network.CELO_ALFAJORES }, + { network: Network.ARBITRUM_ONE }, + { network: Network.ARBITRUM_NOVA, apiKey: process.env.V3_API_KEY_MAINNET }, { network: Network.ARBITRUM_NOVA_TESTNET, - expected: { chainId: 421613 }, apiKey: process.env.V3_API_KEY_TESTNET, }, - { network: Network.HORIZEN_EON, expected: { chainId: 7332 } }, - { network: Network.HORIZEN_EON_GOBI, expected: { chainId: 1663 } }, - { network: Network.CHILIZ, expected: { chainId: 88888 } }, - { network: Network.BINANCE_SMART_CHAIN, expected: { chainId: 56 } }, + { network: Network.HORIZEN_EON }, + { network: Network.HORIZEN_EON_GOBI }, + { network: Network.CHILIZ }, + { network: Network.BINANCE_SMART_CHAIN }, { network: Network.BINANCE_SMART_CHAIN_TESTNET, - expected: { chainId: 97 }, apiKey: process.env.V3_API_KEY_TESTNET, }, - { network: Network.FLARE, expected: { chainId: 14 } }, - { network: Network.FLARE_SONGBIRD, expected: { chainId: 19 } }, - { network: Network.FLARE_COSTON, expected: { chainId: 16 } }, - { network: Network.FLARE_COSTON_2, expected: { chainId: 114 } }, - { network: Network.ETHEREUM, expected: { chainId: 1 } }, - { network: Network.ETHEREUM_SEPOLIA, expected: { chainId: 11155111 } }, - { network: Network.ETHEREUM_HOLESKY, expected: { chainId: 17000 } }, - { network: Network.ETHEREUM_GOERLI, expected: { chainId: 5 }, apiKey: process.env.V3_API_KEY_TESTNET }, - { network: Network.FANTOM, expected: { chainId: 250 }, apiKey: process.env.V3_API_KEY_MAINNET }, - { network: Network.FANTOM_TESTNET, expected: { chainId: 4002 }, apiKey: process.env.V3_API_KEY_TESTNET }, - { network: Network.ETHEREUM_CLASSIC, expected: { chainId: 61 } }, - { network: Network.POLYGON, expected: { chainId: 137 } }, - { network: Network.POLYGON_MUMBAI, expected: { chainId: 80001 } }, - // { network: Network.OPTIMISM, expected: { chainId: 10 } }, - { network: Network.HAQQ, expected: { chainId: 11235 } }, - { network: Network.HAQQ_TESTNET, expected: { chainId: 54211 } }, + { network: Network.FLARE }, + { network: Network.FLARE_SONGBIRD }, + { network: Network.FLARE_COSTON }, + { network: Network.FLARE_COSTON_2 }, + { network: Network.ETHEREUM }, + { network: Network.ETHEREUM_SEPOLIA }, + { network: Network.ETHEREUM_HOLESKY }, + { network: Network.ETHEREUM_GOERLI, apiKey: process.env.V3_API_KEY_TESTNET }, + { network: Network.FANTOM, apiKey: process.env.V3_API_KEY_MAINNET }, + { network: Network.FANTOM_TESTNET, apiKey: process.env.V3_API_KEY_TESTNET }, + { network: Network.ETHEREUM_CLASSIC }, + { network: Network.POLYGON }, + { network: Network.POLYGON_MUMBAI }, + // { network: Network.OPTIMISM }, + { network: Network.HAQQ }, + { network: Network.HAQQ_TESTNET }, { network: Network.TRON, - expected: { chainId: 728126428 }, data: { estimateGas: { from: '0x41F0CC5A2A84CD0F68ED1667070934542D673ACBD8', @@ -52,31 +49,25 @@ const testNetworks = [ }, { network: Network.TRON_SHASTA, - expected: { chainId: 2494104990 }, skipEstimateGas: true, apiKey: process.env.V3_API_KEY_TESTNET, }, { network: Network.KLAYTN, - expected: { chainId: 8217 }, }, { network: Network.KLAYTN_BAOBAB, - expected: { chainId: 1001 }, apiKey: process.env.V4_API_KEY_TESTNET, }, { network: Network.AVALANCHE_C, - expected: { chainId: 43114 }, }, { network: Network.AVALANCHE_C_TESTNET, - expected: { chainId: 43113 }, apiKey: process.env.V3_API_KEY_TESTNET, }, { network: Network.XINFIN, - expected: { chainId: 50 }, }, ] diff --git a/src/e2e/tatum.notification.spec.ts b/src/e2e/tatum.notification.spec.ts index 06deedd3b7..627f05c0b0 100644 --- a/src/e2e/tatum.notification.spec.ts +++ b/src/e2e/tatum.notification.spec.ts @@ -24,6 +24,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network: Network.ETHEREUM, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -45,6 +46,7 @@ describe.skip('notification', () => { network, retryCount: 10, retryDelay: 5000, + verbose: e2eUtil.isVerbose, apiKey: { v4: process.env.V4_API_KEY_MAINNET, }, @@ -62,6 +64,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -80,6 +83,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -97,6 +101,7 @@ describe.skip('notification', () => { it.each(Object.values(OutgoingFailedNetworks))('OK %s', async (network: Network) => { const tatum = await TatumSDK.init({ network, + verbose: e2eUtil.isVerbose, retryCount: 10, retryDelay: 5000, apiKey: { @@ -116,6 +121,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -134,6 +140,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -151,6 +158,7 @@ describe.skip('notification', () => { it.each(Object.values(InternalTxNetworks))('OK %s', async (network: Network) => { const tatum = await TatumSDK.init({ network, + verbose: e2eUtil.isVerbose, retryCount: 10, retryDelay: 5000, apiKey: { @@ -170,6 +178,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -189,6 +198,7 @@ describe.skip('notification', () => { network, retryCount: 10, retryDelay: 5000, + verbose: e2eUtil.isVerbose, apiKey: { v4: process.env.V4_API_KEY_MAINNET, }, @@ -205,6 +215,7 @@ describe.skip('notification', () => { it.each(Object.values(NftNetworks))('OK %s', async (network: Network) => { const tatum = await TatumSDK.init({ network, + verbose: e2eUtil.isVerbose, retryCount: 10, retryDelay: 5000, apiKey: { @@ -225,6 +236,7 @@ describe.skip('notification', () => { network, retryCount: 10, retryDelay: 5000, + verbose: e2eUtil.isVerbose, apiKey: { v4: process.env.V4_API_KEY_MAINNET, }, @@ -242,6 +254,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -260,6 +273,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -279,6 +293,7 @@ describe.skip('notification', () => { network, retryCount: 10, retryDelay: 5000, + verbose: e2eUtil.isVerbose, apiKey: { v4: process.env.V4_API_KEY_MAINNET, }, @@ -295,6 +310,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -313,6 +329,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network: Network.ETHEREUM, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -340,6 +357,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network: Network.ETHEREUM, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -364,6 +382,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network: Network.ETHEREUM_SEPOLIA, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -388,6 +407,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network: Network.ETHEREUM_SEPOLIA, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -407,6 +427,7 @@ describe.skip('notification', () => { const tatum = await TatumSDK.init({ network: Network.ETHEREUM, retryCount: 10, + verbose: e2eUtil.isVerbose, retryDelay: 5000, apiKey: { v4: process.env.V4_API_KEY_MAINNET, @@ -429,6 +450,7 @@ describe.skip('notification', () => { network: Network.ETHEREUM_SEPOLIA, retryCount: 10, retryDelay: 5000, + verbose: e2eUtil.isVerbose, apiKey: { v4: process.env.V4_API_KEY_MAINNET, }, diff --git a/src/e2e/tatum.spec.ts b/src/e2e/tatum.spec.ts index f77c8b337e..ef6938dbfc 100644 --- a/src/e2e/tatum.spec.ts +++ b/src/e2e/tatum.spec.ts @@ -1,6 +1,5 @@ -import { EVM_BASED_NETWORKS, Network } from '../dto' +import { Network } from '../dto' import { Bitcoin, TatumSDK } from '../service' -import { TatumUtils } from '../util' describe('Tatum Init', () => { describe('IP auth', () => { @@ -43,15 +42,3 @@ describe('Tatum Init', () => { }) }) }) -describe('Network to chainId mapping check', () => { - const networks = Object.values(EVM_BASED_NETWORKS) - - for (const network of networks) { - it(`${network} should have chainId mapped`, async () => { - const chainId = TatumUtils.getChainId(network) - - expect(chainId).toBeGreaterThan(0) - expect(TatumUtils.getNetwork(chainId)).toBe(network) - }) - } -}) diff --git a/src/service/notification/subscribe.ts b/src/service/notification/subscribe.ts index 7fb8654b85..21c7f977ec 100644 --- a/src/service/notification/subscribe.ts +++ b/src/service/notification/subscribe.ts @@ -2,6 +2,7 @@ import { Container, Service } from 'typedi' import { TatumConnector } from '../../connector/tatum.connector' import { IdDto } from '../../dto' import { CONFIG, ErrorUtils, ResponseDto, Utils } from '../../util' +import { NetworkUtils } from '../../util/network.utils' import { TatumConfig } from '../tatum' import { AddressBasedNotification, @@ -34,8 +35,11 @@ export class Subscribe { ): Promise> { return ErrorUtils.tryFail(async () => { const chain = Utils.mapNetworkToNotificationChain(this.config.network) + const path = NetworkUtils.isAlternateTestnet(this.config.network) + ? `subscription?testnetType=${this.config.network}` + : 'subscription' const { id } = await this.connector.post({ - path: 'subscription', + path, body: { type: type, attr: { diff --git a/src/util/constant.ts b/src/util/constant.ts index ece1f47634..f692087103 100644 --- a/src/util/constant.ts +++ b/src/util/constant.ts @@ -6,57 +6,6 @@ export const Constant = { V4: 'https://api.tatum.io/v4/', }, NETWORK: { - ChainId: { - [Network.ETHEREUM]: 1, - [Network.ETHEREUM_SEPOLIA]: 11155111, - [Network.ETHEREUM_CLASSIC]: 61, - [Network.ETHEREUM_GOERLI]: 5, - [Network.ETHEREUM_HOLESKY]: 17000, - [Network.AVALANCHE_C]: 43114, - [Network.AVALANCHE_C_TESTNET]: 43113, - [Network.POLYGON]: 137, - [Network.POLYGON_MUMBAI]: 80001, - [Network.GNOSIS]: 100, - [Network.FANTOM]: 250, - [Network.FANTOM_TESTNET]: 4002, - [Network.AURORA]: 1313161554, - [Network.AURORA_TESTNET]: 1313161555, - [Network.CELO]: 42220, - [Network.CELO_ALFAJORES]: 44787, - [Network.BINANCE_SMART_CHAIN_TESTNET]: 97, - [Network.PALM]: 11297108109, - [Network.PALM_TESTNET]: 11297108099, - [Network.CRONOS]: 25, - [Network.CRONOS_TESTNET]: 338, - [Network.KUCOIN]: 321, - [Network.KUCOIN_TESTNET]: 322, - [Network.OASIS]: 42262, - [Network.OASIS_TESTNET]: 42261, - [Network.OPTIMISM]: 10, - [Network.HARMONY_ONE_SHARD_0]: 1666600000, - [Network.HARMONY_ONE_TESTNET_SHARD_0]: 1666700000, - [Network.KLAYTN]: 8217, - [Network.KLAYTN_BAOBAB]: 1001, - [Network.FLARE_COSTON]: 16, - [Network.FLARE_COSTON_2]: 114, - [Network.FLARE]: 14, - [Network.FLARE_SONGBIRD]: 19, - [Network.HAQQ]: 11235, - [Network.HAQQ_TESTNET]: 54211, - [Network.ARBITRUM_NOVA]: 42170, - [Network.ARBITRUM_NOVA_TESTNET]: 421613, - [Network.ARBITRUM_ONE]: 42161, - [Network.BINANCE_SMART_CHAIN]: 56, - [Network.HORIZEN_EON]: 7332, - [Network.HORIZEN_EON_GOBI]: 1663, - [Network.CHILIZ]: 88888, - [Network.GNOSIS_TESTNET]: 10200, - [Network.VECHAIN]: 100009, - [Network.VECHAIN_TESTNET]: 100010, - [Network.XINFIN]: 50, - [Network.XINFIN_TESTNET]: 51, - [Network.OPTIMISM_TESTNET]: 420, - }, ChainMapInverse: { [AddressEventNotificationChain.ETH]: Chain.Ethereum, [AddressEventNotificationChain.SOL]: Chain.Solana, diff --git a/src/util/index.ts b/src/util/index.ts index 7ee249a7a1..bfe64fcc5c 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -3,5 +3,4 @@ export * from './di.tokens' export * from './env' export * from './error' export * from './logger' -export * from './tatum.utils' export * from './util.shared' diff --git a/src/util/network.utils.spec.ts b/src/util/network.utils.spec.ts new file mode 100644 index 0000000000..5827b25c5d --- /dev/null +++ b/src/util/network.utils.spec.ts @@ -0,0 +1,39 @@ +import { Network } from '../dto' +import { NetworkUtils } from './network.utils' + +describe('Network Utils', () => { + describe('getChainId', () => { + it.each([ + [Network.ETHEREUM, 1], + [Network.ETHEREUM_SEPOLIA, 11155111], + [Network.CELO, 42220], + [Network.CELO_ALFAJORES, 44787], + ])('valid %s -> %s', (network: Network, expected: number) => { + expect(NetworkUtils.getChainId(network)).toBe(expected) + }) + }) + + describe('isTestnet', () => { + it.each([ + [Network.ETHEREUM, false], + [Network.ETHEREUM_SEPOLIA, true], + [Network.CELO, false], + [Network.CELO_ALFAJORES, true], + ])('valid %s -> %s', (network: Network, expected: boolean) => { + expect(NetworkUtils.isTestnet(network)).toBe(expected) + }) + }) + + describe('isAlternateTestnet', () => { + it.each([ + [Network.ETHEREUM, false], + [Network.ETHEREUM_SEPOLIA, false], + [Network.ETHEREUM_HOLESKY, true], + [Network.ETHEREUM_GOERLI, true], + [Network.CELO, false], + [Network.CELO_ALFAJORES, false], + ])('valid %s -> %s', (network: Network, expected: boolean) => { + expect(NetworkUtils.isAlternateTestnet(network)).toBe(expected) + }) + }) +}) diff --git a/src/util/network.utils.ts b/src/util/network.utils.ts new file mode 100644 index 0000000000..f3055f79e9 --- /dev/null +++ b/src/util/network.utils.ts @@ -0,0 +1,21 @@ +import { Network, NETWORK_METADATA, NetworkMetadata } from '../dto' + +export const NetworkUtils = { + getNetworkMetadata: (network: Network): NetworkMetadata => { + return NETWORK_METADATA[network] + }, + isTestnet(network: Network): boolean { + return NetworkUtils.getNetworkMetadata(network).testnet + }, + getChainId: (network: Network): number => { + const chainId = NETWORK_METADATA[network]?.chainId + if (!chainId) { + throw new Error(`Tatum Network to ChainId for network ${network} does not exist`) + } + return chainId + }, + isAlternateTestnet: (network: Network) => { + const metadata = NetworkUtils.getNetworkMetadata(network) + return metadata.testnet && !metadata.defaultTestnet + }, +} diff --git a/src/util/tatum.utils.ts b/src/util/tatum.utils.ts deleted file mode 100644 index 1f5e40b3ed..0000000000 --- a/src/util/tatum.utils.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Network } from '../dto' -import { Constant } from './constant' - -export const TatumUtils = { - getChainId: (network: Network): number => { - if (network in Constant.NETWORK.ChainId) { - return Constant.NETWORK.ChainId[network as keyof typeof Constant.NETWORK.ChainId] - } - throw new Error(`Tatum Network to ChainId for network ${network} does not exist`) - }, - getNetwork: (chainId: number): Network => { - if (Object.keys(chainIdToNetworkCache).length === 0) { - buildChainIdToNetworkCache() - } - const network = chainIdToNetworkCache[chainId] - if (!network) { - throw new Error(`ChainId to Tatum Network for chainId ${chainId} does not exist`) - } - return network - }, -} - -const chainIdToNetworkCache: { [key: number]: keyof typeof Constant.NETWORK.ChainId } = {} - -const buildChainIdToNetworkCache = () => { - for (const network of Object.keys(Constant.NETWORK.ChainId)) { - const netKey = network as keyof typeof Constant.NETWORK.ChainId - chainIdToNetworkCache[Constant.NETWORK.ChainId[netKey]] = netKey - } -} diff --git a/src/util/util.shared.ts b/src/util/util.shared.ts index fcf7c7eada..bc34b7c375 100644 --- a/src/util/util.shared.ts +++ b/src/util/util.shared.ts @@ -436,6 +436,7 @@ export const Utils = { case Network.ETHEREUM: case Network.ETHEREUM_SEPOLIA: case Network.ETHEREUM_GOERLI: + case Network.ETHEREUM_HOLESKY: return AddressEventNotificationChain.ETH case Network.POLYGON: case Network.POLYGON_MUMBAI: