Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sdk-coin-bera): add bera token support #4914

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions modules/bitgo/src/v2/coinFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
AvaxP,
Bch,
Bera,
BeraToken,
Bld,
Bsc,
BscToken,
Expand Down Expand Up @@ -294,6 +295,10 @@ function registerCoinConstructors(globalCoinFactory: CoinFactory): void {
globalCoinFactory.register(name, coinConstructor);
});

BeraToken.createTokenConstructors().forEach(({ name, coinConstructor }) => {
globalCoinFactory.register(name, coinConstructor);
});

SolToken.createTokenConstructors().forEach(({ name, coinConstructor }) => {
globalCoinFactory.register(name, coinConstructor);
});
Expand Down
4 changes: 2 additions & 2 deletions modules/bitgo/src/v2/coins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { AvaxC, AvaxCToken, TavaxC } from '@bitgo/sdk-coin-avaxc';
import { AvaxP, TavaxP } from '@bitgo/sdk-coin-avaxp';
import { Bch, Tbch } from '@bitgo/sdk-coin-bch';
import { Bcha, Tbcha } from '@bitgo/sdk-coin-bcha';
import { Bera, Tbera } from '@bitgo/sdk-coin-bera';
import { Bera, Tbera, BeraToken } from '@bitgo/sdk-coin-bera';
import { Bld, Tbld } from '@bitgo/sdk-coin-bld';
import { Bsc, BscToken, Tbsc } from '@bitgo/sdk-coin-bsc';
import { Bsv, Tbsv } from '@bitgo/sdk-coin-bsv';
Expand Down Expand Up @@ -59,7 +59,7 @@ export { Atom, Tatom };
export { AvaxC, AvaxCToken, TavaxC };
export { AvaxP, TavaxP };
export { Bch, Tbch };
export { Bera, Tbera };
export { Bera, Tbera, BeraToken };
export { Bsc, BscToken, Tbsc };
export { Bsv, Tbsv };
export { Btc, Tbtc, Tbtcsig, Tbtcbgsig };
Expand Down
1 change: 1 addition & 0 deletions modules/bitgo/test/browser/browser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ describe('Coins', () => {
OpethToken: 1,
ZkethToken: 1,
SuiToken: 1,
BeraToken: 1,
};
Object.keys(BitGoJS.Coin)
.filter((coinName) => !excludedKeys[coinName])
Expand Down
47 changes: 47 additions & 0 deletions modules/sdk-coin-bera/src/beraToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* @prettier
*/
import { coins, EthLikeTokenConfig } from '@bitgo/statics';
import { BitGoBase, CoinConstructor, common, NamedCoinConstructor } from '@bitgo/sdk-core';
import { CoinNames, EthLikeToken, recoveryBlockchainExplorerQuery } from '@bitgo/abstract-eth';

import { TransactionBuilder } from './lib';

export { EthLikeTokenConfig };

export class BeraToken extends EthLikeToken {
public readonly tokenConfig: EthLikeTokenConfig;
static coinNames: CoinNames = {
Mainnet: 'bera',
Testnet: 'tbera',
};
constructor(bitgo: BitGoBase, tokenConfig: EthLikeTokenConfig) {
super(bitgo, tokenConfig, BeraToken.coinNames);
}
static createTokenConstructor(config: EthLikeTokenConfig): CoinConstructor {
return super.createTokenConstructor(config, BeraToken.coinNames);
}

static createTokenConstructors(): NamedCoinConstructor[] {
return super.createTokenConstructors(BeraToken.coinNames);
}

protected getTransactionBuilder(): TransactionBuilder {
return new TransactionBuilder(coins.get(this.getBaseChain()));
}

/**
* Make a query to Berachain explorer for information such as balance, token balance, solidity calls
* @param {Object} query key-value pairs of parameters to append after /api
* @returns {Promise<Object>} response Berachain explorer
*/
async recoveryBlockchainExplorerQuery(query: Record<string, string>): Promise<Record<string, unknown>> {
const apiToken = common.Environments[this.bitgo.getEnv()].beraExplorerApiToken;
const explorerUrl = common.Environments[this.bitgo.getEnv()].beraExplorerBaseUrl;
return await recoveryBlockchainExplorerQuery(query, explorerUrl as string, apiToken);
}

getFullName(): string {
return 'Bera Token';
}
}
1 change: 1 addition & 0 deletions modules/sdk-coin-bera/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './bera';
export * from './tbera';
export * from './beraToken';
export * from './lib';
export * from './register';
31 changes: 31 additions & 0 deletions modules/sdk-coin-bera/test/unit/beraToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test';
import { BitGoAPI } from '@bitgo/sdk-api';

import { BeraToken } from '../../src';

describe('Bera Token:', function () {
let bitgo: TestBitGoAPI;
let bgtTokenCoin;
const tokenName = 'tbera:bgt';

before(function () {
bitgo = TestBitGo.decorate(BitGoAPI, { env: 'test' });
BeraToken.createTokenConstructors().forEach(({ name, coinConstructor }) => {
bitgo.safeRegister(name, coinConstructor);
});
bitgo.initializeTestVars();
bgtTokenCoin = bitgo.coin(tokenName);
});

it('should return constants', function () {
bgtTokenCoin.getChain().should.equal('tbera:bgt');
bgtTokenCoin.getBaseChain().should.equal('tbera');
bgtTokenCoin.getFullName().should.equal('Bera Token');
bgtTokenCoin.getBaseFactor().should.equal(1e18);
bgtTokenCoin.type.should.equal(tokenName);
bgtTokenCoin.name.should.equal('Bera Test BGT');
bgtTokenCoin.coin.should.equal('tarbeth');
bgtTokenCoin.network.should.equal('Testnet');
bgtTokenCoin.decimalPlaces.should.equal(18);
});
});
100 changes: 100 additions & 0 deletions modules/statics/src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,16 @@ export class ZkethERC20Token extends ContractAddressDefinedToken {
}
}

