From c8ea128acc0eb4a9b515349c0a7097c96a55d35e Mon Sep 17 00:00:00 2001 From: Akash Gianchandani Date: Tue, 21 Nov 2023 13:17:00 +0530 Subject: [PATCH] feat(sdk-coin-opeth): add opeth tokens WIN-963 TICKET: WIN-963 --- modules/bitgo/src/v2/coinFactory.ts | 5 +++ modules/bitgo/src/v2/coins/index.ts | 4 +- modules/bitgo/test/browser/browser.spec.ts | 1 + modules/sdk-coin-opeth/src/index.ts | 1 + modules/sdk-coin-opeth/src/opeth.ts | 4 ++ modules/sdk-coin-opeth/src/opethToken.ts | 35 ++++++++++++++++++ .../sdk-coin-opeth/test/unit/opethToken.ts | 37 +++++++++++++++++++ modules/statics/src/account.ts | 10 +++++ modules/statics/src/base.ts | 6 +++ modules/statics/src/coins.ts | 18 +++++++++ modules/statics/src/tokenConfig.ts | 27 ++++++++++++++ 11 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 modules/sdk-coin-opeth/src/opethToken.ts create mode 100644 modules/sdk-coin-opeth/test/unit/opethToken.ts diff --git a/modules/bitgo/src/v2/coinFactory.ts b/modules/bitgo/src/v2/coinFactory.ts index f05bc84ca7..baaedadee8 100644 --- a/modules/bitgo/src/v2/coinFactory.ts +++ b/modules/bitgo/src/v2/coinFactory.ts @@ -54,6 +54,7 @@ import { Ofc, OfcToken, Opeth, + OpethToken, Osmo, Polygon, PolygonToken, @@ -267,6 +268,10 @@ function registerCoinConstructors(globalCoinFactory: CoinFactory): void { globalCoinFactory.register(name, coinConstructor); }); + OpethToken.createTokenConstructors().forEach(({ name, coinConstructor }) => { + globalCoinFactory.register(name, coinConstructor); + }); + SolToken.createTokenConstructors().forEach(({ name, coinConstructor }) => { globalCoinFactory.register(name, coinConstructor); }); diff --git a/modules/bitgo/src/v2/coins/index.ts b/modules/bitgo/src/v2/coins/index.ts index 23158ceff1..0f769fc9d3 100644 --- a/modules/bitgo/src/v2/coins/index.ts +++ b/modules/bitgo/src/v2/coins/index.ts @@ -29,7 +29,7 @@ import { Hbar, Thbar } from '@bitgo/sdk-coin-hbar'; import { Injective, Tinjective } from '@bitgo/sdk-coin-injective'; import { Islm, Tislm } from '@bitgo/sdk-coin-islm'; import { Ltc, Tltc } from '@bitgo/sdk-coin-ltc'; -import { Opeth, Topeth } from '@bitgo/sdk-coin-opeth'; +import { Opeth, Topeth, OpethToken } from '@bitgo/sdk-coin-opeth'; import { Osmo, Tosmo } from '@bitgo/sdk-coin-osmo'; import { Polygon, PolygonToken, Tpolygon } from '@bitgo/sdk-coin-polygon'; import { Rbtc, Trbtc } from '@bitgo/sdk-coin-rbtc'; @@ -73,7 +73,7 @@ export { Etc, Tetc }; export { Hash, Thash }; export { Hbar, Thbar }; export { Ltc, Tltc }; -export { Opeth, Topeth }; +export { Opeth, Topeth, OpethToken }; export { Osmo, Tosmo }; export { Polygon, PolygonToken, Tpolygon }; export { Rbtc, Trbtc }; diff --git a/modules/bitgo/test/browser/browser.spec.ts b/modules/bitgo/test/browser/browser.spec.ts index 01601eb332..49945e2af5 100644 --- a/modules/bitgo/test/browser/browser.spec.ts +++ b/modules/bitgo/test/browser/browser.spec.ts @@ -22,6 +22,7 @@ describe('Coins', () => { PolygonToken: 1, BscToken: 1, ArbethToken: 1, + OpethToken: 1, }; Object.keys(BitGoJS.Coin) .filter((coinName) => !excludedKeys[coinName]) diff --git a/modules/sdk-coin-opeth/src/index.ts b/modules/sdk-coin-opeth/src/index.ts index 2ab6ea99b4..8e6161d0ca 100644 --- a/modules/sdk-coin-opeth/src/index.ts +++ b/modules/sdk-coin-opeth/src/index.ts @@ -1,4 +1,5 @@ export * from './lib'; export * from './opeth'; export * from './topeth'; +export * from './opethToken'; export * from './register'; diff --git a/modules/sdk-coin-opeth/src/opeth.ts b/modules/sdk-coin-opeth/src/opeth.ts index b4988f50b2..be9bb0085e 100644 --- a/modules/sdk-coin-opeth/src/opeth.ts +++ b/modules/sdk-coin-opeth/src/opeth.ts @@ -1,3 +1,7 @@ +/** + * @prettier + */ + import request from 'superagent'; import { BaseCoin, BitGoBase, common } from '@bitgo/sdk-core'; import { BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics'; diff --git a/modules/sdk-coin-opeth/src/opethToken.ts b/modules/sdk-coin-opeth/src/opethToken.ts new file mode 100644 index 0000000000..ae61475355 --- /dev/null +++ b/modules/sdk-coin-opeth/src/opethToken.ts @@ -0,0 +1,35 @@ +/** + * @prettier + */ +import { EthLikeTokenConfig, coins } from '@bitgo/statics'; +import { BitGoBase, CoinConstructor, NamedCoinConstructor } from '@bitgo/sdk-core'; +import { CoinNames, EthLikeToken } from '@bitgo/abstract-eth'; + +import { TransactionBuilder } from './lib'; +export { EthLikeTokenConfig }; + +export class OpethToken extends EthLikeToken { + public readonly tokenConfig: EthLikeTokenConfig; + static coinNames: CoinNames = { + Mainnet: 'opeth', + Testnet: 'topeth', + }; + constructor(bitgo: BitGoBase, tokenConfig: EthLikeTokenConfig) { + super(bitgo, tokenConfig, OpethToken.coinNames); + } + static createTokenConstructor(config: EthLikeTokenConfig): CoinConstructor { + return super.createTokenConstructor(config, OpethToken.coinNames); + } + + static createTokenConstructors(): NamedCoinConstructor[] { + return super.createTokenConstructors(OpethToken.coinNames); + } + + protected getTransactionBuilder(): TransactionBuilder { + return new TransactionBuilder(coins.get(this.getBaseChain())); + } + + getFullName(): string { + return 'Opeth Token'; + } +} diff --git a/modules/sdk-coin-opeth/test/unit/opethToken.ts b/modules/sdk-coin-opeth/test/unit/opethToken.ts new file mode 100644 index 0000000000..16fc54214d --- /dev/null +++ b/modules/sdk-coin-opeth/test/unit/opethToken.ts @@ -0,0 +1,37 @@ +import 'should'; + +import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test'; +import { OpethToken } from '../../src'; +import { BitGoAPI } from '@bitgo/sdk-api'; + +describe('Opeth Token:', function () { + let bitgo: TestBitGoAPI; + let opethTokenCoin; + const tokenName = 'topeth:terc18dp'; + + before(function () { + bitgo = TestBitGo.decorate(BitGoAPI, { env: 'test' }); + OpethToken.createTokenConstructors().forEach(({ name, coinConstructor }) => { + bitgo.safeRegister(name, coinConstructor); + }); + bitgo.initializeTestVars(); + opethTokenCoin = bitgo.coin(tokenName); + }); + + it('should return constants', function () { + opethTokenCoin.getChain().should.equal('topeth:terc18dp'); + opethTokenCoin.getBaseChain().should.equal('topeth'); + opethTokenCoin.getFullName().should.equal('Opeth Token'); + opethTokenCoin.getBaseFactor().should.equal(1e18); + opethTokenCoin.type.should.equal(tokenName); + opethTokenCoin.name.should.equal('Optimism Test ERC Token 18 Decimals'); + opethTokenCoin.coin.should.equal('topeth'); + opethTokenCoin.network.should.equal('Testnet'); + opethTokenCoin.decimalPlaces.should.equal(18); + }); + + it('should return same token by contract address', function () { + const tokencoinBycontractAddress = bitgo.coin(opethTokenCoin.tokenContractAddress); + opethTokenCoin.should.deepEqual(tokencoinBycontractAddress); + }); +}); diff --git a/modules/statics/src/account.ts b/modules/statics/src/account.ts index 55eedaab25..5c8a868f33 100644 --- a/modules/statics/src/account.ts +++ b/modules/statics/src/account.ts @@ -369,6 +369,16 @@ export class ArbethERC20Token extends ContractAddressDefinedToken { } } +/** + * The Optimism Chain network support tokens + * Optimism Chain Tokens are ERC20 tokens + */ +export class OpethERC20Token extends ContractAddressDefinedToken { + constructor(options: Erc20ConstructorOptions) { + super(options); + } +} + /** * The Xrp network supports tokens * Xrp tokens are identified by their issuer address diff --git a/modules/statics/src/base.ts b/modules/statics/src/base.ts index 2cd203c841..2e85078f33 100644 --- a/modules/statics/src/base.ts +++ b/modules/statics/src/base.ts @@ -1375,6 +1375,12 @@ export enum UnderlyingAsset { // Arbitrum testnet tokens 'tarbeth:link' = 'tarbeth:link', + // Optimism mainnet tokens + 'opeth:link' = 'opeth:link', + + // Optimism testnet tokens + 'topeth:terc18dp' = 'topeth:terc18dp', + ERC721 = 'erc721', ERC1155 = 'erc1155', NONSTANDARD = 'nonstandard', diff --git a/modules/statics/src/coins.ts b/modules/statics/src/coins.ts index cc88fd1351..971b2542a4 100644 --- a/modules/statics/src/coins.ts +++ b/modules/statics/src/coins.ts @@ -16,6 +16,7 @@ import { hederaToken, nonstandardToken, polygonErc20, + opethErc20, solToken, stellarToken, talgoToken, @@ -28,6 +29,7 @@ import { terc20, terc721, tpolygonErc20, + topethErc20, tronToken, tsolToken, tstellarToken, @@ -11388,6 +11390,22 @@ export const coins = CoinMap.fromCoins([ '0x143e1dae4f018ff86051a01d44a1b49b13704056', UnderlyingAsset['tarbeth:link'] ), + opethErc20( + '8d80fac6-4cbc-447c-b49b-4229cb8aa89d', + 'opeth:link', + 'Chainlink Token', + 18, + '0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6', + UnderlyingAsset['opeth:link'] + ), + topethErc20( + '3c06bc28-1af2-4869-a632-bd081376fb46', + 'topeth:terc18dp', + 'Optimism Test ERC Token 18 Decimals', + 18, + '0xe9df68a54bba438c8a6192e95f0f2c53ac93d997', + UnderlyingAsset['topeth:terc18dp'] + ), txrpToken( '8ef16158-1015-4a67-b6fe-db669c18ab2b', 'txrp:tst-rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd', diff --git a/modules/statics/src/tokenConfig.ts b/modules/statics/src/tokenConfig.ts index f6055d23da..15ab3739e2 100644 --- a/modules/statics/src/tokenConfig.ts +++ b/modules/statics/src/tokenConfig.ts @@ -15,6 +15,7 @@ import { TronErc20Coin, XrpCoin, ArbethERC20Token, + OpethERC20Token, } from './account'; import { CoinFamily, CoinKind } from './base'; import { coins } from './coins'; @@ -102,6 +103,9 @@ export interface Tokens { arbeth: { tokens: EthLikeTokenConfig[]; }; + opeth: { + tokens: EthLikeTokenConfig[]; + }; sol: { tokens: SolTokenConfig[]; }; @@ -149,6 +153,9 @@ export interface Tokens { arbeth: { tokens: EthLikeTokenConfig[]; }; + opeth: { + tokens: EthLikeTokenConfig[]; + }; sol: { tokens: SolTokenConfig[]; }; @@ -325,6 +332,20 @@ const formattedArbethTokens = coins.reduce((acc: EthLikeTokenConfig[], coin) => return acc; }, []); +const formattedOpethTokens = coins.reduce((acc: EthLikeTokenConfig[], coin) => { + if (coin instanceof OpethERC20Token) { + acc.push({ + type: coin.name, + coin: coin.network.type === NetworkType.MAINNET ? 'opeth' : 'topeth', + network: coin.network.type === NetworkType.MAINNET ? 'Mainnet' : 'Testnet', + name: coin.fullName, + tokenContractAddress: coin.contractAddress.toString().toLowerCase(), + decimalPlaces: coin.decimalPlaces, + }); + } + return acc; +}, []); + const formattedSolTokens = coins.reduce((acc: SolTokenConfig[], coin) => { if (coin instanceof SolCoin) { acc.push({ @@ -444,6 +465,9 @@ export const tokens: Tokens = { arbeth: { tokens: formattedArbethTokens.filter((token) => token.network === 'Mainnet'), }, + opeth: { + tokens: formattedOpethTokens.filter((token) => token.network === 'Mainnet'), + }, sol: { tokens: formattedSolTokens.filter((token) => token.network === 'Mainnet'), }, @@ -492,6 +516,9 @@ export const tokens: Tokens = { arbeth: { tokens: formattedArbethTokens.filter((token) => token.network === 'Testnet'), }, + opeth: { + tokens: formattedOpethTokens.filter((token) => token.network === 'Testnet'), + }, sol: { tokens: formattedSolTokens.filter((token) => token.network === 'Testnet'), },