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

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 +2897 -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 +453 -120
  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 +217 -163
  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,197 @@
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
61
  eq({ 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);
118
- }
119
-
120
- static fromStringSync(assetString: string, value: NumberPrimitives = 0) {
121
- const { decimal, identifier: tokenIdentifier } = getStaticToken(
122
- assetString as unknown as TokenNames,
123
- );
65
+ // THOR.RUNE
66
+ // THOR.ETH.ETH
67
+ // ETH.THOR-0x1234567890
68
+ static fromUrl(urlAsset: string, value: NumberPrimitives = 0) {
69
+ const [chain, ticker, symbol] = urlAsset.split(".");
70
+ if (!(chain && ticker)) throw new Error("Invalid asset url");
124
71
 
125
- const parsedValue = safeValue(value, decimal);
72
+ const assetString =
73
+ chain === Chain.THORChain && symbol ? `${chain}.${ticker}/${symbol}` : urlAsset;
126
74
 
127
- return tokenIdentifier
128
- ? new AssetValue({ decimal, identifier: tokenIdentifier, value: parsedValue })
129
- : undefined;
75
+ return createAssetValue(assetString, value);
130
76
  }
131
77
 
132
- static async fromIdentifier(
133
- assetString: `${Chain}.${string}` | `${Chain}/${string}` | `${Chain}.${string}-${string}`,
78
+ static fromString(assetString: string, value: NumberPrimitives = 0) {
79
+ return createAssetValue(assetString, value);
80
+ }
81
+ static fromIdentifier(
82
+ assetString:
83
+ | `${Chain}.${string}`
84
+ | `${Chain}/${string}`
85
+ | `${Chain}.${string}-${string}`
86
+ | TokenNames,
134
87
  value: NumberPrimitives = 0,
135
88
  ) {
136
89
  return createAssetValue(assetString, value);
137
90
  }
138
91
 
139
- static fromIdentifierSync(identifier: TokenNames, value: NumberPrimitives = 0) {
140
- const { decimal, identifier: tokenIdentifier } = getStaticToken(identifier);
141
- const parsedValue = safeValue(value, decimal);
92
+ static fromStringSync(assetString: string, value: NumberPrimitives = 0) {
93
+ const { chain, isSynthetic } = getAssetInfo(assetString);
94
+ const tokenInfo = staticTokensMap.get(assetString.toUpperCase() as TokenNames);
95
+
96
+ if (isSynthetic) return createSyntheticAssetValue(assetString, value);
97
+ // TODO: write logger that will only run in dev mode with some flag
98
+ // if (!tokenInfo) {
99
+ // console.error(
100
+ // `Asset ${assetString} is not loaded. Use AssetValue.loadStaticAssets() to load it`,
101
+ // );
102
+ // }
103
+
104
+ const { tax, decimal, identifier } = tokenInfo || {
105
+ decimal: BaseDecimal[chain],
106
+ identifier: assetString,
107
+ };
108
+
109
+ return new AssetValue({
110
+ tax,
111
+ value: safeValue(value, decimal),
112
+ identifier: isSynthetic ? assetString : identifier,
113
+ decimal: isSynthetic ? 8 : decimal,
114
+ });
115
+ }
142
116
 
143
- return new AssetValue({ decimal, identifier: tokenIdentifier, value: parsedValue });
117
+ static async fromStringWithBase(
118
+ assetString: string,
119
+ value: NumberPrimitives = 0,
120
+ baseDecimal: number = BaseDecimal.THOR,
121
+ ) {
122
+ const shiftedAmount = BigIntArithmetics.shiftDecimals({
123
+ value: SwapKitNumber.fromBigInt(BigInt(value)),
124
+ from: 0,
125
+ to: baseDecimal,
126
+ }).getBaseValue("string");
127
+ const assetValue = await AssetValue.fromString(assetString, value);
128
+
129
+ return assetValue.set(shiftedAmount);
144
130
  }
145
131
 
146
- static fromChainOrSignature(assetString: CommonAssetString, value: NumberPrimitives = 0) {
147
- const { decimal, identifier } = getCommonAssetInfo(assetString);
148
- const parsedValue = safeValue(value, decimal);
132
+ static fromStringWithBaseSync(
133
+ assetString: string,
134
+ value: NumberPrimitives = 0,
135
+ baseDecimal: number = BaseDecimal.THOR,
136
+ ) {
137
+ const { chain, isSynthetic } = getAssetInfo(assetString);
138
+ const tokenInfo = staticTokensMap.get(assetString.toUpperCase() as TokenNames);
149
139
 
150
- return new AssetValue({ value: parsedValue, decimal, identifier });
151
- }
140
+ if (isSynthetic) return createSyntheticAssetValue(assetString, value);
152
141
 
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 });
142
+ const { tax, decimal, identifier } = tokenInfo || {
143
+ decimal: BaseDecimal[chain],
144
+ identifier: assetString,
145
+ };
156
146
 
157
- return new AssetValue({ value: shiftedValue, identifier, decimal });
147
+ return new AssetValue({
148
+ tax,
149
+ value: safeValue(BigInt(value), baseDecimal),
150
+ identifier,
151
+ decimal,
152
+ });
158
153
  }
159
154
 
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
- });
155
+ static fromIdentifierSync(assetString: TokenNames, value: NumberPrimitives = 0) {
156
+ const { chain, isSynthetic } = getAssetInfo(assetString);
157
+ const tokenInfo = staticTokensMap.get(assetString);
158
+
159
+ if (isSynthetic) return createSyntheticAssetValue(assetString, value);
160
+ // TODO: write logger that will only run in dev mode with some flag
161
+ // if (!tokenInfo) {
162
+ // console.error(
163
+ // `Asset ${assetString} is not loaded. - Loading with base Chain. Use AssetValue.loadStaticAssets() to load it`,
164
+ // );
165
+ // }
166
+
167
+ const { tax, decimal, identifier } = tokenInfo || {
168
+ decimal: BaseDecimal[chain],
169
+ identifier: assetString,
170
+ };
171
+ return new AssetValue({ tax, decimal, identifier, value: safeValue(value, decimal) });
172
+ }
167
173
 
