Skip to content

Commit 43537f8

Browse files
authored
Merge pull request #6152 from BitGo/COIN-4141
feat(sdk-coin-near): add Nep-141 skeleton
2 parents c9a602a + c32d993 commit 43537f8

File tree

7 files changed

+192
-0
lines changed

7 files changed

+192
-0
lines changed

modules/sdk-coin-near/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './lib';
22
export * from './near';
33
export * from './tnear';
44
export * from './register';
5+
export * from './nep141Token';
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { Near } from './near';
2+
import { coins, Nep141TokenConfig, NetworkType, tokens } from '@bitgo/statics';
3+
import { BitGoBase, CoinConstructor, NamedCoinConstructor } from '@bitgo/sdk-core';
4+
5+
export class Nep141Token extends Near {
6+
public readonly tokenConfig: Nep141TokenConfig;
7+
8+
constructor(bitgo: BitGoBase, tokenConfig: Nep141TokenConfig) {
9+
const staticsCoin = tokenConfig.network === NetworkType.MAINNET ? coins.get('near') : coins.get('tnear');
10+
super(bitgo, staticsCoin);
11+
this.tokenConfig = tokenConfig;
12+
}
13+
14+
static createTokenConstructor(config: Nep141TokenConfig): CoinConstructor {
15+
return (bitgo: BitGoBase) => new Nep141Token(bitgo, config);
16+
}
17+
18+
static createTokenConstructors(): NamedCoinConstructor[] {
19+
const tokensCtors: NamedCoinConstructor[] = [];
20+
for (const token of [...tokens.bitcoin.near.tokens, ...tokens.testnet.near.tokens]) {
21+
const tokenConstructor = Nep141Token.createTokenConstructor(token);
22+
tokensCtors.push({ name: token.type, coinConstructor: tokenConstructor });
23+
}
24+
return tokensCtors;
25+
}
26+
27+
get name(): string {
28+
return this.tokenConfig.name;
29+
}
30+
31+
get coin(): string {
32+
return this.tokenConfig.coin;
33+
}
34+
35+
get contractAddress(): string {
36+
return this.tokenConfig.contractAddress;
37+
}
38+
39+
get decimalPlaces(): number {
40+
return this.tokenConfig.decimalPlaces;
41+
}
42+
43+
getChain(): string {
44+
return this.tokenConfig.type;
45+
}
46+
47+
getBaseChain(): string {
48+
return this.coin;
49+
}
50+
51+
getFullName(): string {
52+
return 'Nep141 Token';
53+
}
54+
55+
getBaseFactor(): number {
56+
return Math.pow(10, this.tokenConfig.decimalPlaces);
57+
}
58+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import { BitGoBase } from '@bitgo/sdk-core';
22
import { Near } from './near';
33
import { TNear } from './tnear';
4+
import { Nep141Token } from './nep141Token';
45

56
export const register = (sdk: BitGoBase): void => {
67
sdk.register('near', Near.createInstance);
78
sdk.register('tnear', TNear.createInstance);
9+
Nep141Token.createTokenConstructors().forEach(({ name, coinConstructor }) => {
10+
sdk.register(name, coinConstructor);
11+
});
812
};

modules/statics/src/account.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ export interface Sip10TokenConstructorOptions extends AccountConstructorOptions
132132
assetId: string;
133133
}
134134

135+
export interface Nep141TokenConstructorOptions extends AccountConstructorOptions {
136+
contractAddress: string;
137+
}
138+
135139
export interface ContractAddress extends String {
136140
__contractaddress_phantom__: never;
137141
}
@@ -568,6 +572,21 @@ export class Sip10Token extends AccountCoinToken {
568572
}
569573
}
570574

575+
/**
576+
* The Near network supports tokens
577+
* Near tokens work similar to native near coin
578+
*/
579+
export class Nep141Token extends AccountCoinToken {
580+
public contractAddress: string;
581+
constructor(options: Nep141TokenConstructorOptions) {
582+
super({
583+
...options,
584+
});
585+
586+
this.contractAddress = options.contractAddress;
587+
}
588+
}
589+
571590
/**
572591
* Factory function for account coin instances.
573592
*
@@ -2880,3 +2899,79 @@ export function tsip10Token(
28802899
) {
28812900
return sip10Token(id, name, fullName, decimalPlaces, assetId, asset, features, prefix, suffix, network);
28822901
}
2902+
2903+
/**
2904+
* Factory function for nep141 token instances.
2905+
*
2906+
* @param id uuid v4
2907+
* @param name unique identifier of the token
2908+
* @param fullName Complete human-readable name of the token
2909+
* @param decimalPlaces Number of decimal places this token supports (divisibility exponent)
2910+
* @param contractAddress Contract address of this token
2911+
* @param asset Asset which this coin represents. This is the same for both mainnet and testnet variants of a coin.
2912+
* @param features Features of this coin. Defaults to the DEFAULT_FEATURES defined in `AccountCoin`
2913+
* @param prefix Optional token prefix. Defaults to empty string
2914+
* @param suffix Optional token suffix. Defaults to token name.
2915+
* @param network Optional token network. Defaults to Near main network.
2916+
* @param primaryKeyCurve The elliptic curve for this chain/token
2917+
*/
2918+
export function nep141Token(
2919+
id: string,
2920+
name: string,
2921+
fullName: string,
2922+
decimalPlaces: number,
2923+
contractAddress: string,
2924+
asset: UnderlyingAsset,
2925+
features: CoinFeature[] = AccountCoin.DEFAULT_FEATURES,
2926+
prefix = '',
2927+
suffix: string = name.toUpperCase(),
2928+
network: AccountNetwork = Networks.main.near,
2929+
primaryKeyCurve: KeyCurve = KeyCurve.Ed25519
2930+
) {
2931+
return Object.freeze(
2932+
new Nep141Token({
2933+
id,
2934+
name,
2935+
fullName,
2936+
network,
2937+
decimalPlaces,
2938+
contractAddress,
2939+
prefix,
2940+
suffix,
2941+
features,
2942+
asset,
2943+
isToken: true,
2944+
primaryKeyCurve,
2945+
baseUnit: BaseUnit.NEAR,
2946+
})
2947+
);
2948+
}
2949+
2950+
/**
2951+
* Factory function for testnet nep141 token instances.
2952+
*
2953+
* @param id uuid v4
2954+
* @param name unique identifier of the token
2955+
* @param fullName Complete human-readable name of the token
2956+
* @param decimalPlaces Number of decimal places this token supports (divisibility exponent)
2957+
* @param contractAddress Contract address of this token
2958+
* @param asset Asset which this coin represents. This is the same for both mainnet and testnet variants of a coin.
2959+
* @param features Features of this coin. Defaults to the DEFAULT_FEATURES defined in `AccountCoin`
2960+
* @param prefix Optional token prefix. Defaults to empty string
2961+
* @param suffix Optional token suffix. Defaults to token name.
2962+
* @param network Optional token network. Defaults to the testnet Near network.
2963+
*/
2964+
export function tnep141Token(
2965+
id: string,
2966+
name: string,
2967+
fullName: string,
2968+
decimalPlaces: number,
2969+
contractAddress: string,
2970+
asset: UnderlyingAsset,
2971+
features: CoinFeature[] = AccountCoin.DEFAULT_FEATURES,
2972+
prefix = '',
2973+
suffix: string = name.toUpperCase(),
2974+
network: AccountNetwork = Networks.test.near
2975+
) {
2976+
return nep141Token(id, name, fullName, decimalPlaces, contractAddress, asset, features, prefix, suffix, network);
2977+
}

