diff --git a/modules/bitgo/src/v2/coinFactory.ts b/modules/bitgo/src/v2/coinFactory.ts index ca04c7a288..d64ce2a6b7 100644 --- a/modules/bitgo/src/v2/coinFactory.ts +++ b/modules/bitgo/src/v2/coinFactory.ts @@ -268,10 +268,12 @@ export function registerCoinConstructors(coinFactory: CoinFactory, coinMap: Coin coinFactory.register('baseeth', EthLikeCoin.createInstance); coinFactory.register('opbnb', EthLikeCoin.createInstance); coinFactory.register('fantom', EthLikeCoin.createInstance); + coinFactory.register('cotieth', EthLikeCoin.createInstance); coinFactory.register('og', EthLikeCoin.createInstance); coinFactory.register('tog', EthLikeCoin.createInstance); coinFactory.register('topbnb', TethLikeCoin.createInstance); coinFactory.register('tfantom', TethLikeCoin.createInstance); + coinFactory.register('tcotieth', TethLikeCoin.createInstance); coinFactory.register('tbaseeth', TethLikeCoin.createInstance); for (const fiatCoin of allFiatCoins) { coinFactory.register(fiatCoin.chain, Fiat.createConstructor(fiatCoin)); @@ -692,12 +694,16 @@ export function getCoinConstructor(coinName: string): CoinConstructor | undefine return EthLikeCoin.createInstance; case 'fantom': return EthLikeCoin.createInstance; + case 'cotieth': + return EthLikeCoin.createInstance; case 'tbaseeth': return TethLikeCoin.createInstance; case 'topbnb': return TethLikeCoin.createInstance; case 'tfantom': return TethLikeCoin.createInstance; + case 'tcotieth': + return TethLikeCoin.createInstance; case 'flr': return Flr.createInstance; case 'flrp': diff --git a/modules/sdk-coin-ethlike/test/fixtures/ethlikeCoin.ts b/modules/sdk-coin-ethlike/test/fixtures/ethlikeCoin.ts index 5c5c3ed569..c290f764c8 100644 --- a/modules/sdk-coin-ethlike/test/fixtures/ethlikeCoin.ts +++ b/modules/sdk-coin-ethlike/test/fixtures/ethlikeCoin.ts @@ -80,6 +80,11 @@ export const ccr = { '0x02f901d3820fa201843b9aca00843b9aca00830186a0948ce59c2d1702844f8eded451aa103961bc37b4e880b90164391252150000000000000000000000002c2b9c9a4a25e24b174f26114e8926a9f2128fe40000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000006939c792000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041833fbbdb8457ee22924b2ad59becbd1629481ca2bf10b9c66dba45e6fbd8fe1f62fc94c6a3a0a8915abe7df7ce9cf2b3d43b0e46f539d11f00cbe9c5aa2dfbe71c00000000000000000000000000000000000000000000000000000000000000c080a05614c8ae83fee9c0d95334114103aa4fee94f574dd55497f41f532d98ce95100a0102dbe65dcd4034fbf2c2e997758180f15e8c626fb9df4f1695a7fa01dbb376e', txid: '0x58062b9508b30f417c948ebce7d30d6029d29681fe17eed21963cbe9f26593fe', }, + tcotieth: { + txHex: + '0xf901cd01843b9aca00830186a0948ce59c2d1702844f8eded451aa103961bc37b4e880b90164391252150000000000000000000000002c2b9c9a4a25e24b174f26114e8926a9f2128fe40000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000006939c792000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041833fbbdb8457ee22924b2ad59becbd1629481ca2bf10b9c66dba45e6fbd8fe1f62fc94c6a3a0a8915abe7df7ce9cf2b3d43b0e46f539d11f00cbe9c5aa2dfbe71c0000000000000000000000000000000000000000000000000000000000000083d82363a05614c8ae83fee9c0d95334114103aa4fee94f574dd55497f41f532d98ce95100a0102dbe65dcd4034fbf2c2e997758180f15e8c626fb9df4f1695a7fa01dbb376e', + txid: '0x9e8bede51b2b435d78b9ab79d925031c374c0c2077365cd8faed304374c6eaf6', + }, }; export const encryptedUserKey = '{"iv":"VFZ3jvXhxo1Z+Yaf2MtZnA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"p+fkHuLa/8k=","ct":"hYG7pvljLIgCjZ53PBlCde5KZRmlUKKHLtDMk+HJfuU46hW+x+C9WsIAO4gFPnTCvFVmQ8x7czCtcNFub5AO2otOGOsX4GE2gXOEmCl1TpWwwNhm7yMUjGJUpgW6ZZgXSXdDitSKi4V/hk78SGSzjFOBSPYRa6I="}'; @@ -117,4 +122,12 @@ export const custodialHot = { signedTxHex: '0xf9016a80830186a082520894702cf81e03aa310ec9481d814e3d04a20b04b50580b901440dcd7a6c000000000000000000000000b9f62c71d5f6949cfb211a67fb13ccf079cc760b0000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000e4ab69c077896252fafbd49efd26b5d171a324100000000000000000000000000000000000000000000000000000000067f415e1000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000041a9c3ead37547fa56b694e4eccc9352225b7458ef08e4e961ca5774d398abd55b5986a7446259374d2098012923583935189739f18dd117c4d15221b2a26f50911c00000000000000000000000000000000000000000000000000000000000000821f678080', }, + tcotieth: { + signatureData: + '0dcd7a6c00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000b9f62c71d5f6949cfb211a67fb13ccf079cc760b0000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000e4ab69c077896252fafbd49efd26b5d171a324100000000000000000000000000000000000000000000000000000000067f415e10000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000d373038323430302d45524332300000000000000000000000000000000000000000', + signature: + '0xa9c3ead37547fa56b694e4eccc9352225b7458ef08e4e961ca5774d398abd55b5986a7446259374d2098012923583935189739f18dd117c4d15221b2a26f50911c', + signedTxHex: + '0xf9016b80830186a082520894702cf81e03aa310ec9481d814e3d04a20b04b50580b901440dcd7a6c000000000000000000000000b9f62c71d5f6949cfb211a67fb13ccf079cc760b0000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000e4ab69c077896252fafbd49efd26b5d171a324100000000000000000000000000000000000000000000000000000000067f415e1000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000041a9c3ead37547fa56b694e4eccc9352225b7458ef08e4e961ca5774d398abd55b5986a7446259374d2098012923583935189739f18dd117c4d15221b2a26f50911c0000000000000000000000000000000000000000000000000000000000000083d823638080', + }, }; diff --git a/modules/sdk-coin-ethlike/test/unit/ethlikeCoin.ts b/modules/sdk-coin-ethlike/test/unit/ethlikeCoin.ts index d55a8205fc..6567a2c895 100644 --- a/modules/sdk-coin-ethlike/test/unit/ethlikeCoin.ts +++ b/modules/sdk-coin-ethlike/test/unit/ethlikeCoin.ts @@ -30,6 +30,10 @@ const coins = [ name: 'tfantom', common: getCommon('tfantom'), }, + { + name: 'tcotieth', + common: getCommon('tcotieth'), + }, ]; describe('EthLike coin tests', function () { diff --git a/modules/sdk-core/src/bitgo/environments.ts b/modules/sdk-core/src/bitgo/environments.ts index 7d3ca6f20a..b2ef2ff3d4 100644 --- a/modules/sdk-core/src/bitgo/environments.ts +++ b/modules/sdk-core/src/bitgo/environments.ts @@ -291,6 +291,10 @@ const mainnetBase: EnvironmentTemplate = { baseUrl: 'https://explorer.fantom.network', rpcUrl: 'https://rpcapi.fantom.network/', }, + cotieth: { + baseUrl: 'https://mainnet.cotiscan.io', + rpcUrl: 'https://mainnet.coti.io/rpc', + }, xtzevm: { baseUrl: 'https://explorer.etherlink.com/api', }, @@ -527,6 +531,10 @@ const testnetBase: EnvironmentTemplate = { baseUrl: 'https://api.etherscan.io/v2', apiToken: process.env.ETHERSCAN_API_TOKEN, }, + tcotieth: { + baseUrl: 'https://testnet.cotiscan.io', + rpcUrl: 'https://testnet.coti.io/rpc', + }, xtzevm: { baseUrl: 'https://shadownet.explorer.etherlink.com/api', }, diff --git a/modules/statics/src/allCoinsAndTokens.ts b/modules/statics/src/allCoinsAndTokens.ts index ba22a6523e..3e1b1e0899 100644 --- a/modules/statics/src/allCoinsAndTokens.ts +++ b/modules/statics/src/allCoinsAndTokens.ts @@ -597,6 +597,26 @@ export const allCoinsAndTokens = [ BaseUnit.ETH, [...ETH_FEATURES, CoinFeature.USES_NON_PACKED_ENCODING_FOR_TXDATA, CoinFeature.EIP1559] ), + account( + 'c4f8e2a1-9b3d-4e5f-a6c7-8d9e0f1a2b3c', + 'tcotieth', + 'COTI Ethereum Testnet', + Networks.test.cotieth, + 18, + UnderlyingAsset.COTIETH, + BaseUnit.ETH, + [...ETH_FEATURES, CoinFeature.USES_NON_PACKED_ENCODING_FOR_TXDATA, CoinFeature.EIP1559] + ), + account( + 'd5a9f3b2-0c4e-5f6a-b7d8-9e0f1a2b3c4d', + 'cotieth', + 'COTI Ethereum', + Networks.main.cotieth, + 18, + UnderlyingAsset.COTIETH, + BaseUnit.ETH, + [...ETH_FEATURES, CoinFeature.USES_NON_PACKED_ENCODING_FOR_TXDATA, CoinFeature.EIP1559] + ), account( 'ffc472f5-27c6-49f8-ad9a-f57659258fb9', 'etc', diff --git a/modules/statics/src/base.ts b/modules/statics/src/base.ts index 36c72f46ef..ad9729a793 100644 --- a/modules/statics/src/base.ts +++ b/modules/statics/src/base.ts @@ -46,6 +46,7 @@ export enum CoinFamily { CODEXETH = 'codexeth', // Codex Ethereum L2 COREDAO = 'coredao', COREUM = 'coreum', + COTIETH = 'cotieth', // COTI EVM native chain CRONOS = 'cronos', CSPR = 'cspr', DASH = 'dash', @@ -643,6 +644,7 @@ export enum UnderlyingAsset { CODEXETH = 'codexeth', // Codex Ethereum L2 COREDAO = 'coredao', COREUM = 'coreum', + COTIETH = 'cotieth', // COTI EVM native chain CRONOS = 'cronos', CSPR = 'cspr', EOS = 'eos', diff --git a/modules/statics/src/networks.ts b/modules/statics/src/networks.ts index 5f92117deb..daf6425e38 100644 --- a/modules/statics/src/networks.ts +++ b/modules/statics/src/networks.ts @@ -463,6 +463,26 @@ class FantomTestnet extends Testnet implements EthereumNetwork { tokenOperationHashPrefix = '4002-ERC20'; } +class Cotieth extends Mainnet implements EthereumNetwork { + name = 'Cotieth'; + family = CoinFamily.COTIETH; + explorerUrl = 'https://mainnet.cotiscan.io/tx/'; + accountExplorerUrl = 'https://mainnet.cotiscan.io/address/'; + chainId = 2632500; + nativeCoinOperationHashPrefix = '2632500'; + tokenOperationHashPrefix = '2632500-ERC20'; +} + +class CotiethTestnet extends Testnet implements EthereumNetwork { + name = 'CotiethTestnet'; + family = CoinFamily.COTIETH; + explorerUrl = 'https://testnet.cotiscan.io/tx/'; + accountExplorerUrl = 'https://testnet.cotiscan.io/address/'; + chainId = 7082400; + nativeCoinOperationHashPrefix = '7082400'; + tokenOperationHashPrefix = '7082400-ERC20'; +} + class LightningBitcoin extends Mainnet implements LightningNetwork { name = 'LightningBitcoin'; family = CoinFamily.LNBTC; @@ -2944,6 +2964,7 @@ export const Networks = { okbxlayer: Object.freeze(new Xlayer()), opbnb: Object.freeze(new OpBNB()), fantom: Object.freeze(new Fantom()), + cotieth: Object.freeze(new Cotieth()), morph: Object.freeze(new Morph()), morpheth: Object.freeze(new MorphETH()), optimism: Object.freeze(new Optimism()), @@ -3077,6 +3098,7 @@ export const Networks = { okbxlayer: Object.freeze(new XlayerTestnet()), opbnb: Object.freeze(new OpBNBTestnet()), fantom: Object.freeze(new FantomTestnet()), + cotieth: Object.freeze(new CotiethTestnet()), morph: Object.freeze(new MorphTestnet()), morpheth: Object.freeze(new MorphETHTestnet()), optimism: Object.freeze(new OptimismTestnet()), diff --git a/modules/statics/test/unit/fixtures/expectedColdFeatures.ts b/modules/statics/test/unit/fixtures/expectedColdFeatures.ts index eed8485b74..b09d602aae 100644 --- a/modules/statics/test/unit/fixtures/expectedColdFeatures.ts +++ b/modules/statics/test/unit/fixtures/expectedColdFeatures.ts @@ -254,6 +254,8 @@ export const expectedColdFeatures = { 'tfantom', 'opbnb', 'topbnb', + 'cotieth', + 'tcotieth', 'fiataed', 'fiataud', 'fiatcad',