@swapkit/helpers 1.0.0-rc.11 → 1.0.0-rc.111

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.
Files changed (42) hide show
  1. package/dist/index.js +2900 -0
  2. package/dist/index.js.map +31 -0
  3. package/package.json +26 -37
  4. package/src/helpers/__tests__/asset.test.ts +186 -103
  5. package/src/helpers/__tests__/memo.test.ts +53 -41
  6. package/src/helpers/__tests__/others.test.ts +44 -37
  7. package/src/helpers/__tests__/validators.test.ts +24 -0
  8. package/src/helpers/asset.ts +184 -95
  9. package/src/helpers/derivationPath.ts +53 -0
  10. package/src/helpers/liquidity.ts +50 -43
  11. package/src/helpers/memo.ts +34 -31
  12. package/src/helpers/others.ts +46 -12
  13. package/src/helpers/validators.ts +15 -6
  14. package/src/helpers/web3wallets.ts +200 -0
  15. package/src/index.ts +14 -9
  16. package/src/modules/__tests__/assetValue.test.ts +486 -129
  17. package/src/modules/__tests__/bigIntArithmetics.test.ts +30 -0
  18. package/src/modules/__tests__/swapKitNumber.test.ts +306 -183
  19. package/src/modules/assetValue.ts +220 -162
  20. package/src/modules/bigIntArithmetics.ts +214 -165
  21. package/src/modules/requestClient.ts +38 -0
  22. package/src/modules/swapKitError.ts +41 -5
  23. package/src/modules/swapKitNumber.ts +1 -1
  24. package/src/types/abis/erc20.ts +99 -0
  25. package/src/types/abis/mayaEvmVaults.ts +331 -0
  26. package/src/types/abis/tcEthVault.ts +496 -0
  27. package/src/types/chains.ts +226 -0
  28. package/src/types/commonTypes.ts +123 -0
  29. package/src/types/derivationPath.ts +58 -0
  30. package/src/types/errors/apiV1.ts +0 -0
  31. package/src/types/index.ts +12 -0
  32. package/src/types/network.ts +45 -0
  33. package/src/types/quotes.ts +391 -0
  34. package/src/types/radix.ts +14 -0
  35. package/src/types/sdk.ts +126 -0
  36. package/src/types/tokens.ts +30 -0
  37. package/src/types/wallet.ts +72 -0
  38. package/LICENSE +0 -201
  39. package/dist/index.cjs +0 -1
  40. package/dist/index.d.ts +0 -356
  41. package/dist/index.es.js +0 -1071
  42. package/src/helpers/request.ts +0 -16