modules/statics/src/coinFeatures.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ export const NEAR_FEATURES = [
268268
CoinFeature.STAKING,
269269
CoinFeature.REBUILD_ON_CUSTODY_SIGNING,
270270
CoinFeature.CUSTODY_BITGO_FRANKFURT,
271+
CoinFeature.SUPPORTS_TOKENS,
271272
];
272273
export const MATIC_FEATURES = [
273274
...ACCOUNT_COIN_DEFAULT_FEATURES,

modules/statics/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export {
2525
AptCoin,
2626
AptNFTCollection,
2727
Sip10Token,
28+
Nep141Token,
2829
} from './account';
2930
export { CoinMap } from './map';
3031
export { gatekeep } from './gatekeep';

modules/statics/src/tokenConfig.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
Erc20Coin,
1515
Erc721Coin,
1616
HederaToken,
17+
Nep141Token,
1718
OpethERC20Token,
1819
PolygonERC20Token,
1920
Sip10Token,
@@ -106,6 +107,10 @@ export type Sip10TokenConfig = BaseNetworkConfig & {
106107
assetId: string;
107108
};
108109

110+
export type Nep141TokenConfig = BaseNetworkConfig & {
111+
contractAddress: string;
112+
};
113+
109114
export interface Tokens {
110115
bitcoin: {
111116
eth: {
@@ -178,6 +183,9 @@ export interface Tokens {
178183
stx: {
179184
tokens: Sip10TokenConfig[];
180185
};
186+
near: {
187+
tokens: Nep141TokenConfig[];
188+
};
181189
};
182190
testnet: {
183191
eth: {
@@ -250,6 +258,9 @@ export interface Tokens {
250258
stx: {
251259
tokens: Sip10TokenConfig[];
252260
};
261+
near: {
262+
tokens: Nep141TokenConfig[];
263+
};
253264
};
254265
}
255266

@@ -698,6 +709,21 @@ const getFormattedSip10Tokens = (customCoinMap = coins) =>
698709
return acc;
699710
}, []);
700711

712+
const getFormattedNep141Tokens = (customCoinMap = coins) =>
713+
customCoinMap.reduce((acc: Nep141TokenConfig[], coin) => {
714+
if (coin instanceof Nep141Token) {
715+
acc.push({
716+
type: coin.name,
717+
coin: coin.network.type === NetworkType.MAINNET ? 'near' : 'tnear',
718+
network: coin.network.type === NetworkType.MAINNET ? 'Mainnet' : 'Testnet',
719+
name: coin.fullName,
720+
contractAddress: coin.contractAddress,
721+
decimalPlaces: coin.decimalPlaces,
722+
});
723+
}
724+
return acc;
725+
}, []);
726+
701727
export const getFormattedTokens = (coinMap = coins): Tokens => {
702728
const formattedAptNFTCollections = getFormattedAptNFTCollections(coinMap);
703729
return {
@@ -776,6 +802,9 @@ export const getFormattedTokens = (coinMap = coins): Tokens => {
776802
stx: {
777803
tokens: getFormattedSip10Tokens(coinMap).filter((token) => token.network === 'Mainnet'),
778804
},
805+
near: {
806+
tokens: getFormattedNep141Tokens(coinMap).filter((token) => token.network === 'Mainnet'),
807+
},
779808
},
780809
testnet: {
781810
eth: {
@@ -852,6 +881,9 @@ export const getFormattedTokens = (coinMap = coins): Tokens => {
852881
coredao: {
853882
tokens: getFormattedCoredaoTokens(coinMap).filter((token) => token.network === 'Testnet'),
854883
},
884+
near: {
885+
tokens: getFormattedNep141Tokens(coinMap).filter((token) => token.network === 'Testnet'),
886+
},
855887
},
856888
};
857889
};

0 commit comments

Comments
 (0)