@swapkit/helpers 1.0.0-rc.8 → 1.0.0-rc.80
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/LICENSE +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +143 -89
- package/dist/index.es.js +578 -446
- package/dist/index.es.js.map +1 -0
- package/package.json +19 -19
- package/src/helpers/__tests__/asset.test.ts +64 -62
- package/src/helpers/__tests__/memo.test.ts +52 -40
- package/src/helpers/__tests__/others.test.ts +57 -30
- package/src/helpers/asset.ts +122 -96
- package/src/helpers/liquidity.ts +50 -42
- package/src/helpers/memo.ts +30 -28
- package/src/helpers/others.ts +30 -56
- package/src/helpers/validators.ts +7 -6
- package/src/index.ts +10 -8
- package/src/modules/__tests__/assetValue.test.ts +329 -121
- package/src/modules/__tests__/bigIntArithmetics.test.ts +30 -0
- package/src/modules/__tests__/swapKitNumber.test.ts +306 -183
- package/src/modules/assetValue.ts +214 -152
- package/src/modules/bigIntArithmetics.ts +214 -146
- package/src/modules/swapKitError.ts +30 -5
- package/src/modules/swapKitNumber.ts +8 -1
- package/src/types.ts +30 -0
|
@@ -1,84 +1,46 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import type { CommonAssetString } from '../helpers/asset.ts';
|
|
17
|
-
import { getAssetType, getCommonAssetInfo, getDecimal, isGasAsset } from '../helpers/asset.ts';
|
|
18
|
-
import { validateIdentifier } from '../helpers/validators.ts';
|
|
19
|
-
|
|
20
|
-
import { BigIntArithmetics } from './bigIntArithmetics.ts';
|
|
21
|
-
import type { SwapKitValueType } from './swapKitNumber.ts';
|
|
22
|
-
|
|
23
|
-
type AssetValueParams = { decimal: number; value: SwapKitValueType } & (
|
|
24
|
-
| { chain: Chain; symbol: string }
|
|
25
|
-
| { identifier: string }
|
|
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
|
-
};
|
|
1
|
+
import { BaseDecimal, Chain, ChainToChainId } from "@swapkit/types";
|
|
2
|
+
|
|
3
|
+
import type { CommonAssetString } from "../helpers/asset.ts";
|
|
4
|
+
import { getAssetType, getCommonAssetInfo, getDecimal, isGasAsset } from "../helpers/asset.ts";
|
|
5
|
+
import { validateIdentifier } from "../helpers/validators.ts";
|
|
6
|
+
import type { TokenNames, TokenTax } from "../types.ts";
|
|
7
|
+
|
|
8
|
+
import type { NumberPrimitives } from "./bigIntArithmetics.ts";
|
|
9
|
+
import { BigIntArithmetics, formatBigIntToSafeValue } from "./bigIntArithmetics.ts";
|
|
10
|
+
import { SwapKitNumber, type SwapKitValueType } from "./swapKitNumber.ts";
|
|
11
|
+
|
|
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,102 +49,152 @@ 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");
|
|
74
|
+
|
|
75
|
+
const assetString =
|
|
76
|
+
chain === Chain.THORChain && symbol ? `${chain}.${ticker}/${symbol}` : urlAsset;
|
|
116
77
|
|
|
117
|
-
return
|
|
118
|
-
? new AssetValue({ decimal, identifier: tokenIdentifier, value })
|
|
119
|
-
: undefined;
|
|
78
|
+
return createAssetValue(assetString, value);
|
|
120
79
|
}
|
|
121
80
|
|
|
122
|
-
static
|
|
123
|
-
assetString
|
|
124
|
-
|
|
81
|
+
static fromString(assetString: string, value: NumberPrimitives = 0) {
|
|
82
|
+
return createAssetValue(assetString, value);
|
|
83
|
+
}
|
|
84
|
+
static fromIdentifier(
|
|
85
|
+
assetString:
|
|
86
|
+
| `${Chain}.${string}`
|
|
87
|
+
| `${Chain}/${string}`
|
|
88
|
+
| `${Chain}.${string}-${string}`
|
|
89
|
+
| TokenNames,
|
|
90
|
+
value: NumberPrimitives = 0,
|
|
125
91
|
) {
|
|
126
92
|
return createAssetValue(assetString, value);
|
|
127
93
|
}
|
|
128
94
|
|
|
129
|
-
static
|
|
130
|
-
const {
|
|
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
|
+
|
|
112
|
+
return new AssetValue({
|
|
113
|
+
tax,
|
|
114
|
+
value: safeValue(value, decimal),
|
|
115
|
+
identifier: isSynthetic ? assetString : identifier,
|
|
116
|
+
decimal: isSynthetic ? 8 : decimal,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
131
119
|
|
|
132
|
-
|
|
120
|
+
static async fromStringWithBase(
|
|
121
|
+
assetString: string,
|
|
122
|
+
value: NumberPrimitives = 0,
|
|
123
|
+
baseDecimal: number = BaseDecimal.THOR,
|
|
124
|
+
) {
|
|
125
|
+
const shiftedAmount = BigIntArithmetics.shiftDecimals({
|
|
126
|
+
value: SwapKitNumber.fromBigInt(BigInt(value)),
|
|
127
|
+
from: 0,
|
|
128
|
+
to: baseDecimal,
|
|
129
|
+
}).getBaseValue("string");
|
|
130
|
+
const assetValue = await AssetValue.fromString(assetString, value);
|
|
131
|
+
|
|
132
|
+
return assetValue.set(shiftedAmount);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
static
|
|
136
|
-
|
|
135
|
+
static fromStringWithBaseSync(
|
|
136
|
+
assetString: string,
|
|
137
|
+
value: NumberPrimitives = 0,
|
|
138
|
+
baseDecimal: number = BaseDecimal.THOR,
|
|
139
|
+
) {
|
|
140
|
+
const { chain, isSynthetic } = getAssetInfo(assetString);
|
|
141
|
+
const tokenInfo = staticTokensMap.get(assetString.toUpperCase() as TokenNames);
|
|
137
142
|
|
|
138
|
-
|
|
139
|
-
}
|
|
143
|
+
if (isSynthetic) return createSyntheticAssetValue(assetString, value);
|
|
140
144
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
const { tax, decimal, identifier } = tokenInfo || {
|
|
146
|
+
decimal: BaseDecimal[chain],
|
|
147
|
+
identifier: assetString,
|
|
148
|
+
};
|
|
144
149
|
|
|
145
|
-
return new AssetValue({
|
|
150
|
+
return new AssetValue({
|
|
151
|
+
tax,
|
|
152
|
+
value: safeValue(BigInt(value), baseDecimal),
|
|
153
|
+
identifier,
|
|
154
|
+
decimal,
|
|
155
|
+
});
|
|
146
156
|
}
|
|
147
157
|
|
|
148
|
-
static
|
|
149
|
-
const
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
static fromIdentifierSync(assetString: TokenNames, value: NumberPrimitives = 0) {
|
|
159
|
+
const { chain, isSynthetic } = getAssetInfo(assetString);
|
|
160
|
+
const tokenInfo = staticTokensMap.get(assetString);
|
|
161
|
+
|
|
162
|
+
if (isSynthetic) return createSyntheticAssetValue(assetString, value);
|
|
163
|
+
// TODO: write logger that will only run in dev mode with some flag
|
|
164
|
+
// if (!tokenInfo) {
|
|
165
|
+
// console.error(
|
|
166
|
+
// `Asset ${assetString} is not loaded. - Loading with base Chain. Use AssetValue.loadStaticAssets() to load it`,
|
|
167
|
+
// );
|
|
168
|
+
// }
|
|
169
|
+
|
|
170
|
+
const { tax, decimal, identifier } = tokenInfo || {
|
|
171
|
+
decimal: BaseDecimal[chain],
|
|
172
|
+
identifier: assetString,
|
|
173
|
+
};
|
|
174
|
+
return new AssetValue({ tax, decimal, identifier, value: safeValue(value, decimal) });
|
|
175
|
+
}
|
|
155
176
|
|
|
156
|
-
|
|
177
|
+
static fromChainOrSignature(assetString: CommonAssetString, value: NumberPrimitives = 0) {
|
|
178
|
+
const { decimal, identifier } = getCommonAssetInfo(assetString);
|
|
179
|
+
return new AssetValue({ value: safeValue(value, decimal), decimal, identifier });
|
|
157
180
|
}
|
|
158
181
|
|
|
159
|
-
static
|
|
182
|
+
static loadStaticAssets() {
|
|
160
183
|
return new Promise<{ ok: true } | { ok: false; message: string; error: any }>(
|
|
161
|
-
|
|
184
|
+
(resolve, reject) => {
|
|
162
185
|
try {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
acc.set(identifier as TokenNames, { identifier, decimal });
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
return acc;
|
|
179
|
-
},
|
|
180
|
-
new Map<TokenNames, { decimal: number; identifier: string }>(),
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
staticTokensMap = tokensMap;
|
|
184
|
-
|
|
185
|
-
resolve({ ok: true });
|
|
186
|
+
import("@swapkit/tokens").then((tokenPackages) => {
|
|
187
|
+
for (const tokenList of Object.values(tokenPackages)) {
|
|
188
|
+
for (const { identifier, chain, ...rest } of tokenList.tokens) {
|
|
189
|
+
staticTokensMap.set(identifier.toUpperCase() as TokenNames, {
|
|
190
|
+
identifier,
|
|
191
|
+
decimal: "decimals" in rest ? rest.decimals : BaseDecimal[chain as Chain],
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
resolve({ ok: true });
|
|
197
|
+
});
|
|
186
198
|
} catch (error) {
|
|
187
199
|
console.error(error);
|
|
188
200
|
reject({
|
|
@@ -197,46 +209,96 @@ export class AssetValue extends BigIntArithmetics {
|
|
|
197
209
|
}
|
|
198
210
|
}
|
|
199
211
|
|
|
200
|
-
export
|
|
212
|
+
export function getMinAmountByChain(chain: Chain) {
|
|
201
213
|
const asset = AssetValue.fromChainOrSignature(chain);
|
|
202
214
|
|
|
203
215
|
switch (chain) {
|
|
204
216
|
case Chain.Bitcoin:
|
|
205
217
|
case Chain.Litecoin:
|
|
206
218
|
case Chain.BitcoinCash:
|
|
207
|
-
return asset.
|
|
219
|
+
return asset.set(0.00010001);
|
|
208
220
|
|
|
209
221
|
case Chain.Dogecoin:
|
|
210
|
-
return asset.
|
|
222
|
+
return asset.set(1.00000001);
|
|
211
223
|
|
|
212
224
|
case Chain.Avalanche:
|
|
213
225
|
case Chain.Ethereum:
|
|
214
|
-
return asset.
|
|
226
|
+
return asset.set(0.00000001);
|
|
215
227
|
|
|
216
228
|
case Chain.THORChain:
|
|
217
229
|
case Chain.Maya:
|
|
218
|
-
return asset.
|
|
230
|
+
return asset.set(0);
|
|
231
|
+
|
|
232
|
+
case Chain.Cosmos:
|
|
233
|
+
return asset.set(0.000001);
|
|
219
234
|
|
|
220
235
|
default:
|
|
221
|
-
return asset.
|
|
236
|
+
return asset.set(0.00000001);
|
|
222
237
|
}
|
|
223
|
-
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function createAssetValue(identifier: string, value: NumberPrimitives = 0) {
|
|
241
|
+
validateIdentifier(identifier);
|
|
242
|
+
|
|
243
|
+
const staticToken = staticTokensMap.get(identifier.toUpperCase() as TokenNames);
|
|
244
|
+
const decimal = staticToken?.decimal || (await getDecimal(getAssetInfo(identifier)));
|
|
245
|
+
if (!staticToken) {
|
|
246
|
+
staticTokensMap.set(identifier.toUpperCase() as TokenNames, { identifier, decimal });
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return new AssetValue({ decimal, value: safeValue(value, decimal), identifier });
|
|
250
|
+
}
|
|
224
251
|
|
|
225
|
-
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
252
|
+
function createSyntheticAssetValue(identifier: string, value: NumberPrimitives = 0) {
|
|
253
|
+
const [synthChain, symbol] =
|
|
254
|
+
identifier.split(".")[0].toUpperCase() === Chain.THORChain
|
|
255
|
+
? identifier.split(".").slice(1).join().split("/")
|
|
256
|
+
: identifier.split("/");
|
|
230
257
|
|
|
231
|
-
|
|
232
|
-
|
|
258
|
+
if (!(synthChain && symbol)) throw new Error("Invalid asset identifier");
|
|
259
|
+
|
|
260
|
+
return new AssetValue({
|
|
261
|
+
decimal: 8,
|
|
262
|
+
value: safeValue(value, 8),
|
|
263
|
+
identifier: `${Chain.THORChain}.${synthChain}/${symbol}`,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function safeValue(value: NumberPrimitives, decimal: number) {
|
|
268
|
+
return typeof value === "bigint"
|
|
269
|
+
? formatBigIntToSafeValue({ value, bigIntDecimal: decimal, decimal })
|
|
270
|
+
: value;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// TODO refactor & split into smaller functions
|
|
274
|
+
function getAssetInfo(identifier: string) {
|
|
275
|
+
const isSynthetic = identifier.slice(0, 14).includes("/");
|
|
276
|
+
|
|
277
|
+
const [synthChain, synthSymbol] =
|
|
278
|
+
identifier.split(".")[0].toUpperCase() === Chain.THORChain
|
|
279
|
+
? identifier.split(".").slice(1).join().split("/")
|
|
280
|
+
: identifier.split("/");
|
|
281
|
+
|
|
282
|
+
if (isSynthetic && !(synthChain && synthSymbol)) throw new Error("Invalid asset identifier");
|
|
283
|
+
|
|
284
|
+
const adjustedIdentifier =
|
|
285
|
+
identifier.includes(".") && !isSynthetic ? identifier : `${Chain.THORChain}.${synthSymbol}`;
|
|
286
|
+
|
|
287
|
+
const [chain, ...rest] = adjustedIdentifier.split(".") as [Chain, string];
|
|
288
|
+
const [ticker, address] = (isSynthetic ? synthSymbol : rest.join(".")).split("-") as [
|
|
289
|
+
string,
|
|
290
|
+
string?,
|
|
291
|
+
];
|
|
292
|
+
const symbol = isSynthetic ? synthSymbol : rest.join(".");
|
|
233
293
|
|
|
234
294
|
return {
|
|
235
295
|
address: address?.toLowerCase(),
|
|
236
296
|
chain,
|
|
237
297
|
isGasAsset: isGasAsset({ chain, symbol }),
|
|
238
298
|
isSynthetic,
|
|
239
|
-
symbol:
|
|
240
|
-
|
|
299
|
+
symbol:
|
|
300
|
+
(isSynthetic ? `${synthChain}/` : "") +
|
|
301
|
+
(address ? `${ticker}-${address?.toLowerCase() ?? ""}` : symbol),
|
|
302
|
+
ticker,
|
|
241
303
|
};
|
|
242
|
-
}
|
|
304
|
+
}
|