@@ -1,200 +1,201 @@
1
- import type {
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';
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 type { NumberPrimitives } from './bigIntArithmetics.ts';
21
- import { BigIntArithmetics, formatBigIntToSafeValue } from './bigIntArithmetics.ts';
22
- import type { SwapKitValueType } from './swapKitNumber.ts';
23
-
24
- const safeValue = (value: NumberPrimitives, decimal: number) =>
25
- typeof value === 'bigint'
26
- ? formatBigIntToSafeValue({ value, bigIntDecimal: decimal, decimal })
27
- : value;
28
-
29
- type AssetValueParams = { decimal: number; value: SwapKitValueType } & (
30
- | { chain: Chain; symbol: string }
31
- | { identifier: string }
32
- );
33
-
34
- type TCTokenNames = (typeof ThorchainList)['tokens'][number]['identifier'];
35
-
36
- type TokenNames =
37
- | TCTokenNames
38
- | (typeof CoinGeckoList)['tokens'][number]['identifier']
39
- | (typeof MayaList)['tokens'][number]['identifier']
40
- | (typeof PancakeswapETHList)['tokens'][number]['identifier']
41
- | (typeof PancakeswapList)['tokens'][number]['identifier']
42
- | (typeof PangolinList)['tokens'][number]['identifier']
43
- | (typeof StargateARBList)['tokens'][number]['identifier']
44
- | (typeof SushiswapList)['tokens'][number]['identifier']
45
- | (typeof TraderjoeList)['tokens'][number]['identifier']
46
- | (typeof WoofiList)['tokens'][number]['identifier']
47
- | (typeof UniswapList)['tokens'][number]['identifier'];
48
-
49
- let staticTokensMap: Map<TokenNames, { decimal: number; identifier: string }> | undefined;
50
-
51
- const getStaticToken = (identifier: TokenNames) => {
52
- if (!staticTokensMap) {
53
- throw new Error('Static assets not loaded, call await AssetValue.loadStaticAssets() first');
54
- }
55
- const tokenInfo = staticTokensMap.get(identifier.toUpperCase() as TokenNames);
1
+ import type { CommonAssetString } from "../helpers/asset.ts";
2
+ import { getAssetType, getCommonAssetInfo, getDecimal, isGasAsset } from "../helpers/asset.ts";
3
+ import { validateIdentifier } from "../helpers/validators.ts";
4
+ import { BaseDecimal, Chain, type ChainId, ChainToChainId } from "../types/chains.ts";
5
+ import type { TokenNames, TokenTax } from "../types/tokens.ts";
56
6
 
57
- return tokenInfo || { decimal: BaseDecimal.THOR, identifier: '' };
58
- };
7
+ import type { NumberPrimitives } from "./bigIntArithmetics.ts";
8
+ import { BigIntArithmetics, formatBigIntToSafeValue } from "./bigIntArithmetics.ts";
9
+ import { SwapKitNumber, type SwapKitValueType } from "./swapKitNumber.ts";
59
10
 
60
- const createAssetValue = async (assetString: string, value: NumberPrimitives = 0) => {
61
- validateIdentifier(assetString);
62
-
63
- const decimal = await getDecimal(getAssetInfo(assetString));
64
- const parsedValue = safeValue(value, decimal);
65
-
66
- return new AssetValue({ decimal, value: parsedValue, identifier: assetString });
67
- };
11
+ const staticTokensMap = new Map<
12
+ TokenNames,
13
+ { tax?: TokenTax; decimal: number; identifier: string }
14
+ >();
68
15
 
69
16
  export class AssetValue extends BigIntArithmetics {
70
17
  address?: string;
71
18
  chain: Chain;
72
- isSynthetic = false;
73
19
  isGasAsset = false;
20
+ isSynthetic = false;
74
21
  symbol: string;
22
+ tax?: TokenTax;
75
23
  ticker: string;
76
24
  type: ReturnType<typeof getAssetType>;
25
+ chainId: ChainId;
77
26
 
78
- constructor(params: AssetValueParams) {
79
- super(
80
- params.value instanceof BigIntArithmetics
81
- ? params.value
82
- : { decimal: params.decimal, value: params.value },
83
- );
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 });
84
39
 
85
- const identifier =
86
- 'identifier' in params ? params.identifier : `${params.chain}.${params.symbol}`;
87
- const assetInfo = getAssetInfo(identifier);
40
+ const assetInfo = getAssetInfo(identifier || `${chain}.${symbol}`);
88
41
 
89
42
  this.type = getAssetType(assetInfo);
43
+ this.tax = tax;
90
44
  this.chain = assetInfo.chain;
91
45
  this.ticker = assetInfo.ticker;
92
46
  this.symbol = assetInfo.symbol;
93
47
  this.address = assetInfo.address;
94
48
  this.isSynthetic = assetInfo.isSynthetic;
95
49
  this.isGasAsset = assetInfo.isGasAsset;
50
+ this.chainId = ChainToChainId[assetInfo.chain];
96
51
  }
97
52
 
