@swapkit/helpers 1.0.0-rc.9 → 1.0.0-rc.91

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 (38) hide show
  1. package/dist/index.js +2099 -0
  2. package/dist/index.js.map +29 -0
  3. package/package.json +24 -37
  4. package/src/helpers/__tests__/asset.test.ts +126 -108
  5. package/src/helpers/__tests__/memo.test.ts +52 -40
  6. package/src/helpers/__tests__/others.test.ts +42 -37
  7. package/src/helpers/__tests__/validators.test.ts +24 -0
  8. package/src/helpers/asset.ts +118 -93
  9. package/src/helpers/derivationPath.ts +52 -0
  10. package/src/helpers/liquidity.ts +50 -43
  11. package/src/helpers/memo.ts +31 -28
  12. package/src/helpers/others.ts +30 -13
  13. package/src/helpers/validators.ts +15 -6
  14. package/src/helpers/web3wallets.ts +178 -0
  15. package/src/index.ts +14 -9
  16. package/src/modules/__tests__/assetValue.test.ts +325 -116
  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 +216 -152
  20. package/src/modules/bigIntArithmetics.ts +214 -147
  21. package/src/modules/requestClient.ts +29 -0
  22. package/src/modules/swapKitError.ts +32 -5
  23. package/src/modules/swapKitNumber.ts +8 -1
  24. package/src/types/abis/erc20.ts +99 -0
  25. package/src/types/abis/tcEthVault.ts +496 -0
  26. package/src/types/chains.ts +220 -0
  27. package/src/types/commonTypes.ts +119 -0
  28. package/src/types/derivationPath.ts +56 -0
  29. package/src/types/index.ts +9 -0
  30. package/src/types/network.ts +43 -0
  31. package/src/types/sdk.ts +44 -0
  32. package/src/types/tokens.ts +30 -0
  33. package/src/types/wallet.ts +47 -0
  34. package/LICENSE +0 -201
  35. package/dist/index.cjs +0 -1
  36. package/dist/index.d.ts +0 -354
  37. package/dist/index.es.js +0 -1054
  38. package/src/helpers/request.ts +0 -16
@@ -1,188 +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 { 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
- };
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";
53
6
 
54
- const createAssetValue = async (assetString: string, value: number | string = 0) => {
55
- validateIdentifier(assetString);
7
+ import type { NumberPrimitives } from "./bigIntArithmetics.ts";
8
+ import { BigIntArithmetics, formatBigIntToSafeValue } from "./bigIntArithmetics.ts";
9
+ import { SwapKitNumber, type SwapKitValueType } from "./swapKitNumber.ts";
56
10
 
57
- const decimal = await getDecimal(getAssetInfo(assetString));
58
- return new AssetValue({ decimal, value, identifier: assetString });
59
- };
11
+ const staticTokensMap = new Map<
12
+ TokenNames,
13
+ { tax?: TokenTax; decimal: number; identifier: string }
14
+ >();
60
15
 
