-
Notifications
You must be signed in to change notification settings - Fork 302
Expand file tree
/
Copy pathbitgo.ts
More file actions
161 lines (148 loc) · 5.1 KB
/
bitgo.ts
File metadata and controls
161 lines (148 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//
// BitGo JavaScript SDK
//
// Copyright 2014, BitGo, Inc. All Rights Reserved.
//
import pjson = require('../package.json');
import * as _ from 'lodash';
import { BaseCoin, CoinFactory, common, UnsupportedCoinError } from '@bitgo/sdk-core';
import { BitGoAPI, BitGoAPIOptions } from '@bitgo/sdk-api';
import {
createTokenMapUsingTrimmedConfigDetails,
TrimmedAmsTokenConfig,
createToken,
getFormattedTokenConfigForCoin,
coins,
BaseCoin as StaticsBaseCoin,
} from '@bitgo/statics';
import { GlobalCoinFactory, registerCoinConstructors, getTokenConstructor, getCoinConstructor } from './v2/coinFactory';
import { Ofc } from './v2/coins';
// constructor params used exclusively for BitGo class
export type BitGoOptions = BitGoAPIOptions & {
useAms?: boolean;
};
export class BitGo extends BitGoAPI {
private _coinFactory: CoinFactory;
private _useAms: boolean;
/**
* Constructor for BitGo Object
*/
constructor(params: BitGoOptions = {}) {
super(params);
if (
!common.validateParams(
params,
[],
[
'clientId',
'clientSecret',
'refreshToken',
'accessToken',
'userAgent',
'customRootURI',
'customBitcoinNetwork',
'serverXpub',
'stellarFederationServerUrl',
]
) ||
(params.useProduction && !_.isBoolean(params.useProduction)) ||
(params.useAms && !_.isBoolean(params.useAms))
) {
throw new Error('invalid argument');
}
if (!params.clientId !== !params.clientSecret) {
throw new Error('invalid argument - must provide both client id and secret');
}
this._useAms = !!params.useAms;
this._version = pjson.version;
this._userAgent = params.userAgent || 'BitGoJS/' + this.version();
this._coinFactory = new CoinFactory();
}
/**
* Initialize the coin factory with token configurations
* @param tokenConfigMap - A map of token metadata from AMS
*/
initCoinFactory(tokenConfigMap: Record<string, TrimmedAmsTokenConfig[]>): void {
const coinMap = createTokenMapUsingTrimmedConfigDetails(tokenConfigMap);
this._coinFactory = new CoinFactory();
registerCoinConstructors(this._coinFactory, coinMap);
}
/**
* Fetch all the tokens and initialize the coin factory
*/
async registerAllTokens(): Promise<void> {
if (!this._useAms) {
throw new Error('registerAllTokens is only supported when useAms is set to true');
}
// Fetch mainnet assets for prod and adminProd environments, testnet assets for all other environments
const assetEnvironment = ['prod', 'adminProd'].includes(this.getEnv()) ? 'mainnet' : 'testnet';
const url = this.url(`/assets/list/${assetEnvironment}`);
const tokenConfigMap = (await this.executeAssetRequest(url)) as Record<string, TrimmedAmsTokenConfig[]>;
this.initCoinFactory(tokenConfigMap);
}
/**
* Create a basecoin object
* @param coinName
*/
coin(coinName: string): BaseCoin {
if (this._useAms) {
return this._coinFactory.getInstance(this, coinName);
}
return GlobalCoinFactory.getInstance(this, coinName);
}
/**
* Register a token in the coin factory by name, fetching metadata from AMS if needed.
* @param tokenName - The token name to register
*/
async registerTokenByName(tokenName: string): Promise<void> {
if (!this._useAms) {
throw new Error('registerTokenByName is only supported when useAms is set to true');
}
//do not register a coin/token if it's already registered
if (this._coinFactory.hasCoin(tokenName)) {
return;
}
//ofc is not present in statics coin map
if (tokenName === 'ofc') {
this._coinFactory.register(tokenName, Ofc.createInstance);
return;
}
// Get the coin/token details only if it's not present in statics library
let staticsBaseCoin: Readonly<StaticsBaseCoin> | undefined;
if (coins.has(tokenName)) {
staticsBaseCoin = coins.get(tokenName);
} else {
const url = this.url(`/assets/name/${tokenName}`);
const tokenConfig = (await this.executeAssetRequest(url)) as TrimmedAmsTokenConfig;
staticsBaseCoin = createToken(tokenConfig);
}
if (!staticsBaseCoin) {
throw new UnsupportedCoinError(tokenName);
}
if (staticsBaseCoin.isToken) {
const formattedTokenConfig = getFormattedTokenConfigForCoin(staticsBaseCoin);
if (!formattedTokenConfig) {
throw new UnsupportedCoinError(tokenName);
}
const tokenConstructor = getTokenConstructor(formattedTokenConfig);
if (!tokenConstructor) {
throw new UnsupportedCoinError(tokenName);
}
this._coinFactory.registerToken(staticsBaseCoin, tokenConstructor);
} else {
const coinConstructor = getCoinConstructor(tokenName);
if (!coinConstructor) {
throw new UnsupportedCoinError(tokenName);
}
this._coinFactory.registerToken(staticsBaseCoin, coinConstructor);
}
}
/**
* Create a basecoin object for a virtual token
* @param tokenName
*/
async token(tokenName: string): Promise<BaseCoin> {
await this.fetchConstants();
return this.coin(tokenName);
}
}