98
- get assetValue() {
99
- return `${this.getValue('string')} ${this.ticker}`;
53
+ toString() {
54
+ return this.isSynthetic ? this.symbol : `${this.chain}.${this.symbol}`;
100
55
  }
101
56
 
102
- toString(short = false) {
103
- // THOR.RUNE | ETH/ETH
104
- const shortFormat = this.isSynthetic ? this.ticker : `${this.chain}.${this.ticker}`;
105
-
106
- return short
107
- ? shortFormat
108
- : // THOR.ETH/ETH | ETH.USDT-0x1234567890
109
- `${this.chain}.${this.symbol}`;
57
+ toUrl() {
58
+ return this.isSynthetic ? `${this.chain}.${this.symbol.replace("/", ".")}` : this.toString();
110
59
  }
111
60
 
112
- eq({ chain, symbol }: { chain: Chain; symbol: string }) {
61
+ eqAsset({ chain, symbol }: { chain: Chain; symbol: string }) {
113
62
  return this.chain === chain && this.symbol === symbol;
114
63
  }
115
64
 
116
- static async fromString(assetString: string, value: NumberPrimitives = 0) {
117
- return createAssetValue(assetString, value);
65
+ eq(assetValue: AssetValue) {
66
+ return this.eqAsset(assetValue) && this.eqValue(assetValue);
118
67
  }
119
68
 
120
- static fromStringSync(assetString: string, value: NumberPrimitives = 0) {
121
- const { decimal, identifier: tokenIdentifier } = getStaticToken(
122
- assetString as unknown as TokenNames,
123
- );
69
+ // THOR.RUNE
70
+ // THOR.ETH.ETH
71
+ // ETH.THOR-0x1234567890
72
+ static fromUrl(urlAsset: string, value: NumberPrimitives = 0) {
73
+ const [chain, ticker, symbol] = urlAsset.split(".");
74
+ if (!(chain && ticker)) throw new Error("Invalid asset url");
124
75
 
125
- const parsedValue = safeValue(value, decimal);
76
+ const assetString =
77
+ chain === Chain.THORChain && symbol ? `${chain}.${ticker}/${symbol}` : urlAsset;
126
78
 
127
- return tokenIdentifier
128
- ? new AssetValue({ decimal, identifier: tokenIdentifier, value: parsedValue })
129
- : undefined;
79
+ return createAssetValue(assetString, value);
130
80
  }
131
81
 
132
- static async fromIdentifier(
133
- assetString: `${Chain}.${string}` | `${Chain}/${string}` | `${Chain}.${string}-${string}`,
82
+ static fromString(assetString: string, value: NumberPrimitives = 0) {
83
+ return createAssetValue(assetString, value);
84
+ }
85
+ static fromIdentifier(
86
+ assetString:
87
+ | `${Chain}.${string}`
88
+ | `${Chain}/${string}`
89
+ | `${Chain}.${string}-${string}`
90
+ | TokenNames,
134
91
  value: NumberPrimitives = 0,
135
92
  ) {
136
93
  return createAssetValue(assetString, value);
137
94
  }
138
95
 
139
- static fromIdentifierSync(identifier: TokenNames, value: NumberPrimitives = 0) {
140
- const { decimal, identifier: tokenIdentifier } = getStaticToken(identifier);
141
- const parsedValue = safeValue(value, decimal);
96
+ static fromStringSync(assetString: string, value: NumberPrimitives = 0) {
97
+ const { chain, isSynthetic } = getAssetInfo(assetString);
98
+ const tokenInfo = staticTokensMap.get(assetString.toUpperCase() as TokenNames);
99
+
100
+ if (isSynthetic) return createSyntheticAssetValue(assetString, value);
101
+ // TODO: write logger that will only run in dev mode with some flag
102
+ // if (!tokenInfo) {
103
+ // console.error(
104
+ // `Asset ${assetString} is not loaded. Use AssetValue.loadStaticAssets() to load it`,
105
+ // );
106
+ // }
107
+
108
+ const { tax, decimal, identifier } = tokenInfo || {
109
+ decimal: BaseDecimal[chain],
110
+ identifier: assetString,
111
+ };
112
+
113
+ return new AssetValue({
114
+ tax,
115
+ value: safeValue(value, decimal),
116
+ identifier: isSynthetic ? assetString : identifier,
117
+ decimal: isSynthetic ? 8 : decimal,
118
+ });
119
+ }
142
120
 
143
- return new AssetValue({ decimal, identifier: tokenIdentifier, value: parsedValue });
121
+ static async fromStringWithBase(
122
+ assetString: string,
123
+ value: NumberPrimitives = 0,
124
+ baseDecimal: number = BaseDecimal.THOR,
125
+ ) {
126
+ const shiftedAmount = BigIntArithmetics.shiftDecimals({
127
+ value: SwapKitNumber.fromBigInt(BigInt(value)),
128
+ from: 0,
129
+ to: baseDecimal,
130
+ }).getBaseValue("string");
131
+ const assetValue = await AssetValue.fromString(assetString, value);
132
+
133
+ return assetValue.set(shiftedAmount);
144
134
  }
145
135
 
146
- static fromChainOrSignature(assetString: CommonAssetString, value: NumberPrimitives = 0) {
147
- const { decimal, identifier } = getCommonAssetInfo(assetString);
148
- const parsedValue = safeValue(value, decimal);
136
+ static fromStringWithBaseSync(
137
+ assetString: string,
138
+ value: NumberPrimitives = 0,
139
+ baseDecimal: number = BaseDecimal.THOR,
140
+ ) {
141
+ const { chain, isSynthetic } = getAssetInfo(assetString);
142
+ const tokenInfo = staticTokensMap.get(assetString.toUpperCase() as TokenNames);
149
143
 
150
- return new AssetValue({ value: parsedValue, decimal, identifier });
151
- }
144
+ if (isSynthetic) return createSyntheticAssetValue(assetString, value);
152
145
 
153
- static async fromTCQuote(identifier: TCTokenNames, value: NumberPrimitives = 0) {
154
- const decimal = await getDecimal(getAssetInfo(identifier));
155
- const shiftedValue = this.shiftDecimals({ value, from: BaseDecimal.THOR, to: decimal });
146
+ const { tax, decimal, identifier } = tokenInfo || {
147
+ decimal: BaseDecimal[chain],
148
+ identifier: assetString,
149
+ };
156
150
 
157
- return new AssetValue({ value: shiftedValue, identifier, decimal });
151
+ return new AssetValue({
152
+ tax,
153
+ value: safeValue(BigInt(value), baseDecimal),
154
+ identifier,
155
+ decimal,
156
+ });
158
157
  }
159
158
 
160
- static fromTCQuoteStatic(identifier: TCTokenNames, value: NumberPrimitives = 0) {
161
- const tokenInfo = getStaticToken(identifier);
162
- const shiftedValue = this.shiftDecimals({
163
- value,
164
- from: BaseDecimal.THOR,
165
- to: tokenInfo.decimal,
166
- });
159
+ static fromIdentifierSync(assetString: TokenNames, value: NumberPrimitives = 0) {
160
+ const { chain, isSynthetic } = getAssetInfo(assetString);
161
+ const tokenInfo = staticTokensMap.get(assetString);
162
+
163
+ if (isSynthetic) return createSyntheticAssetValue(assetString, value);
164
+ // TODO: write logger that will only run in dev mode with some flag
165
+ // if (!tokenInfo) {
166
+ // console.error(
167
+ // `Asset ${assetString} is not loaded. - Loading with base Chain. Use AssetValue.loadStaticAssets() to load it`,
168
+ // );
169
+ // }
170
+
171
+ const { tax, decimal, identifier } = tokenInfo || {
172
+ decimal: BaseDecimal[chain],
173
+ identifier: assetString,
174
+ };
175
+ return new AssetValue({ tax, decimal, identifier, value: safeValue(value, decimal) });
176
+ }
167
177
 
168
- return new AssetValue({ ...tokenInfo, value: shiftedValue });
178
+ static fromChainOrSignature(assetString: CommonAssetString, value: NumberPrimitives = 0) {
179
+ const { decimal, identifier } = getCommonAssetInfo(assetString);
180
+ return new AssetValue({ value: safeValue(value, decimal), decimal, identifier });
169
181
  }
170
182
 
171
- static async loadStaticAssets() {
172
- return new Promise<{ ok: true } | { ok: false; message: string; error: any }>(
173
- async (resolve, reject) => {
183
+ static loadStaticAssets() {
184
+ return new Promise<{ ok: true } | { ok: false; message: string; error: Todo }>(
185
+ (resolve, reject) => {
174
186
  try {
175
- const {
176
- // Omit ThorchainList from import to avoid decimals conflict (TC uses 8 for all)
177
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
178
- ThorchainList: _ThorchainList,
179
- NativeList,
180
- ...tokensPackage
181
- } = await import('@swapkit/tokens');
182
- const tokensMap = [NativeList, ...Object.values(tokensPackage)].reduce(
183
- (acc, { tokens }) => {
184
- tokens.forEach(({ identifier, chain, ...rest }) => {
185
- const decimal = 'decimals' in rest ? rest.decimals : BaseDecimal[chain as Chain];
186
-
187
- acc.set(identifier as TokenNames, { identifier, decimal });
188
- });
189
-
190
- return acc;
191
- },
192
- new Map<TokenNames, { decimal: number; identifier: string }>(),
193
- );
194
-
195
- staticTokensMap = tokensMap;
196
-
197
- resolve({ ok: true });
187
+ import("@swapkit/tokens").then((tokenPackages) => {
188
+ for (const tokenList of Object.values(tokenPackages)) {
189
+ for (const { identifier, chain, ...rest } of tokenList.tokens) {
190
+ staticTokensMap.set(identifier.toUpperCase() as TokenNames, {
191
+ identifier,
192
+ decimal: "decimals" in rest ? rest.decimals : BaseDecimal[chain as Chain],
193
+ });
194
+ }
195
+ }
196
+
197
+ resolve({ ok: true });
198
+ });
198
199
  } catch (error) {
199
200
  console.error(error);
200
201
  reject({
@@ -209,46 +210,103 @@ export class AssetValue extends BigIntArithmetics {
209
210
  }
210
211
  }
211
212
 
212
- export const getMinAmountByChain = (chain: Chain) => {
213
+ export function getMinAmountByChain(chain: Chain) {
213
214
  const asset = AssetValue.fromChainOrSignature(chain);
214
215
 
215
216
  switch (chain) {
216
217
  case Chain.Bitcoin:
217
218
  case Chain.Litecoin:
218
219
  case Chain.BitcoinCash:
219
- return asset.add(10001);
220
+ return asset.set(0.00010001);
220
221
 
221
222
  case Chain.Dogecoin:
222
- return asset.add(100000001);
223
+ return asset.set(1.00000001);
223
224
 
224
225
  case Chain.Avalanche:
225
226
  case Chain.Ethereum:
226
- return asset.add(10 * 10 ** 9);
227
+ return asset.set(0.00000001);
227
228
 
228
229
  case Chain.THORChain:
229
230
  case Chain.Maya:
230
- return asset.add(0);
231
+ return asset.set(0);
232
+
233
+ case Chain.Cosmos:
234
+ return asset.set(0.000001);
231
235
 
232
236
  default:
233
- return asset.add(1);
237
+ return asset.set(0.00000001);
234
238
  }
235
- };
239
+ }
240
+
241
+ async function createAssetValue(identifier: string, value: NumberPrimitives = 0) {
242
+ validateIdentifier(identifier);
243
+
244
+ const staticToken = staticTokensMap.get(identifier.toUpperCase() as TokenNames);
245
+ const decimal = staticToken?.decimal || (await getDecimal(getAssetInfo(identifier)));
246
+ if (!staticToken) {
247
+ staticTokensMap.set(identifier.toUpperCase() as TokenNames, { identifier, decimal });
248
+ }
249
+
250
+ return new AssetValue({ decimal, value: safeValue(value, decimal), identifier });
251
+ }
236
252
 
237
- const getAssetInfo = (identifier: string) => {
238
- const isSynthetic = identifier.slice(0, 14).includes('/');
239
- const adjustedIdentifier = identifier.includes('.')
240
- ? identifier
241
- : `${Chain.THORChain}.${identifier}`;
253
+ function createSyntheticAssetValue(identifier: string, value: NumberPrimitives = 0) {
254
+ const [synthChain, symbol] =
255
+ identifier.split(".")?.[0]?.toUpperCase() === Chain.THORChain
256
+ ? identifier.split(".").slice(1).join().split("/")
257
+ : identifier.split("/");
242
258
 
243
- const [chain, symbol] = adjustedIdentifier.split('.') as [Chain, string];
244
- const [ticker, address] = symbol.split('-') as [string, string?];
259
+ if (!(synthChain && symbol)) throw new Error("Invalid asset identifier");
260
+
261
+ return new AssetValue({
262
+ decimal: 8,
263
+ value: safeValue(value, 8),
264
+ identifier: `${Chain.THORChain}.${synthChain}/${symbol}`,
265
+ });
266
+ }
267
+
268
+ function safeValue(value: NumberPrimitives, decimal: number) {
269
+ return typeof value === "bigint"
270
+ ? formatBigIntToSafeValue({ value, bigIntDecimal: decimal, decimal })
271
+ : value;
272
+ }
273
+
274
+ // TODO refactor & split into smaller functions
275
+ function getAssetInfo(identifier: string) {
276
+ const isSynthetic = identifier.slice(0, 14).includes("/");
277
+
278
+ const isThorchain = identifier.split(".")?.[0]?.toUpperCase() === Chain.THORChain;
279
+ const isMaya = identifier.split(".")?.[0]?.toUpperCase() === Chain.Maya;
280
+
281
+ const [synthChain, synthSymbol = ""] =
282
+ isThorchain || isMaya
283
+ ? identifier.split(".").slice(1).join().split("/")
284
+ : identifier.split("/");
285
+
286
+ if (isSynthetic && !(synthChain && synthSymbol)) throw new Error("Invalid asset identifier");
287
+
288
+ const adjustedIdentifier =
289
+ identifier.includes(".") && !isSynthetic
290
+ ? identifier
291
+ : `${isMaya ? Chain.Maya : Chain.THORChain}.${synthSymbol}`;
292
+
293
+ const [chain, ...rest] = adjustedIdentifier.split(".") as [Chain, string];
294
+
295
+ const symbol = isSynthetic ? synthSymbol : rest.join(".");
296
+ const splitSymbol = symbol.split("-");
297
+ const ticker = (
298
+ splitSymbol.length === 1 ? splitSymbol[0] : splitSymbol.slice(0, -1).join("-")
299
+ ) as string;
300
+ const address = splitSymbol.length === 1 ? undefined : splitSymbol[splitSymbol.length - 1];
245
301
 
246
302
  return {
247
303
  address: address?.toLowerCase(),
248
304
  chain,
249
305
  isGasAsset: isGasAsset({ chain, symbol }),
250
306
  isSynthetic,
251
- symbol: address ? `${ticker}-${address?.toLowerCase() ?? ''}` : symbol,
252
- ticker: isSynthetic ? symbol : ticker,
307
+ symbol:
308
+ (isSynthetic ? `${synthChain}/` : "") +
309
+ (address ? `${ticker}-${address?.toLowerCase() ?? ""}` : symbol),
310
+ ticker,
253
311
  };
254
- };
312
+ }