@swapkit/helpers 3.0.0-beta.0 → 3.0.0-beta.1

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 (100) hide show
  1. package/dist/api/index.cjs +2 -2
  2. package/dist/api/index.cjs.map +6 -6
  3. package/dist/api/index.js +2 -2
  4. package/dist/api/index.js.map +6 -6
  5. package/dist/chunk-1gwdyyeh.js +4 -0
  6. package/dist/chunk-1gwdyyeh.js.map +10 -0
  7. package/dist/chunk-2bhvezjh.js +4 -0
  8. package/dist/chunk-2bhvezjh.js.map +10 -0
  9. package/dist/chunk-3ptwhtpd.js +3 -0
  10. package/dist/chunk-3ptwhtpd.js.map +10 -0
  11. package/dist/{chunk-nm00d52v.js → chunk-3wnfcm30.js} +2 -2
  12. package/dist/{chunk-nm00d52v.js.map → chunk-3wnfcm30.js.map} +1 -1
  13. package/dist/chunk-40epvqbm.js +3 -0
  14. package/dist/chunk-40epvqbm.js.map +10 -0
  15. package/dist/chunk-49nsjaay.js +3 -0
  16. package/dist/chunk-49nsjaay.js.map +10 -0
  17. package/dist/chunk-4b66tryh.js +4 -0
  18. package/dist/chunk-4b66tryh.js.map +10 -0
  19. package/dist/chunk-4kzjrrjv.js +3 -0
  20. package/dist/chunk-4kzjrrjv.js.map +10 -0
  21. package/dist/chunk-5m49s8z8.js +4 -0
  22. package/dist/chunk-5m49s8z8.js.map +10 -0
  23. package/dist/chunk-9b6y7r75.js +4 -0
  24. package/dist/chunk-9b6y7r75.js.map +10 -0
  25. package/dist/chunk-9zcbvqq2.js +3 -0
  26. package/dist/chunk-9zcbvqq2.js.map +10 -0
  27. package/dist/chunk-a0bpx1q3.js +4 -0
  28. package/dist/chunk-a0bpx1q3.js.map +10 -0
  29. package/dist/chunk-a0fxkkfh.js +4 -0
  30. package/dist/chunk-a0fxkkfh.js.map +10 -0
  31. package/dist/chunk-a6bjd9ar.js +3 -0
  32. package/dist/chunk-a6bjd9ar.js.map +10 -0
  33. package/dist/chunk-bg6pz5qh.js +3 -0
  34. package/dist/chunk-bg6pz5qh.js.map +10 -0
  35. package/dist/chunk-cpdcnp2x.js +4 -0
  36. package/dist/chunk-cpdcnp2x.js.map +10 -0
  37. package/dist/chunk-fr86y3rx.js +4 -0
  38. package/dist/chunk-fr86y3rx.js.map +10 -0
  39. package/dist/chunk-ftdtdkhk.js +3 -0
  40. package/dist/chunk-ftdtdkhk.js.map +10 -0
  41. package/dist/chunk-gjeaw024.js +4 -0
  42. package/dist/chunk-gjeaw024.js.map +10 -0
  43. package/dist/chunk-hdcdd2cf.js +4 -0
  44. package/dist/chunk-hdcdd2cf.js.map +10 -0
  45. package/dist/chunk-q2pb6ggs.js +3 -0
  46. package/dist/chunk-q2pb6ggs.js.map +10 -0
  47. package/dist/chunk-t9s9811k.js +3 -0
  48. package/dist/chunk-t9s9811k.js.map +10 -0
  49. package/dist/chunk-v4dvhh90.js +4 -0
  50. package/dist/chunk-v4dvhh90.js.map +10 -0
  51. package/dist/chunk-vzptz52h.js +4 -0
  52. package/dist/chunk-vzptz52h.js.map +10 -0
  53. package/dist/chunk-wyr5d8ad.js +3 -0
  54. package/dist/chunk-wyr5d8ad.js.map +10 -0
  55. package/dist/chunk-x0jsq6ag.js +3 -0
  56. package/dist/chunk-x0jsq6ag.js.map +10 -0
  57. package/dist/chunk-x2fe9scs.js +3 -0
  58. package/dist/chunk-x2fe9scs.js.map +10 -0
  59. package/dist/chunk-xm5jkehh.js +4 -0
  60. package/dist/chunk-xm5jkehh.js.map +10 -0
  61. package/dist/chunk-xzb1nshn.js +3 -0
  62. package/dist/chunk-xzb1nshn.js.map +10 -0
  63. package/dist/contracts/index.cjs.map +2 -2
  64. package/dist/contracts/index.js +1 -1
  65. package/dist/contracts/index.js.map +2 -2
  66. package/dist/index.cjs +3 -3
  67. package/dist/index.cjs.map +19 -18
  68. package/dist/index.js +3 -3
  69. package/dist/index.js.map +19 -18
  70. package/dist/tokens/index.cjs +2 -2
  71. package/dist/tokens/index.cjs.map +3 -16
  72. package/dist/tokens/index.js +2 -2
  73. package/dist/tokens/index.js.map +3 -16
  74. package/package.json +8 -5
  75. package/src/api/midgard/endpoints.ts +120 -132
  76. package/src/api/swapkitApi/endpoints.ts +53 -158
  77. package/src/api/swapkitApi/types.ts +318 -514
  78. package/src/api/thorswapStatic/endpoints.ts +18 -2
  79. package/src/contracts/index.ts +1 -1
  80. package/src/index.ts +15 -10
  81. package/src/modules/__tests__/assetValue.test.ts +50 -22
  82. package/src/modules/__tests__/swapKitConfig.test.ts +3 -3
  83. package/src/modules/assetValue.ts +77 -67
  84. package/src/modules/requestClient.ts +52 -55
  85. package/src/modules/swapKitConfig.ts +8 -5
  86. package/src/modules/swapKitError.ts +18 -11
  87. package/src/tokens/lists/index.ts +1 -0
  88. package/src/types/chains.ts +22 -5
  89. package/src/types/commonTypes.ts +1 -1
  90. package/src/types/derivationPath.ts +11 -24
  91. package/src/types/radix.ts +2 -2
  92. package/src/types/sdk.ts +0 -7
  93. package/src/types/tokens.ts +13 -16
  94. package/src/types/wallet.ts +42 -21
  95. package/src/utils/asset.ts +118 -217
  96. package/src/utils/derivationPath.ts +24 -7
  97. package/src/utils/plugin.ts +1 -1
  98. package/src/utils/tokens.ts +73 -0
  99. package/src/utils/validators.ts +3 -2
  100. package/src/utils/wallets.ts +19 -10