/**
* The Bera Chain network support tokens
* Bera Chain Tokens are ERC20 tokens
*/
export class BeraERC20Token extends ContractAddressDefinedToken {
constructor(options: Erc20ConstructorOptions) {
super(options);
}
}

/**
* The Xrp network supports tokens
* Xrp tokens are identified by their issuer address
Expand Down Expand Up @@ -1998,6 +2008,96 @@ export function tzkethErc20(
);
}

/**
* Factory function for beraErc20 token instances.
*
* @param id uuid v4
* @param name unique identifier of the token
* @param fullName Complete human-readable name of the token
* @param decimalPlaces Number of decimal places this token supports (divisibility exponent)
* @param contractAddress Contract address of this token
* @param asset Asset which this coin represents. This is the same for both mainnet and testnet variants of a coin.
* @param prefix? Optional token prefix. Defaults to empty string
* @param suffix? Optional token suffix. Defaults to token name.
* @param network? Optional token network. Defaults to zkSync mainnet network.
* @param features? Features of this coin. Defaults to the DEFAULT_FEATURES defined in `AccountCoin`
* @param primaryKeyCurve The elliptic curve for this chain/token
*/
export function beraErc20(
id: string,
name: string,
fullName: string,
decimalPlaces: number,
contractAddress: string,
asset: UnderlyingAsset,
features: CoinFeature[] = AccountCoin.DEFAULT_FEATURES,
prefix = '',
suffix: string = name.toUpperCase(),
network: AccountNetwork = Networks.main.bera,
primaryKeyCurve: KeyCurve = KeyCurve.Secp256k1
) {
return Object.freeze(
new BeraERC20Token({
id,
name,
fullName,
network,
contractAddress,
prefix,
suffix,
features,
decimalPlaces,
asset,
isToken: true,
primaryKeyCurve,
baseUnit: BaseUnit.ETH,
})
);
}