168
- return new AssetValue({ ...tokenInfo, value: shiftedValue });
174
+ static fromChainOrSignature(assetString: CommonAssetString, value: NumberPrimitives = 0) {
175
+ const { decimal, identifier } = getCommonAssetInfo(assetString);
176
+ return new AssetValue({ value: safeValue(value, decimal), decimal, identifier });
169
177
  }
170
178
 
171
- static async loadStaticAssets() {
172
- return new Promise<{ ok: true } | { ok: false; message: string; error: any }>(
173
- async (resolve, reject) => {
179
+ static loadStaticAssets() {
180
+ return new Promise<{ ok: true } | { ok: false; message: string; error: Todo }>(
181
+ (resolve, reject) => {
174
182
  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 });
183
+ import("@swapkit/tokens").then((tokenPackages) => {
184
+ for (const tokenList of Object.values(tokenPackages)) {
185
+ for (const { identifier, chain, ...rest } of tokenList.tokens) {
186
+ staticTokensMap.set(identifier.toUpperCase() as TokenNames, {
187
+ identifier,
188
+ decimal: "decimals" in rest ? rest.decimals : BaseDecimal[chain as Chain],
189
+ });
190
+ }
191
+ }
192
+
193
+ resolve({ ok: true });
194
+ });
198
195
  } catch (error) {
199
196
  console.error(error);
200
197
  reject({
@@ -209,46 +206,103 @@ export class AssetValue extends BigIntArithmetics {
209
206
  }
210
207
  }
211
208
 
212
- export const getMinAmountByChain = (chain: Chain) => {
209
+ export function getMinAmountByChain(chain: Chain) {
213
210
  const asset = AssetValue.fromChainOrSignature(chain);
214
211
 
215
212
  switch (chain) {
216
213
  case Chain.Bitcoin:
217
214
  case Chain.Litecoin:
218
215
  case Chain.BitcoinCash:
219
- return asset.add(10001);
216
+ return asset.set(0.00010001);
220
217
 
221
218
  case Chain.Dogecoin:
222
- return asset.add(100000001);
219
+ return asset.set(1.00000001);
223
220
 
224
221
  case Chain.Avalanche:
225
222
  case Chain.Ethereum:
226
- return asset.add(10 * 10 ** 9);
223
+ return asset.set(0.00000001);
227
224
 
228
225
  case Chain.THORChain:
229
226
  case Chain.Maya:
230
- return asset.add(0);
227
+ return asset.set(0);
228
+
229
+ case Chain.Cosmos:
230
+ return asset.set(0.000001);
231
231
 
232
232
  default:
233
- return asset.add(1);
233
+ return asset.set(0.00000001);
234
234
  }
235
- };
235
+ }
236
+
237
+ async function createAssetValue(identifier: string, value: NumberPrimitives = 0) {
238
+ validateIdentifier(identifier);
239
+
240
+ const staticToken = staticTokensMap.get(identifier.toUpperCase() as TokenNames);
241
+ const decimal = staticToken?.decimal || (await getDecimal(getAssetInfo(identifier)));
242
+ if (!staticToken) {
243
+ staticTokensMap.set(identifier.toUpperCase() as TokenNames, { identifier, decimal });
244
+ }
245
+
246
+ return new AssetValue({ decimal, value: safeValue(value, decimal), identifier });
247
+ }
236
248
 
237
- const getAssetInfo = (identifier: string) => {
238
- const isSynthetic = identifier.slice(0, 14).includes('/');
239
- const adjustedIdentifier = identifier.includes('.')
240
- ? identifier
241
- : `${Chain.THORChain}.${identifier}`;
249
+ function createSyntheticAssetValue(identifier: string, value: NumberPrimitives = 0) {
250
+ const [synthChain, symbol] =
251
+ identifier.split(".")?.[0]?.toUpperCase() === Chain.THORChain
252
+ ? identifier.split(".").slice(1).join().split("/")
253
+ : identifier.split("/");
242
254
 
243
- const [chain, symbol] = adjustedIdentifier.split('.') as [Chain, string];
244
- const [ticker, address] = symbol.split('-') as [string, string?];
255
+ if (!(synthChain && symbol)) throw new Error("Invalid asset identifier");
256
+
257
+ return new AssetValue({
258
+ decimal: 8,
259
+ value: safeValue(value, 8),
260
+ identifier: `${Chain.THORChain}.${synthChain}/${symbol}`,
261
+ });
262
+ }
263
+
264
+ function safeValue(value: NumberPrimitives, decimal: number) {
265
+ return typeof value === "bigint"
266
+ ? formatBigIntToSafeValue({ value, bigIntDecimal: decimal, decimal })
267
+ : value;
268
+ }
269
+
270
+ // TODO refactor & split into smaller functions
271
+ function getAssetInfo(identifier: string) {
272
+ const isSynthetic = identifier.slice(0, 14).includes("/");
273
+
274
+ const isThorchain = identifier.split(".")?.[0]?.toUpperCase() === Chain.THORChain;
275
+ const isMaya = identifier.split(".")?.[0]?.toUpperCase() === Chain.Maya;
276
+
277
+ const [synthChain, synthSymbol = ""] =
278
+ isThorchain || isMaya
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
286
+ ? identifier
287
+ : `${isMaya ? Chain.Maya : Chain.THORChain}.${synthSymbol}`;
288
+
289
+ const [chain, ...rest] = adjustedIdentifier.split(".") as [Chain, string];
290
+
291
+ const symbol = isSynthetic ? synthSymbol : rest.join(".");
292
+ const splitSymbol = symbol.split("-");
293
+ const ticker = (
294
+ splitSymbol.length === 1 ? splitSymbol[0] : splitSymbol.slice(0, -1).join("-")
295
+ ) as string;
296
+ const address = splitSymbol.length === 1 ? undefined : splitSymbol[splitSymbol.length - 1];
245
297
 
246
298
  return {
247
299
  address: address?.toLowerCase(),
248
300
  chain,
249
301
  isGasAsset: isGasAsset({ chain, symbol }),
250
302
  isSynthetic,
251
- symbol: address ? `${ticker}-${address?.toLowerCase() ?? ''}` : symbol,
252
- ticker: isSynthetic ? symbol : ticker,
303
+ symbol:
304
+ (isSynthetic ? `${synthChain}/` : "") +
305
+ (address ? `${ticker}-${address?.toLowerCase() ?? ""}` : symbol),
306
+ ticker,
253
307
  };
254
- };
308
+ }