@swapkit/helpers 1.0.0-rc.6 → 1.0.0-rc.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +85 -68
- package/dist/index.es.js +915 -472
- package/dist/index.es.js.map +1 -0
- package/package.json +16 -13
- package/src/helpers/__tests__/memo.test.ts +1 -1
- package/src/helpers/asset.ts +41 -19
- package/src/helpers/liquidity.ts +46 -38
- package/src/helpers/memo.ts +18 -15
- package/src/helpers/others.ts +6 -54
- package/src/helpers/request.ts +15 -0
- package/src/helpers/validators.ts +4 -3
- package/src/index.ts +1 -0
- package/src/modules/__tests__/assetValue.test.ts +126 -38
- package/src/modules/__tests__/bigIntArithmetics.test.ts +30 -0
- package/src/modules/__tests__/swapKitNumber.test.ts +174 -48
- package/src/modules/assetValue.ts +161 -144
- package/src/modules/bigIntArithmetics.ts +190 -117
- package/src/modules/swapKitError.ts +2 -1
- package/src/modules/swapKitNumber.ts +8 -1
- package/src/types.ts +28 -0
|
@@ -1,84 +1,46 @@
|
|
|
1
|
-
import
|
|
2
|
-
CoinGeckoList,
|
|
3
|
-
MayaList,
|
|
4
|
-
PancakeswapETHList,
|
|
5
|
-
PancakeswapList,
|
|
6
|
-
PangolinList,
|
|
7
|
-
StargateARBList,
|
|
8
|
-
SushiswapList,
|
|
9
|
-
ThorchainList,
|
|
10
|
-
TraderjoeList,
|
|
11
|
-
UniswapList,
|
|
12
|
-
WoofiList,
|
|
13
|
-
} from '@swapkit/tokens';
|
|
14
|
-
import { BaseDecimal, Chain } from '@swapkit/types';
|
|
1
|
+
import { BaseDecimal, Chain, ChainToChainId } from '@swapkit/types';
|
|
15
2
|
|
|
16
3
|
import type { CommonAssetString } from '../helpers/asset.ts';
|
|
17
4
|
import { getAssetType, getCommonAssetInfo, getDecimal, isGasAsset } from '../helpers/asset.ts';
|
|
18
5
|
import { validateIdentifier } from '../helpers/validators.ts';
|
|
6
|
+
import type { TokenNames, TokenTax } from '../types.ts';
|
|
19
7
|
|
|
20
|
-
import {
|
|
8
|
+
import type { NumberPrimitives } from './bigIntArithmetics.ts';
|
|
9
|
+
import { BigIntArithmetics, formatBigIntToSafeValue } from './bigIntArithmetics.ts';
|
|
21
10
|
import type { SwapKitValueType } from './swapKitNumber.ts';
|
|
22
11
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
type TCTokenNames = (typeof ThorchainList)['tokens'][number]['identifier'];
|
|
29
|
-
|
|
30
|
-
type TokenNames =
|
|
31
|
-
| TCTokenNames
|
|
32
|
-
| (typeof CoinGeckoList)['tokens'][number]['identifier']
|
|
33
|
-
| (typeof MayaList)['tokens'][number]['identifier']
|
|
34
|
-
| (typeof PancakeswapETHList)['tokens'][number]['identifier']
|
|
35
|
-
| (typeof PancakeswapList)['tokens'][number]['identifier']
|
|
36
|
-
| (typeof PangolinList)['tokens'][number]['identifier']
|
|
37
|
-
| (typeof StargateARBList)['tokens'][number]['identifier']
|
|
38
|
-
| (typeof SushiswapList)['tokens'][number]['identifier']
|
|
39
|
-
| (typeof TraderjoeList)['tokens'][number]['identifier']
|
|
40
|
-
| (typeof WoofiList)['tokens'][number]['identifier']
|
|
41
|
-
| (typeof UniswapList)['tokens'][number]['identifier'];
|
|
42
|
-
|
|
43
|
-
let staticTokensMap: Map<TokenNames, { decimal: number; identifier: string }> | undefined;
|
|
44
|
-
|
|
45
|
-
const getStaticToken = (identifier: TokenNames) => {
|
|
46
|
-
if (!staticTokensMap) {
|
|
47
|
-
throw new Error('Static assets not loaded, call await AssetValue.loadStaticAssets() first');
|
|
48
|
-
}
|
|
49
|
-
const tokenInfo = staticTokensMap.get(identifier.toUpperCase() as TokenNames);
|
|
50
|
-
|
|
51
|
-
return tokenInfo || { decimal: BaseDecimal.THOR, identifier: '' };
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const createAssetValue = async (assetString: string, value: number | string = 0) => {
|
|
55
|
-
validateIdentifier(assetString);
|
|
56
|
-
|
|
57
|
-
const decimal = await getDecimal(getAssetInfo(assetString));
|
|
58
|
-
return new AssetValue({ decimal, value, identifier: assetString });
|
|
59
|
-
};
|
|
12
|
+
const staticTokensMap = new Map<
|
|
13
|
+
TokenNames,
|
|
14
|
+
{ tax?: TokenTax; decimal: number; identifier: string }
|
|
15
|
+
>();
|
|
60
16
|
|
|
61
17
|
export class AssetValue extends BigIntArithmetics {
|
|
62
18
|
address?: string;
|
|
63
19
|
chain: Chain;
|
|
64
|
-
isSynthetic = false;
|
|
65
20
|
isGasAsset = false;
|
|
21
|
+
isSynthetic = false;
|
|
66
22
|
symbol: string;
|
|
23
|
+
tax?: TokenTax;
|
|
67
24
|
ticker: string;
|
|
68
25
|
type: ReturnType<typeof getAssetType>;
|
|
69
26
|
|
|
70
|
-
constructor(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
27
|
+
constructor({
|
|
28
|
+
value,
|
|
29
|
+
decimal,
|
|
30
|
+
tax,
|
|
31
|
+
chain,
|
|
32
|
+
symbol,
|
|
33
|
+
identifier,
|
|
34
|
+
}: { decimal: number; value: SwapKitValueType; tax?: TokenTax } & (
|
|
35
|
+
| { chain: Chain; symbol: string; identifier?: never }
|
|
36
|
+
| { identifier: string; chain?: never; symbol?: never }
|
|
37
|
+
)) {
|
|
38
|
+
super(typeof value === 'object' ? value : { decimal, value });
|
|
76
39
|
|
|
77
|
-
const identifier
|
|
78
|
-
'identifier' in params ? params.identifier : `${params.chain}.${params.symbol}`;
|
|
79
|
-
const assetInfo = getAssetInfo(identifier);
|
|
40
|
+
const assetInfo = getAssetInfo(identifier || `${chain}.${symbol}`);
|
|
80
41
|
|
|
81
42
|
this.type = getAssetType(assetInfo);
|
|
43
|
+
this.tax = tax;
|
|
82
44
|
this.chain = assetInfo.chain;
|
|
83
45
|
this.ticker = assetInfo.ticker;
|
|
84
46
|
this.symbol = assetInfo.symbol;
|
|
@@ -87,100 +49,111 @@ export class AssetValue extends BigIntArithmetics {
|
|
|
87
49
|
this.isGasAsset = assetInfo.isGasAsset;
|
|
88
50
|
}
|
|
89
51
|
|
|
90
|
-
|
|
91
|
-
return `${this.
|
|
52
|
+
toString() {
|
|
53
|
+
return this.isSynthetic ? this.symbol : `${this.chain}.${this.symbol}`;
|
|
92
54
|
}
|
|
93
55
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const shortFormat = this.isSynthetic ? this.ticker : `${this.chain}.${this.ticker}`;
|
|
97
|
-
|
|
98
|
-
return short
|
|
99
|
-
? shortFormat
|
|
100
|
-
: // THOR.ETH/ETH | ETH.USDT-0x1234567890
|
|
101
|
-
`${this.chain}.${this.symbol}`;
|
|
56
|
+
toUrl() {
|
|
57
|
+
return this.isSynthetic ? `${this.chain}.${this.symbol.replace('/', '.')}` : this.toString();
|
|
102
58
|
}
|
|
103
59
|
|
|
104
60
|
eq({ chain, symbol }: { chain: Chain; symbol: string }) {
|
|
105
61
|
return this.chain === chain && this.symbol === symbol;
|
|
106
62
|
}
|
|
107
63
|
|
|
108
|
-
|
|
109
|
-
return
|
|
64
|
+
chainId() {
|
|
65
|
+
return ChainToChainId[this.chain];
|
|
110
66
|
}
|
|
111
67
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
68
|
+
// THOR.RUNE
|
|
69
|
+
// THOR.ETH.ETH
|
|
70
|
+
// ETH.THOR-0x1234567890
|
|
71
|
+
static fromUrl(urlAsset: string, value: NumberPrimitives = 0) {
|
|
72
|
+
const [chain, ticker, symbol] = urlAsset.split('.');
|
|
73
|
+
if (!chain || !ticker) throw new Error('Invalid asset url');
|
|
116
74
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
: undefined;
|
|
120
|
-
}
|
|
75
|
+
const assetString =
|
|
76
|
+
chain === Chain.THORChain && symbol ? `${chain}.${ticker}/${symbol}` : urlAsset;
|
|
121
77
|
|
|
122
|
-
static async fromIdentifier(
|
|
123
|
-
assetString: `${Chain}.${string}` | `${Chain}/${string}` | `${Chain}.${string}-${string}`,
|
|
124
|
-
value: number | string = 0,
|
|
125
|
-
) {
|
|
126
78
|
return createAssetValue(assetString, value);
|
|
127
79
|
}
|
|
128
80
|
|
|
129
|
-
static
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
return new AssetValue({ decimal, identifier: tokenIdentifier, value });
|
|
81
|
+
static fromString(assetString: string, value: NumberPrimitives = 0) {
|
|
82
|
+
return createAssetValue(assetString, value);
|
|
133
83
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
84
|
+
static fromIdentifier(
|
|
85
|
+
assetString:
|
|
86
|
+
| `${Chain}.${string}`
|
|
87
|
+
| `${Chain}/${string}`
|
|
88
|
+
| `${Chain}.${string}-${string}`
|
|
89
|
+
| TokenNames,
|
|
90
|
+
value: NumberPrimitives = 0,
|
|
91
|
+
) {
|
|
92
|
+
return createAssetValue(assetString, value);
|
|
139
93
|
}
|
|
140
94
|
|
|
141
|
-
static
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
95
|
+
static fromStringSync(assetString: string, value: NumberPrimitives = 0) {
|
|
96
|
+
const { chain, isSynthetic } = getAssetInfo(assetString);
|
|
97
|
+
const tokenInfo = staticTokensMap.get(assetString.toUpperCase() as TokenNames);
|
|
98
|
+
|
|
99
|
+
if (isSynthetic) return createSyntheticAssetValue(assetString, value);
|
|
100
|
+
// TODO: write logger that will only run in dev mode with some flag
|
|
101
|
+
// if (!tokenInfo) {
|
|
102
|
+
// console.error(
|
|
103
|
+
// `Asset ${assetString} is not loaded. Use AssetValue.loadStaticAssets() to load it`,
|
|
104
|
+
// );
|
|
105
|
+
// }
|
|
106
|
+
|
|
107
|
+
const { tax, decimal, identifier } = tokenInfo || {
|
|
108
|
+
decimal: BaseDecimal[chain],
|
|
109
|
+
identifier: assetString,
|
|
110
|
+
};
|
|
111
|
+
return new AssetValue({
|
|
112
|
+
tax,
|
|
113
|
+
value: safeValue(value, decimal),
|
|
114
|
+
identifier: isSynthetic ? assetString : identifier,
|
|
115
|
+
decimal: isSynthetic ? 8 : decimal,
|
|
116
|
+
});
|
|
146
117
|
}
|
|
147
118
|
|
|
148
|
-
static
|
|
149
|
-
const
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
119
|
+
static fromIdentifierSync(assetString: TokenNames, value: NumberPrimitives = 0) {
|
|
120
|
+
const { chain, isSynthetic } = getAssetInfo(assetString);
|
|
121
|
+
const tokenInfo = staticTokensMap.get(assetString);
|
|
122
|
+
|
|
123
|
+
if (isSynthetic) return createSyntheticAssetValue(assetString, value);
|
|
124
|
+
// TODO: write logger that will only run in dev mode with some flag
|
|
125
|
+
// if (!tokenInfo) {
|
|
126
|
+
// console.error(
|
|
127
|
+
// `Asset ${assetString} is not loaded. - Loading with base Chain. Use AssetValue.loadStaticAssets() to load it`,
|
|
128
|
+
// );
|
|
129
|
+
// }
|
|
130
|
+
|
|
131
|
+
const { tax, decimal, identifier } = tokenInfo || {
|
|
132
|
+
decimal: BaseDecimal[chain],
|
|
133
|
+
identifier: assetString,
|
|
134
|
+
};
|
|
135
|
+
return new AssetValue({ tax, decimal, identifier, value: safeValue(value, decimal) });
|
|
136
|
+
}
|
|
155
137
|
|
|
156
|
-
|
|
138
|
+
static fromChainOrSignature(assetString: CommonAssetString, value: NumberPrimitives = 0) {
|
|
139
|
+
const { decimal, identifier } = getCommonAssetInfo(assetString);
|
|
140
|
+
return new AssetValue({ value: safeValue(value, decimal), decimal, identifier });
|
|
157
141
|
}
|
|
158
142
|
|
|
159
|
-
static
|
|
143
|
+
static loadStaticAssets() {
|
|
160
144
|
return new Promise<{ ok: true } | { ok: false; message: string; error: any }>(
|
|
161
145
|
async (resolve, reject) => {
|
|
162
146
|
try {
|
|
163
|
-
const
|
|
164
|
-
// Omit ThorchainList from import to avoid decimals conflict (TC uses 8 for all)
|
|
165
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
166
|
-
ThorchainList: _ThorchainList,
|
|
167
|
-
NativeList,
|
|
168
|
-
...tokensPackage
|
|
169
|
-
} = await import('@swapkit/tokens');
|
|
170
|
-
const tokensMap = [NativeList, ...Object.values(tokensPackage)].reduce(
|
|
171
|
-
(acc, { tokens }) => {
|
|
172
|
-
tokens.forEach(({ identifier, chain, ...rest }) => {
|
|
173
|
-
const decimal = 'decimals' in rest ? rest.decimals : BaseDecimal[chain as Chain];
|
|
174
|
-
|
|
175
|
-
acc.set(identifier as TokenNames, { identifier, decimal });
|
|
176
|
-
});
|
|
147
|
+
const tokenPackages = await import('@swapkit/tokens');
|
|
177
148
|
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
149
|
+
Object.values(tokenPackages).forEach((tokenList) => {
|
|
150
|
+
tokenList?.tokens?.forEach(({ identifier, chain, ...rest }) => {
|
|
151
|
+
staticTokensMap.set(identifier.toUpperCase() as TokenNames, {
|
|
152
|
+
identifier,
|
|
153
|
+
decimal: 'decimals' in rest ? rest.decimals : BaseDecimal[chain as Chain],
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
184
157
|
|
|
185
158
|
resolve({ ok: true });
|
|
186
159
|
} catch (error) {
|
|
@@ -197,46 +170,90 @@ export class AssetValue extends BigIntArithmetics {
|
|
|
197
170
|
}
|
|
198
171
|
}
|
|
199
172
|
|
|
200
|
-
export
|
|
173
|
+
export function getMinAmountByChain(chain: Chain) {
|
|
201
174
|
const asset = AssetValue.fromChainOrSignature(chain);
|
|
202
175
|
|
|
203
176
|
switch (chain) {
|
|
204
177
|
case Chain.Bitcoin:
|
|
205
178
|
case Chain.Litecoin:
|
|
206
179
|
case Chain.BitcoinCash:
|
|
207
|
-
return asset.
|
|
180
|
+
return asset.set(0.00010001);
|
|
208
181
|
|
|
209
182
|
case Chain.Dogecoin:
|
|
210
|
-
return asset.
|
|
183
|
+
return asset.set(1.00000001);
|
|
211
184
|
|
|
212
185
|
case Chain.Avalanche:
|
|
213
186
|
case Chain.Ethereum:
|
|
214
|
-
return asset.
|
|
187
|
+
return asset.set(0.00000001);
|
|
215
188
|
|
|
216
189
|
case Chain.THORChain:
|
|
217
190
|
case Chain.Maya:
|
|
218
|
-
return asset.
|
|
191
|
+
return asset.set(0);
|
|
192
|
+
|
|
193
|
+
case Chain.Cosmos:
|
|
194
|
+
return asset.set(0.000001);
|
|
219
195
|
|
|
220
196
|
default:
|
|
221
|
-
return asset.
|
|
197
|
+
return asset.set(0.00000001);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function createAssetValue(identifier: string, value: NumberPrimitives = 0) {
|
|
202
|
+
validateIdentifier(identifier);
|
|
203
|
+
|
|
204
|
+
const staticToken = staticTokensMap.get(identifier.toUpperCase() as TokenNames);
|
|
205
|
+
const decimal = staticToken?.decimal || (await getDecimal(getAssetInfo(identifier)));
|
|
206
|
+
if (!staticToken) {
|
|
207
|
+
staticTokensMap.set(identifier.toUpperCase() as TokenNames, { identifier, decimal });
|
|
222
208
|
}
|
|
223
|
-
};
|
|
224
209
|
|
|
225
|
-
|
|
210
|
+
return new AssetValue({ decimal, value: safeValue(value, decimal), identifier });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function createSyntheticAssetValue(identifier: string, value: NumberPrimitives = 0) {
|
|
214
|
+
const [synthChain, symbol] =
|
|
215
|
+
identifier.split('.')[0].toUpperCase() === Chain.THORChain
|
|
216
|
+
? identifier.split('.').slice(1)!.join().split('/')
|
|
217
|
+
: identifier.split('/');
|
|
218
|
+
|
|
219
|
+
if (!synthChain || !symbol) throw new Error('Invalid asset identifier');
|
|
220
|
+
|
|
221
|
+
return new AssetValue({
|
|
222
|
+
decimal: 8,
|
|
223
|
+
value: safeValue(value, 8),
|
|
224
|
+
identifier: `${Chain.THORChain}.${synthChain}/${symbol}`,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function safeValue(value: NumberPrimitives, decimal: number) {
|
|
229
|
+
return typeof value === 'bigint'
|
|
230
|
+
? formatBigIntToSafeValue({ value, bigIntDecimal: decimal, decimal })
|
|
231
|
+
: value;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function getAssetInfo(identifier: string) {
|
|
226
235
|
const isSynthetic = identifier.slice(0, 14).includes('/');
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
236
|
+
const [synthChain, synthSymbol] =
|
|
237
|
+
identifier.split('.')[0].toUpperCase() === Chain.THORChain
|
|
238
|
+
? identifier.split('.').slice(1)!.join().split('/')
|
|
239
|
+
: identifier.split('/');
|
|
240
|
+
|
|
241
|
+
if (isSynthetic && (!synthChain || !synthSymbol)) throw new Error('Invalid asset identifier');
|
|
242
|
+
|
|
243
|
+
const adjustedIdentifier =
|
|
244
|
+
identifier.includes('.') && !isSynthetic ? identifier : `${Chain.THORChain}.${synthSymbol}`;
|
|
230
245
|
|
|
231
246
|
const [chain, symbol] = adjustedIdentifier.split('.') as [Chain, string];
|
|
232
|
-
const [ticker, address] = symbol.split('-') as [string, string?];
|
|
247
|
+
const [ticker, address] = (isSynthetic ? synthSymbol : symbol).split('-') as [string, string?];
|
|
233
248
|
|
|
234
249
|
return {
|
|
235
250
|
address: address?.toLowerCase(),
|
|
236
251
|
chain,
|
|
237
252
|
isGasAsset: isGasAsset({ chain, symbol }),
|
|
238
253
|
isSynthetic,
|
|
239
|
-
symbol:
|
|
240
|
-
|
|
254
|
+
symbol:
|
|
255
|
+
(isSynthetic ? `${synthChain}/` : '') +
|
|
256
|
+
(address ? `${ticker}-${address?.toLowerCase() ?? ''}` : symbol),
|
|
257
|
+
ticker,
|
|
241
258
|
};
|
|
242
|
-
}
|
|
259
|
+
}
|