@@ -1,4 +1,10 @@
1
- import { AssetValue, type ProviderName, RequestClient, getChainIdentifier } from "@swapkit/helpers";
1
+ import {
2
+ AssetValue,
3
+ Chain,
4
+ type ProviderName,
5
+ RequestClient,
6
+ getChainIdentifier,
7
+ } from "@swapkit/helpers";
2
8
 
3
9
  import { getTokenListProviders } from "../swapkitApi/endpoints";
4
10
  import type { TokenListProvidersResponse } from "../swapkitApi/types";
@@ -11,7 +17,9 @@ export function getStaticTokenList(tokenListName: string) {
11
17
  }
12
18
 
13
19
  export function getLogoForAsset(assetString: string) {
14
- return `${baseUrl}/token-list/images/${assetString.toLowerCase()}.png`;
20
+ const mappedAssetIcon = getMappedAssetIcon(assetString);
21
+
22
+ return `${baseUrl}/token-list/images/${mappedAssetIcon}.png`;
15
23
  }
16
24
 
17
25
  export function getChainLogoForAsset(assetString: string) {
@@ -28,3 +36,11 @@ export async function getProviderLogo(providerName: ProviderName | string) {
28
36
 
29
37
  return providerData.find((p) => p.name === providerName)?.url;
30
38
  }
39
+
40
+ function getMappedAssetIcon(assetString: string) {
41
+ const { symbol } = AssetValue.from({ asset: assetString });
42
+
43
+ if (symbol === Chain.Ethereum) return "eth.eth";
44
+
45
+ return assetString.toLowerCase();
46
+ }
@@ -20,7 +20,7 @@ import { uniswapV3_100 } from "./abis/uniswapV3_100";
20
20
  import { uniswapV3_500 } from "./abis/uniswapV3_500";
21
21
  import { uniswapV3_3000 } from "./abis/uniswapV3_3000";
22
22
  import { uniswapV3_10000 } from "./abis/uniswapV3_10000";
23
- import { lowercasedRouterAbiMapping } from "./routers/index";
23
+ import { lowercasedRouterAbiMapping } from "./routers";
24
24
 
25
25
  type AbiTypes =
26
26
  | typeof avaxGeneric
package/src/index.ts CHANGED
@@ -1,5 +1,15 @@
1
1
  /**
2
- * Helpers
2
+ * Modules
3
+ */
4
+ export * from "./modules/assetValue";
5
+ export * from "./modules/bigIntArithmetics";
6
+ export * from "./modules/requestClient";
7
+ export * from "./modules/swapKitError";
8
+ export * from "./modules/swapKitNumber";
9
+ export * from "./modules/swapKitConfig";
10
+
11
+ /**
12
+ * Utils
3
13
  */
4
14
  export * from "./utils/asset";
5
15
  export * from "./utils/derivationPath";
@@ -9,14 +19,9 @@ export * from "./utils/others";
9
19
  export * from "./utils/plugin";
10
20
  export * from "./utils/validators";
11
21
  export * from "./utils/wallets";
22
+ export * from "./utils/tokens";
23
+
12
24
  /**
13
- * Modules
25
+ * Types
14
26
  */
15
- export * from "./modules/assetValue";
16
- export * from "./modules/bigIntArithmetics";
17
- export * from "./modules/requestClient";
18
- export * from "./modules/swapKitError";
19
- export * from "./modules/swapKitNumber";
20
- export * from "./modules/swapKitConfig";
21
-
22
- export * from "./types/index";
27
+ export * from "./types";
@@ -79,13 +79,15 @@ describe("AssetValue", () => {
79
79
 
80
80
  expect(atomDerived.toString()).toBe("THOR.ATOM");
81
81
 
82
+ const value = 10;
82
83
  const mayaCacao = AssetValue.from({
83
84
  asset: "MAYA.CACAO",
84
- value: 10,
85
+ value,
85
86
  });
86
87
 
87
88
  expect(mayaCacao.toString()).toBe("MAYA.CACAO");
88
- expect(mayaCacao.getBaseValue("string")).toBe("1000000000");
89
+ const expectedValue = value * 10_000_000_000;
90
+ expect(mayaCacao.getBaseValue("string")).toBe(expectedValue.toString());
89
91
 
90
92
  const ethMayaSynth = AssetValue.from({
91
93
  asset: "MAYA.ETH/ETH",
@@ -105,29 +107,38 @@ describe("AssetValue", () => {
105
107
  expect(ethTCSynthFallback.toString({ includeSynthProtocol: true })).toBe("THOR.ETH/ETH");
106
108
  expect(ethTCSynthFallback.getBaseValue("string")).toBe("1000000000");
107
109
 
108
- // TODO:
109
- // const radixXWBTC = new AssetValue({
110
- // identifier:
111
- // "RADIX.XWBTC-resource_rdx1t580qxc7upat7lww4l2c4jckacafjeudxj5wpjrrct0p3e82sq4y75",
112
- // decimal: 8,
113
- // value: 11112222,
114
- // });
115
-
116
- // expect(radixXWBTC.toString()).toBe(
117
- // "RADIX.XWBTC-resource_rdx1t580qxc7upat7lww4l2c4jckacafjeudxj5wpjrrct0p3e82sq4y75",
118
- // )
110
+ const solFromString = AssetValue.from({ asset: "SOL.SOL" });
111
+ expect(solFromString.toString()).toBe("SOL.SOL");
112
+ });
113
+
114
+ test("regres cases", () => {
115
+ const arbWeth = AssetValue.from({
116
+ asset: "ARB.WETH-0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
117
+ });
118
+ expect(arbWeth.toString()).toBe("ARB.WETH-0x82af49447d8a07e3bd95bd0d56f35241523fbab1");
119
+
120
+ const baseAssetFromString = AssetValue.from({
121
+ asset: "BASE.USDC-0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
122
+ });
123
+ expect(baseAssetFromString.toString()).toBe(
124
+ "BASE.USDC-0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
125
+ );
126
+
127
+ const avaxSolanaAsset = AssetValue.from({
128
+ asset: "AVAX.SOL-0XFE6B19286885A4F7F55ADAD09C3CD1F906D2478F",
129
+ });
130
+ expect(avaxSolanaAsset.toString()).toBe(
131
+ "AVAX.SOL-0xfe6b19286885a4f7f55adad09c3cd1f906d2478f",
132
+ );
119
133
  });
120
134
  });
121
135
 
122
136
  describe("set", () => {
123
137
  test("get a copy of an assetValue with a new value", () => {
124
- const btc = AssetValue.from({
125
- asset: "BTC.BTC",
126
- });
138
+ const btc = AssetValue.from({ asset: "BTC.BTC" });
127
139
 
128
140
  const btc2 = btc.set(10);
129
141
 
130
- expect(btc2).toBeDefined();
131
142
  expect(btc2).toEqual(
132
143
  expect.objectContaining({
133
144
  chain: Chain.Bitcoin,
@@ -293,8 +304,21 @@ describe("AssetValue", () => {
293
304
  const thor = AssetValue.from({ asset: "ETH.THOR" });
294
305
  expect(thor.toString()).toBe("ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044");
295
306
 
296
- const ethSynth = await AssetValue.from({ asset: "ETH/ETH", asyncTokenLookup: true });
307
+ const ethSynth = await AssetValue.from({
308
+ asset: "ETH/ETH",
309
+ asyncTokenLookup: true,
310
+ });
297
311
  expect(ethSynth.toString()).toBe("ETH/ETH");
312
+
313
+ const eth = await AssetValue.from({
314
+ asset: "eth.eth",
315
+ });
316
+ expect(eth.toString()).toBe("ETH.ETH");
317
+
318
+ const ethFromChain = await AssetValue.from({
319
+ chain: Chain.Ethereum,
320
+ });
321
+ expect(ethFromChain.toString()).toBe("ETH.ETH");
298
322
  });
299
323
  });
300
324
 
@@ -509,7 +533,9 @@ describe("AssetValue", () => {
509
533
  test("returns safe decimals if string is not in `@swapkit/tokens` lists", async () => {
510
534
  await AssetValue.loadStaticAssets();
511
535
  const fakeAvaxUSDCAssetString = "AVAX.USDC-1234";
512
- const fakeAvaxUSDCAsset = AssetValue.from({ asset: fakeAvaxUSDCAssetString });
536
+ const fakeAvaxUSDCAsset = AssetValue.from({
537
+ asset: fakeAvaxUSDCAssetString,
538
+ });
513
539
 
514
540
  expect(fakeAvaxUSDCAsset).toBeDefined();
515
541
  expect(fakeAvaxUSDCAsset).toEqual(
@@ -528,7 +554,9 @@ describe("AssetValue", () => {
528
554
  test("returns safe decimals if string is not in `@swapkit/tokens` lists with multiple dashes", async () => {
529
555
  await AssetValue.loadStaticAssets();
530
556
  const fakeAvaxUSDCAssetString = "AVAX.USDC-LPT-1234";
531
- const fakeAvaxUSDCAsset2 = AssetValue.from({ asset: fakeAvaxUSDCAssetString });
557
+ const fakeAvaxUSDCAsset2 = AssetValue.from({
558
+ asset: fakeAvaxUSDCAssetString,
559
+ });
532
560
 
533
561
  expect(fakeAvaxUSDCAsset2).toBeDefined();
534
562
  expect(fakeAvaxUSDCAsset2).toEqual(
@@ -557,8 +585,8 @@ describe("AssetValue", () => {
557
585
  decimal: 8,
558
586
  isGasAsset: false,
559
587
  isSynthetic: false,
560
- symbol: "BTC.b-0x152b9d0fdc40c096757f570a51e494bd4b943e50",
561
- ticker: "BTC.b",
588
+ symbol: "BTC.B-0x152b9d0fdc40c096757f570a51e494bd4b943e50",
589
+ ticker: "BTC.B",
562
590
  }),
563
591
  );
564
592
  });
@@ -17,17 +17,17 @@ describe("swapKitConfig", () => {
17
17
  SKConfig.setApiKey("swapKit", "123");
18
18
  expect(SKConfig.get("apiKeys").swapKit).toBe("123");
19
19
 
20
- SKConfig.setApiKey("ethplorer", "123");
20
+ SKConfig.setApiKey("walletConnectProjectId", "123");
21
21
  expect(SKConfig.get("apiKeys")).toMatchObject({
22
22
  swapKit: "123",
23
- ethplorer: "123",
23
+ walletConnectProjectId: "123",
24
24
  });
25
25
 
26
26
  SKConfig.setExplorerUrl(Chain.Ethereum, "https://lul.xyz");
27
27
  expect(SKConfig.getState()).toMatchObject({
28
28
  apiKeys: {
29
29
  swapKit: "123",
30
- ethplorer: "123",
30
+ walletConnectProjectId: "123",
31
31
  },
32
32
  explorerUrls: {
33
33
  [Chain.Ethereum]: "https://lul.xyz",
@@ -2,13 +2,14 @@ import { BaseDecimal, Chain, type ChainId, ChainToChainId } from "../types/chain
2
2
  import type { TokenNames, TokenTax } from "../types/tokens";
3
3
  import {
4
4
  type CommonAssetString,
5
- CommonAssetStrings,
5
+ assetFromString,
6
6
  getAssetType,
7
7
  getCommonAssetInfo,
8
8
  getDecimal,
9
9
  isGasAsset,
10
10
  } from "../utils/asset";
11
11
  import { warnOnce } from "../utils/others";
12
+ import { type TokenListName, loadTokenLists } from "../utils/tokens";
12
13
  import { validateIdentifier } from "../utils/validators";
13
14
 
14
15
  import type { NumberPrimitives } from "./bigIntArithmetics";
@@ -25,8 +26,7 @@ type ConditionalAssetValueReturn<T extends { asyncTokenLookup?: boolean }> =
25
26
  T["asyncTokenLookup"] extends true ? Promise<AssetValue> : AssetValue;
26
27
 
27
28
  type AssetIdentifier =
28
- | { asset: CommonAssetString }
29
- | { asset: TokenNames }
29
+ | { asset: CommonAssetString | TokenNames }
30
30
  | { asset: string }
31
31
  | { chain: Chain };
32
32
 
@@ -114,7 +114,6 @@ export class AssetValue extends BigIntArithmetics {
114
114
  return AssetValue.from({ asset, value });
115
115
  }
116
116
 
117
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: TODO: refactor
118
117
  static from<T extends {}>({
119
118
  value = 0,
120
119
  fromBaseDecimal,
@@ -122,16 +121,11 @@ export class AssetValue extends BigIntArithmetics {
122
121
  ...fromAssetOrChain
123
122
  }: T & AssetValueFromParams): ConditionalAssetValueReturn<T> {
124
123
  const parsedValue = value instanceof BigIntArithmetics ? value.getValue("string") : value;
125
- const isFromChain = "chain" in fromAssetOrChain;
126
- const assetOrChain = isFromChain ? fromAssetOrChain.chain : fromAssetOrChain.asset;
124
+ const assetOrChain = getAssetString(fromAssetOrChain);
127
125
 
128
- const isFromCommonAssetOrChain =
129
- isFromChain ||
130
- CommonAssetStrings.includes(assetOrChain as (typeof CommonAssetStrings)[number]);
131
-
132
- const { identifier: unsafeIdentifier, decimal: commonAssetDecimal } = isFromCommonAssetOrChain
133
- ? getCommonAssetInfo(assetOrChain as CommonAssetString)
134
- : { identifier: assetOrChain, decimal: undefined };
126
+ const { identifier: unsafeIdentifier, decimal: commonAssetDecimal } = getCommonAssetInfo(
127
+ assetOrChain as CommonAssetString,
128
+ );
135
129
 
136
130
  const { chain, isSynthetic, isTradeAsset } = getAssetInfo(unsafeIdentifier);
137
131
  const token = staticTokensMap.get(
@@ -139,6 +133,7 @@ export class AssetValue extends BigIntArithmetics {
139
133
  ? (unsafeIdentifier as TokenNames)
140
134
  : (unsafeIdentifier.toUpperCase() as TokenNames),
141
135
  );
136
+
142
137
  const tokenDecimal = token?.decimal || commonAssetDecimal;
143
138
 
144
139
  warnOnce(
@@ -154,39 +149,34 @@ or by passing asyncTokenLookup: true to the from() function, which will make it
154
149
  identifier: unsafeIdentifier,
155
150
  };
156
151
 
152
+ const isSynthOrTrade = isSynthetic || isTradeAsset;
153
+
157
154
  const adjustedValue = fromBaseDecimal
158
155
  ? safeValue(BigInt(parsedValue), fromBaseDecimal)
159
156
  : safeValue(parsedValue, decimal);
160
157
 
161
158
  const assetValue = asyncTokenLookup
162
159
  ? createAssetValue(identifier, fromBaseDecimal ? adjustedValue : parsedValue)
163
- : isSynthetic || isTradeAsset
160
+ : isSynthOrTrade
164
161
  ? createSyntheticAssetValue(identifier, adjustedValue)
165
162
  : new AssetValue({ tax, decimal, identifier, value: adjustedValue });
166
163
 
167
164
  return assetValue as ConditionalAssetValueReturn<T>;
168
165
  }
169
166
 
170
- static async loadStaticAssets() {
171
- try {
172
- await import("@swapkit/helpers/tokens").then(({ tokenLists }) => {
173
- for (const { tokens } of Object.values(tokenLists)) {
174
- for (const { identifier, chain, ...rest } of tokens) {
175
- staticTokensMap.set(
176
- chain === "SOL" ? identifier : (identifier.toUpperCase() as TokenNames),
177
- {
178
- identifier,
179
- decimal: "decimals" in rest ? rest.decimals : BaseDecimal[chain as Chain],
180
- },
181
- );
182
- }
183
- }
184
- });
185
- return true;
186
- } catch (error) {
187
- console.error(error);
188
- return false;
167
+ static async loadStaticAssets(listNames?: TokenListName[]) {
168
+ const lists = await loadTokenLists(listNames);
169
+
170
+ for (const { tokens } of Object.values(lists)) {
171
+ for (const { identifier, chain, ...rest } of tokens) {
172
+ const tokenKey = (chain === "SOL" ? identifier : identifier.toUpperCase()) as TokenNames;
173
+ const tokenDecimal = "decimals" in rest ? rest.decimals : BaseDecimal[chain as Chain];
174
+
175
+ staticTokensMap.set(tokenKey, { identifier, decimal: tokenDecimal });
176
+ }
189
177
  }
178
+
179
+ return true;
190
180
  }
191
181
  }
192
182
 
@@ -237,7 +227,11 @@ async function createAssetValue(identifier: string, value: NumberPrimitives = 0)
237
227
  staticTokensMap.set(modifiedIdentifier, { identifier, decimal });
238
228
  }
239
229
 
240
- return new AssetValue({ decimal, value: safeValue(value, decimal), identifier });
230
+ return new AssetValue({
231
+ decimal,
232
+ value: safeValue(value, decimal),
233
+ identifier,
234
+ });
241
235
  }
242
236
 
243
237
  function createSyntheticAssetValue(identifier: string, value: NumberPrimitives = 0) {
@@ -246,11 +240,11 @@ function createSyntheticAssetValue(identifier: string, value: NumberPrimitives =
246
240
  : undefined;
247
241
  const isMayaOrThor = chain ? [Chain.Maya, Chain.THORChain].includes(chain) : false;
248
242
 
249
- const assetSeperator = identifier.slice(0, 14).includes("~") ? "~" : "/";
243
+ const assetSeparator = identifier.slice(0, 14).includes("~") ? "~" : "/";
250
244
 
251
245
  const [synthChain, symbol] = isMayaOrThor
252
- ? identifier.split(".").slice(1).join().split(assetSeperator)
253
- : identifier.split(assetSeperator);
246
+ ? identifier.split(".").slice(1).join().split(assetSeparator)
247
+ : identifier.split(assetSeparator);
254
248
 
255
249
  if (!(synthChain && symbol)) {
256
250
  throw new SwapKitError({
@@ -262,7 +256,7 @@ function createSyntheticAssetValue(identifier: string, value: NumberPrimitives =
262
256
  return new AssetValue({
263
257
  decimal: 8,
264
258
  value: safeValue(value, 8),
265
- identifier: `${chain || Chain.THORChain}.${synthChain}${assetSeperator}${symbol}`,
259
+ identifier: `${chain || Chain.THORChain}.${synthChain}${assetSeparator}${symbol}`,
266
260
  });
267
261
  }
268
262
 
@@ -272,53 +266,69 @@ function safeValue(value: NumberPrimitives, decimal: number) {
272
266
  : value;
273
267
  }
274
268
 
275
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: TODO: refactor & split into smaller functions
269
+ function getAssetString(assetOrChain: AssetIdentifier) {
270
+ if ("chain" in assetOrChain) return assetOrChain.chain;
271
+
272
+ const { chain, symbol } = assetFromString(assetOrChain.asset);
273
+ const isNativeChain = getAssetType({ chain, symbol }) === "Native";
274
+
275
+ return isNativeChain ? chain : assetOrChain.asset;
276
+ }
277
+
276
278
  function getAssetInfo(identifier: string) {
277
- const isSynthetic = identifier.slice(0, 14).includes("/");
278
- const isTradeAsset = identifier.slice(0, 14).includes("~");
279
- const assetSeperator = isTradeAsset ? "~" : "/";
279
+ const shortIdentifier = identifier.slice(0, 14);
280
+ const splitIdentifier = identifier.split(".");
281
+ const identifierChain = splitIdentifier[0]?.toUpperCase() as Chain;
282
+ const isThorOrMaya = [Chain.THORChain, Chain.Maya].includes(identifierChain);
280
283
 
281
- const isThorchain = identifier.split(".")?.[0]?.toUpperCase() === Chain.THORChain;
282
- const isMaya = identifier.split(".")?.[0]?.toUpperCase() === Chain.Maya;
284
+ const isSynthetic = shortIdentifier.includes("/");
285
+ const isTradeAsset = shortIdentifier.includes("~");
286
+ const isSynthOrTrade = isSynthetic || isTradeAsset;
287
+ const assetSeparator = isTradeAsset ? "~" : "/";
283
288
 
284
- const [synthChain, synthSymbol = ""] =
285
- isThorchain || isMaya
286
- ? identifier.split(".").slice(1).join().split(assetSeperator)
287
- : identifier.split(assetSeperator);
289
+ const [synthChain, synthSymbol = ""] = isThorOrMaya
290
+ ? splitIdentifier.slice(1).join().split(assetSeparator)
291
+ : identifier.split(assetSeparator);
288
292
 
289
- if ((isSynthetic || isTradeAsset) && !(synthChain && synthSymbol)) {
293
+ if (isSynthOrTrade && !(synthChain && synthSymbol)) {
290
294
  throw new SwapKitError({
291
295
  errorKey: "helpers_invalid_asset_identifier",
292
296
  info: { identifier },
293
297
  });
294
298
  }
295
299
 
296
- const adjustedIdentifier =
297
- identifier.includes(".") && !isSynthetic && !isTradeAsset
298
- ? identifier
299
- : `${isMaya ? Chain.Maya : Chain.THORChain}.${synthSymbol}`;
300
+ const [chain, ...rest] = (
301
+ identifier.includes(".") && !isSynthOrTrade ? identifier : `${identifierChain}.${synthSymbol}`
302
+ ).split(".") as [Chain, string];
300
303
 
301
- const [chain, ...rest] = adjustedIdentifier.split(".") as [Chain, string];
302
-
303
- const symbol = isSynthetic || isTradeAsset ? synthSymbol : rest.join(".");
304
- const splitSymbol = symbol.split("-");
305
- const ticker = (
306
- splitSymbol.length === 1 ? splitSymbol[0] : splitSymbol.slice(0, -1).join("-")
307
- ) as string;
308
- const unformattedAddress =
309
- splitSymbol.length === 1 ? undefined : splitSymbol[splitSymbol.length - 1];
304
+ const assetSymbol = isSynthOrTrade ? synthSymbol : rest.join(".");
310
305
 
311
- const address = chain === Chain.Solana ? unformattedAddress : unformattedAddress?.toLowerCase();
306
+ const { address, ticker } = getAssetBaseInfo({ symbol: assetSymbol, chain });
307
+ const symbol =
308
+ (isSynthOrTrade ? `${synthChain}${assetSeparator}` : "") +
309
+ (address ? `${ticker}-${address ?? ""}` : assetSymbol);
312
310
 
313
311
  return {
314
312
  address,
315
313
  chain,
316
- isGasAsset: isGasAsset({ chain, symbol }),
314
+ isSynthOrTrade,
317
315
  isSynthetic,
318
316
  isTradeAsset,
319
317
  ticker,
320
- symbol:
321
- (isSynthetic || isTradeAsset ? `${synthChain}${assetSeperator}` : "") +
322
- (address ? `${ticker}-${address ?? ""}` : symbol),
318
+ symbol,
319
+ isGasAsset: isGasAsset({ chain, symbol: assetSymbol }),
323
320
  };
324
321
  }
322
+
323
+ function getAssetBaseInfo({ symbol, chain }: { symbol: string; chain: Chain }) {
324
+ const splitSymbol = symbol.split("-");
325
+ const unformattedAddress =
326
+ splitSymbol.length === 1 ? undefined : splitSymbol[splitSymbol.length - 1];
327
+
328
+ const address = chain === Chain.Solana ? unformattedAddress : unformattedAddress?.toLowerCase();
329
+ const ticker = (
330
+ splitSymbol.length === 1 ? splitSymbol[0] : splitSymbol.slice(0, -1).join("-")
331
+ ) as string;
332
+
333
+ return { address, ticker };
334
+ }
@@ -1,66 +1,63 @@
1
1
  import { SKConfig } from "./swapKitConfig";
2
2
 
3
- type Options = Parameters<typeof fetch>[1] & {
4
- headers?: Record<string, string>;
5
- apiKey?: string;
6
- onError?: (error: any) => any;
3
+ type Options = RequestInit & {
4
+ /**
5
+ * @deprecated Use onSuccess instead
6
+ */
7
7
  responseHandler?: (response: any) => any;
8
- searchParams?: Record<string, string>;
9
8
  json?: unknown;
9
+ onError?: (error: any) => any;
10
+ onSuccess?: (response: any) => any;
11
+ searchParams?: Record<string, string>;
10
12
  };
11
13
 
12
- export const defaultRequestHeaders =
13
- typeof window !== "undefined"
14
- ? ({} as Record<string, string>)
15
- : { referrer: "https://sk.thorswap.net", referer: "https://sk.thorswap.net" };
16
-
17
- async function fetchWithConfig(
18
- { url, method }: { url: string; method: "GET" | "POST" },
19
- options: Options = {},
20
- ) {
21
- const { searchParams, json, body } = options;
22
- const urlInstance = new URL(url);
23
- const isJson = json || url.endsWith(".json");
24
- const bodyToSend = isJson ? JSON.stringify(json) : body;
25
-
26
- const headers = {
27
- ...defaultRequestHeaders,
28
- ...options.headers,
29
- ...(isJson ? { "Content-Type": "application/json" } : {}),
30
- } as Record<string, string>;
31
-
32
- if (searchParams) {
33
- urlInstance.search = new URLSearchParams(searchParams).toString();
34
- }
35
- if (SKConfig.get("apiKeys").swapKit) {
36
- headers["x-api-key"] = SKConfig.get("apiKeys").swapKit;
37
- }
38
-
39
- try {
40
- const response = await fetch(urlInstance.toString(), {
41
- ...options,
42
- method,
43
- body: bodyToSend,
44
- headers,
45
- });
46
- const body = await response.json();
47
-
48
- return options.responseHandler?.(body) || body;
49
- } catch (error) {
50
- return options.onError?.(error) || console.error(error);
51
- }
52
- }
53
-
54
14
  export const RequestClient = {
55
- get: async <T>(url: string, options?: Options): Promise<T> =>
56
- fetchWithConfig({ url, method: "GET" }, options),
57
- post: async <T>(url: string, options?: Options): Promise<T> =>
58
- fetchWithConfig({ url, method: "POST" }, options),
15
+ get: fetchWithConfig("GET"),
16
+ post: fetchWithConfig("POST"),
59
17
  extend: (extendOptions: Options) => ({
60
- get: async <T>(url: string, options?: Options): Promise<T> =>
61
- fetchWithConfig({ url, method: "GET" }, { ...extendOptions, ...options }),
62
- post: async <T>(url: string, options?: Options): Promise<T> =>
63
- fetchWithConfig({ url, method: "POST" }, { ...extendOptions, ...options }),
18
+ get: fetchWithConfig("GET", extendOptions),
19
+ post: fetchWithConfig("POST", extendOptions),
64
20
  extend: (newOptions: Options) => RequestClient.extend({ ...extendOptions, ...newOptions }),
65
21
  }),
66
22
  };
23
+
24
+ function fetchWithConfig(method: "GET" | "POST", extendOptions: Options = {}) {
25
+ return async <T>(url: string, options: Options = {}): Promise<T> => {
26
+ const { searchParams, json, body, headers: headersOptions } = { ...extendOptions, ...options };
27
+ const { swapKit } = SKConfig.get("apiKeys");
28
+
29
+ const isJson = json || url.endsWith(".json");
30
+ const bodyToSend = isJson ? JSON.stringify(json) : body;
31
+ const urlInstance = new URL(url);
32
+
33
+ if (searchParams) {
34
+ urlInstance.search = new URLSearchParams(searchParams).toString();
35
+ }
36
+
37
+ const headers = {
38
+ ...headersOptions,
39
+ ...(isJson ? { "Content-Type": "application/json" } : {}),
40
+ ...(swapKit ? { "x-api-key": swapKit } : {}),
41
+ };
42
+
43
+ try {
44
+ const response = await fetch(urlInstance.toString(), {
45
+ ...options,
46
+ method,
47
+ body: bodyToSend,
48
+ headers,
49
+ });
50
+
51
+ if (!response.ok) {
52
+ const message = await response.text();
53
+ throw new Error(`${response.statusText}(${response.status}): ${message}`);
54
+ }
55
+
56
+ const body = await response.json();
57
+
58
+ return options.onSuccess?.(body) || options.responseHandler?.(body) || body;
59
+ } catch (error) {
60
+ return options.onError?.(error) || console.error(error);
61
+ }
62
+ };
63
+ }
@@ -1,5 +1,5 @@
1
1
  import { createStore } from "zustand/vanilla";
2
- import { type Chain, EXPLORER_URLS, NODE_URLS, RPC_URLS } from "../types";
2
+ import { Chain, EXPLORER_URLS, NODE_URLS, RPC_URLS, WalletOption } from "../types";
3
3
 
4
4
  export type SKConfigIntegrations = {
5
5
  chainflip?: { useSDKBroker?: boolean; brokerUrl: string };
@@ -28,14 +28,14 @@ const initialState = {
28
28
  // TODO: figure out how to type apis without using toolbox directly
29
29
  // Maybe move rpc/toolbox apis to helpers?
30
30
  apis: {} as { [key in Chain]: any },
31
+ chains: Object.values(Chain),
32
+ wallets: Object.values(WalletOption),
31
33
  explorerUrls: EXPLORER_URLS,
32
34
  nodeUrls: NODE_URLS,
33
35
  rpcUrls: RPC_URLS,
34
36
 
35
37
  apiKeys: {
36
38
  blockchair: "",
37
- covalent: "",
38
- ethplorer: "freekey",
39
39
  kado: "",
40
40
  keepKey: "",
41
41
  swapKit: "",
@@ -47,7 +47,6 @@ const initialState = {
47
47
  devApiUrl: "https://dev-api.swapkit.dev",
48
48
  isDev: false,
49
49
  isStagenet: false,
50
- referer: "https://swapkit.dev",
51
50
  },
52
51
 
53
52
  integrations: {
@@ -67,11 +66,13 @@ type SKState = typeof initialState;
67
66
 
68
67
  export type SKConfigState = {
69
68
  apiKeys?: Partial<SKState["apiKeys"]>;
69
+ chains?: SKState["chains"];
70
70
  envs?: Partial<SKState["envs"]>;
71
71
  explorerUrls?: Partial<SKState["explorerUrls"]>;
72
72
  integrations?: Partial<SKConfigIntegrations>;
73
73
  nodeUrls?: Partial<SKState["nodeUrls"]>;
74
74
  rpcUrls?: Partial<SKState["rpcUrls"]>;
75
+ wallets?: SKState["wallets"];
75
76
  };
76
77
 
77
78
  type SwapKitConfigStore = SKState & {
@@ -103,9 +104,11 @@ const swapKitState = createStore<SwapKitConfigStore>((set) => ({
103
104
  apiKeys: { ...s.apiKeys, ...config.apiKeys },
104
105
  envs: { ...s.envs, ...config.envs },
105
106
  explorerUrls: { ...s.explorerUrls, ...config.explorerUrls },
107
+ integrations: { ...s.integrations, ...config.integrations },
106
108
  nodeUrls: { ...s.nodeUrls, ...config.nodeUrls },
107
109
  rpcUrls: { ...s.rpcUrls, ...config.rpcUrls },
108
- integrations: { ...s.integrations, ...config.integrations },
110
+ chains: s.chains.concat(config.chains || []),
111
+ wallets: s.wallets.concat(config.wallets || []),
109
112
  })),
110
113
  }));
111
114