Skip to content

Commit c32d993

Browse files
committed
feat(sdk-coin-near): add Nep-141 skeleton
Ticket: COIN-4141
1 parent d713150 commit c32d993

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
@@ -142,6 +142,10 @@ export interface Sip10TokenConstructorOptions extends AccountConstructorOptions
142142
assetId: string;
143143
}
144144

145+
export interface Nep141TokenConstructorOptions extends AccountConstructorOptions {
146+
contractAddress: string;
147+
}
148+
145149
export interface ContractAddress extends String {
146150
__contractaddress_phantom__: never;
147151
}
@@ -578,6 +582,21 @@ export class Sip10Token extends AccountCoinToken {
578582
}
579583
}
580584

585+
/**
586+
* The Near network supports tokens
587+
* Near tokens work similar to native near coin
588+
*/
589+
export class Nep141Token extends AccountCoinToken {
590+
public contractAddress: string;
591+
constructor(options: Nep141TokenConstructorOptions) {
592+
super({
593+
...options,
594+
});
595+
596+
this.contractAddress = options.contractAddress;
597+
}
598+
}
599+
581600
/**
582601
* Factory function for account coin instances.
583602
*
@@ -2890,3 +2909,79 @@ export function tsip10Token(
28902909
) {
28912910
return sip10Token(id, name, fullName, decimalPlaces, assetId, asset, features, prefix, suffix, network);
28922911
}
2912+
2913+
/**
2914+
* Factory function for nep141 token instances.
2915+
*
2916+
* @param id uuid v4
2917+
* @param name unique identifier of the token
2918+
* @param fullName Complete human-readable name of the token
2919+
* @param decimalPlaces Number of decimal places this token supports (divisibility exponent)
2920+
* @param contractAddress Contract address of this token
2921+
* @param asset Asset which this coin represents. This is the same for both mainnet and testnet variants of a coin.
2922+
* @param features Features of this coin. Defaults to the DEFAULT_FEATURES defined in `AccountCoin`
2923+
* @param prefix Optional token prefix. Defaults to empty string
2924+
* @param suffix Optional token suffix. Defaults to token name.
2925+
* @param network Optional token network. Defaults to Near main network.
2926+
* @param primaryKeyCurve The elliptic curve for this chain/token
2927+
*/
2928+
export function nep141Token(
2929+
id: string,
2930+
name: string,
2931+
fullName: string,
2932+
decimalPlaces: number,
2933+
contractAddress: string,
2934+
asset: UnderlyingAsset,
2935+
features: CoinFeature[] = AccountCoin.DEFAULT_FEATURES,
2936+
prefix = '',
2937+
suffix: string = name.toUpperCase(),
2938+
network: AccountNetwork = Networks.main.near,
2939+
primaryKeyCurve: KeyCurve = KeyCurve.Ed25519
2940+
) {
2941+
return Object.freeze(
2942+
new Nep141Token({
2943+
id,
2944+
name,
2945+
fullName,
2946+
network,
2947+
decimalPlaces,
2948+
contractAddress,
2949+
prefix,
2950+
suffix,
2951+
features,
2952+
asset,
2953+
isToken: true,
2954+
primaryKeyCurve,
2955+
baseUnit: BaseUnit.NEAR,
2956+
})
2957+
);
2958+
}
2959+
2960+
/**
2961+
* Factory function for testnet nep141 token instances.
2962+
*
2963+
* @param id uuid v4
2964+
* @param name unique identifier of the token
2965+
* @param fullName Complete human-readable name of the token
2966+
* @param decimalPlaces Number of decimal places this token supports (divisibility exponent)
2967+
* @param contractAddress Contract address of this token
2968+
* @param asset Asset which this coin represents. This is the same for both mainnet and testnet variants of a coin.
2969+
* @param features Features of this coin. Defaults to the DEFAULT_FEATURES defined in `AccountCoin`
2970+
* @param prefix Optional token prefix. Defaults to empty string
2971+
* @param suffix Optional token suffix. Defaults to token name.
2972+
* @param network Optional token network. Defaults to the testnet Near network.
2973+
*/
2974+
export function tnep141Token(
2975+
id: string,
2976+
name: string,
2977+
fullName: string,
2978+
decimalPlaces: number,
2979+
contractAddress: string,
2980+
asset: UnderlyingAsset,
2981+
features: CoinFeature[] = AccountCoin.DEFAULT_FEATURES,
2982+
prefix = '',
2983+
suffix: string = name.toUpperCase(),
2984+
network: AccountNetwork = Networks.test.near
2985+
) {
2986+
return nep141Token(id, name, fullName, decimalPlaces, contractAddress, asset, features, prefix, suffix, network);
2987+
}

modules/statics/src/coinFeatures.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ export const NEAR_FEATURES = [
225225
CoinFeature.STAKING,
226226
CoinFeature.REBUILD_ON_CUSTODY_SIGNING,
227227
CoinFeature.CUSTODY_BITGO_FRANKFURT,
228+
CoinFeature.SUPPORTS_TOKENS,
228229
];
229230
export const MATIC_FEATURES = [
230231
...AccountCoin.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)