/**
* Factory function for zkSync Sepolia testnet zkethErc20 token instances.
*
* @param id uuid v4
* @param name unique identifier of the token
* @param fullName Complete human-readable name of the token
* @param decimalPlaces Number of decimal places this token supports (divisibility exponent)
* @param contractAddress Contract address of this token
* @param asset Asset which this coin represents. This is the same for both mainnet and testnet variants of a coin.
* @param prefix? Optional token prefix. Defaults to empty string
* @param suffix? Optional token suffix. Defaults to token name.
* @param network? Optional token network. Defaults to the zkSync sepolia test network.
* @param features? Features of this coin. Defaults to the DEFAULT_FEATURES defined in `AccountCoin`
* @param primaryKeyCurve The elliptic curve for this chain/token
*/
export function tberaErc20(
id: string,
name: string,
fullName: string,
decimalPlaces: number,
contractAddress: string,
asset: UnderlyingAsset,
features: CoinFeature[] = AccountCoin.DEFAULT_FEATURES,
prefix = '',
suffix: string = name.toUpperCase(),
network: AccountNetwork = Networks.test.bera,
primaryKeyCurve: KeyCurve = KeyCurve.Secp256k1
) {
return beraErc20(
id,
name,
fullName,
decimalPlaces,
contractAddress,
asset,
features,
prefix,
suffix,
network,
primaryKeyCurve
);
}

/**
* Factory function for xrp token instances.
*
Expand Down
6 changes: 6 additions & 0 deletions modules/statics/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2100,6 +2100,12 @@ export enum UnderlyingAsset {
// Celo mainnet tokens
'celo:pact' = 'celo:pact',

// bera mainnet tokens
'bera:bgt' = 'bera:bgt',

// bera testnet tokens
'tbera:bgt' = 'tbera:bgt',

ERC721 = 'erc721',
ERC1155 = 'erc1155',
NONSTANDARD = 'nonstandard',
Expand Down
11 changes: 11 additions & 0 deletions modules/statics/src/coins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
tarbethErc20,
tavaxErc20,
tbscToken,
tberaErc20,
beraErc20,
tceloToken,
teosToken,
terc1155,
Expand Down Expand Up @@ -17806,6 +17808,15 @@ export const coins = CoinMap.fromCoins([
'0xcccb29bac5ad81290383643c6fb38130cda9d881',
UnderlyingAsset['tzketh:link']
),
beraErc20('ef833f4e-7617-4c6d-8a1f-1fef0dd1dd0e', 'bera:bgt', 'BGT Token', 18, '', UnderlyingAsset['bera:bgt']),
tberaErc20(
'24af5e18-ab4b-43e5-80db-0ddb9beb01b3',
'tbera:bgt',
'bera Test BGT',
18,
'0xbDa130737BDd9618301681329bF2e46A016ff9Ad',
UnderlyingAsset['tbera:bgt']
),
txrpToken(
'8ef16158-1015-4a67-b6fe-db669c18ab2b',
'txrp:tst-rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd',
Expand Down
27 changes: 27 additions & 0 deletions modules/statics/src/tokenConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
OpethERC20Token,
ZkethERC20Token,
SuiCoin,
BeraERC20Token,
} from './account';
import { CoinFamily, CoinKind } from './base';
import { coins } from './coins';
Expand Down Expand Up @@ -135,6 +136,9 @@ export interface Tokens {
sui: {
tokens: SuiTokenConfig[];
};
bera: {
tokens: EthLikeTokenConfig[];
};
};
testnet: {
eth: {
Expand Down Expand Up @@ -191,6 +195,9 @@ export interface Tokens {
sui: {
tokens: SuiTokenConfig[];
};
bera: {
tokens: EthLikeTokenConfig[];
};
};
}

Expand Down Expand Up @@ -382,6 +389,20 @@ const formattedZkethTokens = coins.reduce((acc: EthLikeTokenConfig[], coin) => {
return acc;
}, []);

const formattedBeraTokens = coins.reduce((acc: EthLikeTokenConfig[], coin) => {
if (coin instanceof BeraERC20Token) {
acc.push({
type: coin.name,
coin: coin.network.type === NetworkType.MAINNET ? 'bera' : 'tbera',
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({
Expand Down Expand Up @@ -541,6 +562,9 @@ export const tokens: Tokens = {
sui: {
tokens: formattedSuiTokens.filter((token) => token.network === 'Mainnet'),
},
bera: {
tokens: formattedBeraTokens.filter((token) => token.network === 'Mainnet'),
},
},
// network name for test environments
testnet: {
Expand Down Expand Up @@ -598,6 +622,9 @@ export const tokens: Tokens = {
sui: {
tokens: formattedSuiTokens.filter((token) => token.network === 'Testnet'),
},
bera: {
tokens: formattedArbethTokens.filter((token) => token.network === 'Testnet'),
},
},
};

Expand Down
Loading