61
16
  export class AssetValue extends BigIntArithmetics {
62
17
  address?: string;
63
18
  chain: Chain;
64
- isSynthetic = false;
65
19
  isGasAsset = false;
20
+ isSynthetic = false;
66
21
  symbol: string;
22
+ tax?: TokenTax;
67
23
  ticker: string;
68
24
  type: ReturnType<typeof getAssetType>;
25
+ chainId: ChainId;
69
26
 
70
- constructor(params: AssetValueParams) {
71
- super(
72
- params.value instanceof BigIntArithmetics
73
- ? params.value
74
- : { decimal: params.decimal, value: params.value },
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;
85
47
  this.address = assetInfo.address;
86
48
  this.isSynthetic = assetInfo.isSynthetic;
87
49
  this.isGasAsset = assetInfo.isGasAsset;
50
+ this.chainId = ChainToChainId[assetInfo.chain];
88
51
  }
89
52
 
90
- get assetValue() {
91
- return `${this.getValue('string')} ${this.ticker}`;
53
+ toString() {
54
+ return this.isSynthetic ? this.symbol : `${this.chain}.${this.symbol}`;
92
55
  }
93
56
 
94
- toString(short = false) {
95
- // THOR.RUNE | ETH/ETH
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}`;
57
+ toUrl() {
58
+ return this.isSynthetic ? `${this.chain}.${this.symbol.replace("/", ".")}` : this.toString();
102
59
  }
103
60
 
104
61
  eq({ chain, symbol }: { chain: Chain; symbol: string }) {
105
62
  return this.chain === chain && this.symbol === symbol;
106
63
  }
107
64
 
108
- static async fromString(assetString: string, value: number | string = 0) {
109
- return createAssetValue(assetString, value);
110
- }
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");
111
71
 
112
- static fromStringSync(assetString: string, value: number | string = 0) {
113
- const { decimal, identifier: tokenIdentifier } = getStaticToken(
114
- assetString as unknown as TokenNames,
115
- );
72
+ const assetString =
73
+ chain === Chain.THORChain && symbol ? `${chain}.${ticker}/${symbol}` : urlAsset;
116
74
 
117
- return tokenIdentifier
118
- ? new AssetValue({ decimal, identifier: tokenIdentifier, value })
119
- : undefined;
75
+ return createAssetValue(assetString, value);
120
76
  }
121
77
 
122
- static async fromIdentifier(
123
- assetString: `${Chain}.${string}` | `${Chain}/${string}` | `${Chain}.${string}-${string}`,
124
- value: number | string = 0,
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,
87
+ value: NumberPrimitives = 0,
125
88
  ) {
126
89
  return createAssetValue(assetString, value);
127
90
  }
128
91
 
129
- static fromIdentifierSync(identifier: TokenNames, value: number | string = 0) {
130
- const { decimal, identifier: tokenIdentifier } = getStaticToken(identifier);
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
+ }
131
116
 
132
- return new AssetValue({ decimal, identifier: tokenIdentifier, value });
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);
133
130
  }
134
131
 
135
- static fromChainOrSignature(assetString: CommonAssetString, value: number | string = 0) {
136
- const { decimal, identifier } = getCommonAssetInfo(assetString);
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);
137
139
 
138
- return new AssetValue({ value, decimal, identifier });
139
- }
140
+ if (isSynthetic) return createSyntheticAssetValue(assetString, value);
140
141
 
141
- static async fromTCQuote(identifier: TCTokenNames, value: number | string = 0) {
142
- const decimal = await getDecimal(getAssetInfo(identifier));
143
- const shiftedValue = this.shiftDecimals({ value, from: BaseDecimal.THOR, to: decimal });
142
+ const { tax, decimal, identifier } = tokenInfo || {
143
+ decimal: BaseDecimal[chain],
144
+ identifier: assetString,
145
+ };
144
146
 
145
- return new AssetValue({ value: shiftedValue, identifier, decimal });
147
+ return new AssetValue({
148
+ tax,
149
+ value: safeValue(BigInt(value), baseDecimal),
150
+ identifier,
151
+ decimal,
152
+ });
146
153
  }
147
154
 
148
- static fromTCQuoteStatic(identifier: TCTokenNames, value: number | string = 0) {
149
- const tokenInfo = getStaticToken(identifier);
150
- const shiftedValue = this.shiftDecimals({
151
- value,
152
- from: BaseDecimal.THOR,
153
- to: tokenInfo.decimal,
154
- });
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
+ }
155
173
 
156
- 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 });
157
177
  }
158
178
 
159
- static async loadStaticAssets() {
160
- return new Promise<{ ok: true } | { ok: false; message: string; error: any }>(
161
- async (resolve, reject) => {
179
+ static loadStaticAssets() {
180
+ return new Promise<{ ok: true } | { ok: false; message: string; error: Todo }>(
181
+ (resolve, reject) => {
162
182
  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
- });
177
-
178
- return acc;
179
- },
180
- new Map<TokenNames, { decimal: number; identifier: string }>(),
181
- );
182
-
183
- staticTokensMap = tokensMap;
184
-
185
- 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
+ });
186
195
  } catch (error) {
187
196
  console.error(error);
188
197
  reject({
@@ -197,46 +206,101 @@ export class AssetValue extends BigIntArithmetics {
197
206
  }
198
207
  }
199
208
 
200
- export const getMinAmountByChain = (chain: Chain) => {
209
+ export function getMinAmountByChain(chain: Chain) {
201
210
  const asset = AssetValue.fromChainOrSignature(chain);
202
211
 
203
212
  switch (chain) {
204
213
  case Chain.Bitcoin:
205
214
  case Chain.Litecoin:
206
215
  case Chain.BitcoinCash:
207
- return asset.add(10001);
216
+ return asset.set(0.00010001);
208
217
 
209
218
  case Chain.Dogecoin:
210
- return asset.add(100000001);
219
+ return asset.set(1.00000001);
211
220
 
212
221
  case Chain.Avalanche:
213
222
  case Chain.Ethereum:
214
- return asset.add(10 * 10 ** 9);
223
+ return asset.set(0.00000001);
215
224
 
216
225
  case Chain.THORChain:
217
226
  case Chain.Maya:
218
- return asset.add(0);
227
+ return asset.set(0);
228
+
229
+ case Chain.Cosmos:
230
+ return asset.set(0.000001);
219
231
 
220
232
  default:
221
- return asset.add(1);
233
+ return asset.set(0.00000001);
222
234
  }
223
- };
235
+ }
224
236
 
225
- const getAssetInfo = (identifier: string) => {
226
- const isSynthetic = identifier.slice(0, 14).includes('/');
227
- const adjustedIdentifier = identifier.includes('.')
228
- ? identifier
229
- : `${Chain.THORChain}.${identifier}`;
237
+ async function createAssetValue(identifier: string, value: NumberPrimitives = 0) {
238
+ validateIdentifier(identifier);
230
239
 
231
- const [chain, symbol] = adjustedIdentifier.split('.') as [Chain, string];
232
- const [ticker, address] = symbol.split('-') as [string, string?];
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
+ }
248
+
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("/");
254
+
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
+ const [ticker, address] = (isSynthetic ? synthSymbol : rest.join(".")).split("-") as [
291
+ string,
292
+ string?,
293
+ ];
294
+ const symbol = isSynthetic ? synthSymbol : rest.join(".");
233
295
 
234
296
  return {
235
297
  address: address?.toLowerCase(),
236
298
  chain,
237
299
  isGasAsset: isGasAsset({ chain, symbol }),
238
300
  isSynthetic,
239
- symbol: address ? `${ticker}-${address?.toLowerCase() ?? ''}` : symbol,
240
- ticker: isSynthetic ? symbol : ticker,
301
+ symbol:
302
+ (isSynthetic ? `${synthChain}/` : "") +
303
+ (address ? `${ticker}-${address?.toLowerCase() ?? ""}` : symbol),
304
+ ticker,
241
305
  };
242
- };
306
+ }