@swapkit/helpers 3.0.0-beta.8 → 4.0.0-beta.24

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 (71) hide show
  1. package/dist/api/index.cjs +2 -2
  2. package/dist/api/index.cjs.map +5 -5
  3. package/dist/api/index.js +2 -2
  4. package/dist/api/index.js.map +5 -5
  5. package/dist/{chunk-6vvdbb6s.js → chunk-7shcm26h.js} +3 -3
  6. package/dist/{chunk-6vvdbb6s.js.map → chunk-7shcm26h.js.map} +1 -1
  7. package/dist/chunk-8fdws4se.js +4 -0
  8. package/dist/chunk-8fdws4se.js.map +10 -0
  9. package/dist/{chunk-dbsrwnw2.js → chunk-b8hashv0.js} +3 -3
  10. package/dist/{chunk-dbsrwnw2.js.map → chunk-b8hashv0.js.map} +1 -1
  11. package/dist/{chunk-kdcsgh3q.js → chunk-bf0ph1bk.js} +3 -3
  12. package/dist/{chunk-kdcsgh3q.js.map → chunk-bf0ph1bk.js.map} +1 -1
  13. package/dist/{chunk-mmwvr2y8.js → chunk-bh986mnf.js} +3 -3
  14. package/dist/{chunk-mmwvr2y8.js.map → chunk-bh986mnf.js.map} +1 -1
  15. package/dist/{chunk-ahpfxkx0.js → chunk-dzypg9sp.js} +3 -3
  16. package/dist/{chunk-ahpfxkx0.js.map → chunk-dzypg9sp.js.map} +1 -1
  17. package/dist/{chunk-wmxwvv8c.js → chunk-ghdhtvtt.js} +3 -3
  18. package/dist/{chunk-wmxwvv8c.js.map → chunk-ghdhtvtt.js.map} +1 -1
  19. package/dist/{chunk-fr86y3rx.js → chunk-jhmhh7ax.js} +3 -3
  20. package/dist/{chunk-fr86y3rx.js.map → chunk-jhmhh7ax.js.map} +1 -1
  21. package/dist/{chunk-ekd1k975.js → chunk-nm1av1e6.js} +3 -3
  22. package/dist/{chunk-ekd1k975.js.map → chunk-nm1av1e6.js.map} +1 -1
  23. package/dist/{chunk-wrjh857m.js → chunk-rarep8vg.js} +3 -3
  24. package/dist/{chunk-wrjh857m.js.map → chunk-rarep8vg.js.map} +1 -1
  25. package/dist/{chunk-kr69v1tm.js → chunk-rr043vwc.js} +3 -3
  26. package/dist/{chunk-kr69v1tm.js.map → chunk-rr043vwc.js.map} +1 -1
  27. package/dist/{chunk-3wnfcm30.js → chunk-s82pm7xc.js} +2 -2
  28. package/dist/{chunk-3wnfcm30.js.map → chunk-s82pm7xc.js.map} +1 -1
  29. package/dist/chunk-sb9hymk1.js +3 -0
  30. package/dist/chunk-sb9hymk1.js.map +10 -0
  31. package/dist/{chunk-tq87xn7m.js → chunk-tn4e7zrk.js} +3 -3
  32. package/dist/{chunk-tq87xn7m.js.map → chunk-tn4e7zrk.js.map} +1 -1
  33. package/dist/{chunk-z8emzpyc.js → chunk-vadspc46.js} +3 -3
  34. package/dist/{chunk-z8emzpyc.js.map → chunk-vadspc46.js.map} +1 -1
  35. package/dist/{chunk-xyczdrny.js → chunk-vgg88vt8.js} +3 -3
  36. package/dist/{chunk-xyczdrny.js.map → chunk-vgg88vt8.js.map} +1 -1
  37. package/dist/{chunk-q8xy3739.js → chunk-wssz50sc.js} +3 -3
  38. package/dist/{chunk-q8xy3739.js.map → chunk-wssz50sc.js.map} +1 -1
  39. package/dist/contracts/index.js +1 -1
  40. package/dist/index.cjs +3 -3
  41. package/dist/index.cjs.map +18 -18
  42. package/dist/index.js +3 -3
  43. package/dist/index.js.map +18 -18
  44. package/dist/tokens/index.js +2 -2
  45. package/dist/tokens/index.js.map +2 -2
  46. package/package.json +10 -6
  47. package/src/api/microgard/types.ts +0 -3
  48. package/src/api/midgard/endpoints.ts +1 -65
  49. package/src/api/midgard/types.ts +0 -49
  50. package/src/api/swapkitApi/endpoints.ts +16 -10
  51. package/src/api/swapkitApi/types.ts +1 -1
  52. package/src/index.ts +1 -0
  53. package/src/modules/__tests__/assetValue.test.ts +43 -0
  54. package/src/modules/__tests__/swapKitNumber.test.ts +4 -5
  55. package/src/modules/assetValue.ts +26 -35
  56. package/src/modules/bigIntArithmetics.ts +12 -1
  57. package/src/modules/feeMultiplier.ts +87 -0
  58. package/src/modules/requestClient.ts +43 -23
  59. package/src/modules/swapKitConfig.ts +9 -1
  60. package/src/modules/swapKitError.ts +325 -105
  61. package/src/types/chains.ts +98 -44
  62. package/src/types/derivationPath.ts +2 -0
  63. package/src/types/quotes.ts +1 -2
  64. package/src/types/sdk.ts +0 -2
  65. package/src/types/wallet.ts +5 -0
  66. package/src/utils/__tests__/memo.test.ts +0 -20
  67. package/src/utils/asset.ts +17 -30
  68. package/src/utils/derivationPath.ts +6 -0
  69. package/src/utils/memo.ts +5 -42
  70. package/src/utils/others.ts +1 -2
  71. package/src/utils/wallets.ts +6 -3
@@ -1,3 +1,3 @@
1
- import{a as w}from"../chunk-ahpfxkx0.js";import{b as C}from"../chunk-xyczdrny.js";import{c as p}from"../chunk-q8xy3739.js";import{d as m}from"../chunk-z8emzpyc.js";import{e as x}from"../chunk-fr86y3rx.js";import{f}from"../chunk-tq87xn7m.js";import{g as l}from"../chunk-wmxwvv8c.js";import{h as L}from"../chunk-wrjh857m.js";import{i as e}from"../chunk-kdcsgh3q.js";import{j as V}from"../chunk-ekd1k975.js";import{k as t}from"../chunk-mmwvr2y8.js";import{l as a}from"../chunk-dbsrwnw2.js";import{m as i}from"../chunk-kr69v1tm.js";import{n as o}from"../chunk-6vvdbb6s.js";import{p as T}from"../chunk-3wnfcm30.js";var s={};T(s,{UniswapV3List:()=>C,UniswapV2List:()=>w,TraderjoeV2List:()=>V,ThorchainList:()=>e,SushiswapList:()=>L,PangolinList:()=>l,PancakeswapList:()=>f,OpenOceanV2List:()=>x,OneInchList:()=>m,MayaList:()=>p,JupiterList:()=>o,ChainflipList:()=>i,CaviarV1List:()=>a,CamelotV3List:()=>t});function B(O){for(let c of Object.values(s)){let r=c.tokens.find((P)=>P.identifier===O);if(r?.logoURI)return r.logoURI}return}export{s as tokenLists,B as getTokenIcon};
1
+ import{e as w}from"../chunk-dzypg9sp.js";import{f as C}from"../chunk-vgg88vt8.js";import{g as p}from"../chunk-wssz50sc.js";import{h as m}from"../chunk-vadspc46.js";import{i as x}from"../chunk-jhmhh7ax.js";import{j as f}from"../chunk-tn4e7zrk.js";import{k as l}from"../chunk-ghdhtvtt.js";import{l as L}from"../chunk-rarep8vg.js";import{m as e}from"../chunk-bf0ph1bk.js";import{n as V}from"../chunk-nm1av1e6.js";import{o as t}from"../chunk-bh986mnf.js";import{p as a}from"../chunk-b8hashv0.js";import{q as i}from"../chunk-rr043vwc.js";import{r as o}from"../chunk-7shcm26h.js";import{t as T}from"../chunk-s82pm7xc.js";var s={};T(s,{UniswapV3List:()=>C,UniswapV2List:()=>w,TraderjoeV2List:()=>V,ThorchainList:()=>e,SushiswapList:()=>L,PangolinList:()=>l,PancakeswapList:()=>f,OpenOceanV2List:()=>x,OneInchList:()=>m,MayaList:()=>p,JupiterList:()=>o,ChainflipList:()=>i,CaviarV1List:()=>a,CamelotV3List:()=>t});function B(O){for(let c of Object.values(s)){let r=c.tokens.find((P)=>P.identifier===O);if(r?.logoURI)return r.logoURI}return}export{s as tokenLists,B as getTokenIcon};
2
2
 
3
- //# debugId=4914D9B24FD3F03364756E2164756E21
3
+ //# debugId=3A5B936F2C5A6EC964756E2164756E21
@@ -4,7 +4,7 @@
4
4
  "sourcesContent": [
5
5
  "import * as tokenLists from \"./lists\";\n\nexport function getTokenIcon(identifier: string): string | undefined {\n // Search through all lists for a matching token\n for (const list of Object.values(tokenLists)) {\n const token = list.tokens.find((token) => token.identifier === identifier);\n if (token?.logoURI) {\n return token.logoURI;\n }\n }\n\n return undefined;\n}\n\nexport { tokenLists };\n"
6
6
  ],
7
- "mappings": "28BAEO,IAAS,JAAY,JAAC,HAAwC,JAEnE,GAAW,AAAQ,EAAO,EAAO,JAAU,HAAG,JAC5C,DAAM,HAAQ,EAAK,OAAO,KAAK,CAAC,IAAU,EAAM,aAAe,CAAU,EACzE,GAAI,GAAO,QACT,OAAO,EAAM,QAIjB",
8
- "debugId": "4914D9B24FD3F03364756E2164756E21",
7
+ "mappings": "g9BAEO,IAAS,JAAY,JAAC,HAAwC,JAEnE,GAAW,AAAQ,EAAO,EAAO,JAAU,HAAG,JAC5C,DAAM,HAAQ,EAAK,OAAO,KAAK,CAAC,IAAU,EAAM,aAAe,CAAU,EACzE,GAAI,GAAO,QACT,OAAO,EAAM,QAIjB",
8
+ "debugId": "3A5B936F2C5A6EC964756E2164756E21",
9
9
  "names": []
10
10
  }
package/package.json CHANGED
@@ -1,14 +1,18 @@
1
1
  {
2
2
  "author": "swapkit-oss",
3
3
  "dependencies": {
4
- "ethers": "6.13.5",
5
- "ts-pattern": "5.7.0",
6
- "zod": "3.24.3",
7
- "zustand": "5.0.3"
4
+ "ethers": "^6.0.0",
5
+ "ts-pattern": "^5.0.0",
6
+ "zod": "3.25.74",
7
+ "zustand": "^5.0.0"
8
8
  },
9
9
  "description": "SwapKit - Helpers",
10
10
  "devDependencies": {
11
- "@swapkit/toolboxes": "1.0.0-beta.9"
11
+ "@swapkit/toolboxes": "4.0.0-beta.35",
12
+ "ethers": "6.14.3",
13
+ "ts-pattern": "5.7.1",
14
+ "zod": "3.25.74",
15
+ "zustand": "5.0.5"
12
16
  },
13
17
  "exports": {
14
18
  ".": {
@@ -55,5 +59,5 @@
55
59
  "type-check:go": "tsgo"
56
60
  },
57
61
  "type": "module",
58
- "version": "3.0.0-beta.8"
62
+ "version": "4.0.0-beta.24"
59
63
  }
@@ -17,9 +17,6 @@ export type PoolDetail = {
17
17
  liquidityUnits: string;
18
18
  poolAPY: string;
19
19
  runeDepth: string;
20
- saversAPR: string;
21
- saversDepth: string;
22
- saversUnits: string;
23
20
  status: string;
24
21
  synthSupply: string;
25
22
  synthUnits: string;
@@ -1,11 +1,5 @@
1
1
  import { AssetValue, BaseDecimal, Chain, RequestClient, SwapKitNumber } from "@swapkit/helpers";
2
- import type {
3
- BorrowerDetails,
4
- MemberDetailsMayachain,
5
- MemberDetailsThorchain,
6
- SaverDetails,
7
- THORNameDetails,
8
- } from "./types";
2
+ import type { MemberDetailsMayachain, MemberDetailsThorchain, THORNameDetails } from "./types";
9
3
 
10
4
  function getMidgardBaseUrl(isThorchain = true) {
11
5
  return isThorchain ? "https://midgard.ninerealms.com" : "https://midgard.mayachain.info";
@@ -16,18 +10,6 @@ function getNameServiceBaseUrl(isThorchain = true) {
16
10
  return isThorchain ? `${baseUrl}/v2/thorname` : `${baseUrl}/v2/mayaname`;
17
11
  }
18
12
 
19
- function getBorrowerDetailRaw(baseUrl: string) {
20
- return function getBorrowerDetail(address: string) {
21
- return RequestClient.get<BorrowerDetails>(`${baseUrl}/v2/borrower/${address}`);
22
- };
23
- }
24
-
25
- function getSaverDetailRaw(baseUrl: string) {
26
- return function getSaverDetail(address: string) {
27
- return RequestClient.get<SaverDetails>(`${baseUrl}/v2/saver/${address}`);
28
- };
29
- }
30
-
31
13
  function getLiquidityPositionRaw<Chain extends Chain.THORChain | Chain.Maya>(baseUrl: string) {
32
14
  return function getLiquidityPosition(
33
15
  address: string,
@@ -56,50 +38,10 @@ function getNamesByOwner(baseUrl: string) {
56
38
  };
57
39
  }
58
40
 
59
- function getBorrowerDetail(borrowerDetailGetter: ReturnType<typeof getBorrowerDetailRaw>) {
60
- return async function getBorrowerDetail(address: string) {
61
- const rawBorrowerDetail = await borrowerDetailGetter(address);
62
-
63
- return rawBorrowerDetail.pools.map((p) => ({
64
- collateral_deposited: AssetValue.from({
65
- asset: p.collateral_asset,
66
- value: p.collateral_deposited,
67
- fromBaseDecimal: BaseDecimal.THOR,
68
- }),
69
- collateral_withdrawn: AssetValue.from({
70
- asset: p.collateral_asset,
71
- value: p.collateral_withdrawn,
72
- fromBaseDecimal: BaseDecimal.THOR,
73
- }),
74
- debt_issued_tor: SwapKitNumber.fromBigInt(BigInt(p.debt_issued_tor), BaseDecimal.THOR),
75
- debt_repaid_tor: SwapKitNumber.fromBigInt(BigInt(p.debt_repaid_tor), BaseDecimal.THOR),
76
- last_open_loan_timestamp: p.last_open_loan_timestamp,
77
- last_repay_loan_timestamp: p.last_repay_loan_timestamp,
78
- target_assets: p.target_assets.map((asset) => AssetValue.from({ asset })),
79
- }));
80
- };
81
- }
82
-
83
41
  function getPoolAsset({ asset, value }: { asset: string; value: string }) {
84
42
  return AssetValue.from({ asset, value, fromBaseDecimal: BaseDecimal.THOR });
85
43
  }
86
44
 
87
- function getSaverDetail(saverDetailGetter: ReturnType<typeof getSaverDetailRaw>) {
88
- return async function getSaverDetail(address: string) {
89
- const rawSaverPositions = await saverDetailGetter(address);
90
-
91
- return rawSaverPositions.pools.map((p) => ({
92
- assetAdded: getPoolAsset({ asset: p.pool, value: p.assetAdded }),
93
- assetDeposit: getPoolAsset({ asset: p.pool, value: p.assetDeposit }),
94
- assetRedeem: getPoolAsset({ asset: p.pool, value: p.assetRedeem }),
95
- assetWithdrawn: getPoolAsset({ asset: p.pool, value: p.assetWithdrawn }),
96
- assetRegisteredAddress: p.assetAddress,
97
- dateFirstAdded: p.dateFirstAdded,
98
- dateLastAdded: p.dateLastAdded,
99
- }));
100
- };
101
- }
102
-
103
45
  function getLiquidityPosition<IsThorchain extends boolean = true>({
104
46
  liquidityPositionGetter,
105
47
  isThorchain,
@@ -134,15 +76,9 @@ function getMidgardMethodsForProtocol<T extends Chain.THORChain | Chain.Maya>(ch
134
76
  const midgardBaseUrl = getMidgardBaseUrl(isThorchain);
135
77
  const nameServiceBaseUrl = getNameServiceBaseUrl(isThorchain);
136
78
  const liquidityPositionGetter = getLiquidityPositionRaw<T>(midgardBaseUrl);
137
- const borrowerDetailGetter = getBorrowerDetailRaw(midgardBaseUrl);
138
- const saverDetailGetter = getSaverDetailRaw(midgardBaseUrl);
139
79
 
140
80
  return {
141
81
  getLiquidityPositionRaw: liquidityPositionGetter,
142
- getBorrowerDetailRaw: borrowerDetailGetter,
143
- getSaverDetailRaw: saverDetailGetter,
144
- getBorrowerDetail: getBorrowerDetail(borrowerDetailGetter),
145
- getSaversDetail: getSaverDetail(saverDetailGetter),
146
82
  getNameDetails: getNameDetails(nameServiceBaseUrl),
147
83
  getNamesByAddress: getNamesByAddress(nameServiceBaseUrl),
148
84
  getNamesByOwner: getNamesByOwner(nameServiceBaseUrl),
@@ -1,52 +1,3 @@
1
- export type BorrowerDetails = {
2
- /** @description List details of all the loans identified with the given address */
3
- pools: BorrowerPool[];
4
- };
5
-
6
- export type BorrowerPool = {
7
- /** @description The asset that the borrower used as collateral */
8
- collateral_asset: string;
9
- /** @description Int64(e8), The total amount of collateral that user deposited */
10
- collateral_deposited: string;
11
- /** @description Int64(e8), The total amount of collateral the system paid back to the user */
12
- collateral_withdrawn: string;
13
- /** @description Int64(e8), The total amount of debt issued as debt for user. denominated in TOR. */
14
- debt_issued_tor: string;
15
- /** @description Int64(e8), The total amount of debt that the user paid back. denominated in TOR. */
16
- debt_repaid_tor: string;
17
- /** @description Int64, Unix timestamp for the last time borrower opened a loan */
18
- last_open_loan_timestamp: string;
19
- /** @description Int64, Unix timestamp for the last time borrower repayment occurred */
20
- last_repay_loan_timestamp: string;
21
- target_assets: string[];
22
- };
23
-
24
- export type SaverDetails = {
25
- /** @description List details of all the savers identified with the given address */
26
- pools: SaverPool[];
27
- };
28
-
29
- export type SaverPool = {
30
- /** @description Int64(e8), total asset added in the saver pool by member */
31
- assetAdded: string;
32
- /** @description saver address used by the member */
33
- assetAddress: string;
34
- /** @description Int64(e8), total asset that is currently deposited by the member */
35
- assetDeposit: string;
36
- /** @description Int64(e8), total asset can be redeemed from the saver pool by member */
37
- assetRedeem: string;
38
- /** @description Int64(e8), total asset withdrawn from the saver pool by member */
39
- assetWithdrawn: string;
40
- /** @description Int64, Unix timestamp for the first time member deposited into the saver pool */
41
- dateFirstAdded: string;
42
- /** @description Int64, Unix timestamp for the last time member deposited into the saver pool */
43
- dateLastAdded: string;
44
- /** @description The Pool rest of the data are refering to (only those pools can show up which have a corresponding saver pool) */
45
- pool: string;
46
- /** @description Int64, saver liquidity units that belong the the member */
47
- saverUnits: string;
48
- };
49
-
50
1
  export type MemberDetailsMayachain = {
51
2
  /** @MemberPool List details of all the liquidity providers identified with the given address */
52
3
  pools: MemberPoolMayachain[];
@@ -28,12 +28,19 @@ import {
28
28
  type TrackerResponse,
29
29
  } from "./types";
30
30
 
31
+ const SKRequestClient = RequestClient.extend({
32
+ dynamicHeader: () => {
33
+ const { swapKit } = SKConfig.get("apiKeys");
34
+ return swapKit ? { "x-api-key": swapKit } : {};
35
+ },
36
+ });
37
+
31
38
  export function getTrackerDetails(json: TrackerParams) {
32
- return RequestClient.post<TrackerResponse>(getApiUrl("/track"), { json });
39
+ return SKRequestClient.post<TrackerResponse>(getApiUrl("/track"), { json });
33
40
  }
34
41
 
35
42
  export async function getSwapQuote(json: QuoteRequest) {
36
- const response = await RequestClient.post<QuoteResponse>(getApiUrl("/quote"), { json });
43
+ const response = await SKRequestClient.post<QuoteResponse>(getApiUrl("/quote"), { json });
37
44
 
38
45
  if (response.error) {
39
46
  throw new SwapKitError("api_v2_server_error", { message: response.error });
@@ -47,9 +54,8 @@ export async function getSwapQuote(json: QuoteRequest) {
47
54
  }
48
55
 
49
56
  return parsedResponse.data;
50
- } catch (error) {
57
+ } catch (_error) {
51
58
  // throw new SwapKitError("api_v2_invalid_response", error);
52
- console.warn(error);
53
59
  return response;
54
60
  }
55
61
  }
@@ -60,7 +66,7 @@ export async function getChainBalance<T extends Chain>({
60
66
  scamFilter = true,
61
67
  }: { chain: T; address: string; scamFilter?: boolean }) {
62
68
  const url = getApiUrl(`/balance?chain=${chain}&address=${address}`);
63
- const balanceResponse = await RequestClient.get<BalanceResponse>(url);
69
+ const balanceResponse = await SKRequestClient.get<BalanceResponse>(url);
64
70
  const balances = Array.isArray(balanceResponse) ? balanceResponse : [];
65
71
 
66
72
  return scamFilter ? filterAssets(balances) : balances;
@@ -68,17 +74,17 @@ export async function getChainBalance<T extends Chain>({
68
74
 
69
75
  export function getTokenListProviders() {
70
76
  const url = getApiUrl("/providers");
71
- return RequestClient.get<TokenListProvidersResponse>(url);
77
+ return SKRequestClient.get<TokenListProvidersResponse>(url);
72
78
  }
73
79
 
74
80
  export function getTokenList(provider: ProviderName) {
75
81
  const url = getApiUrl(`/tokens?provider=${provider}`);
76
- return RequestClient.get<TokensResponseV2>(url);
82
+ return SKRequestClient.get<TokensResponseV2>(url);
77
83
  }
78
84
 
79
85
  export async function getPrice(body: PriceRequest) {
80
86
  const url = getApiUrl("/price");
81
- const response = await RequestClient.post<PriceResponse>(url, {
87
+ const response = await SKRequestClient.post<PriceResponse>(url, {
82
88
  json: body,
83
89
  });
84
90
 
@@ -97,7 +103,7 @@ export async function getPrice(body: PriceRequest) {
97
103
 
98
104
  export async function getGasRate() {
99
105
  const url = getApiUrl("/gas");
100
- const response = await RequestClient.get<GasResponse>(url);
106
+ const response = await SKRequestClient.get<GasResponse>(url);
101
107
 
102
108
  try {
103
109
  const parsedResponse = GasResponseSchema.safeParse(response);
@@ -120,7 +126,7 @@ export async function getChainflipDepositChannel(body: BrokerDepositChannelParam
120
126
  }
121
127
  const url = SKConfig.get("integrations").chainflip?.brokerUrl || getApiUrl("/channel");
122
128
 
123
- const response = await RequestClient.post<DepositChannelResponse>(url, { json: body });
129
+ const response = await SKRequestClient.post<DepositChannelResponse>(url, { json: body });
124
130
 
125
131
  try {
126
132
  const parsedResponse = DepositChannelResponseSchema.safeParse(response);
@@ -2,7 +2,6 @@ import {
2
2
  type AssetValue,
3
3
  Chain,
4
4
  ChainId,
5
- ErrorCode,
6
5
  FeeTypeEnum,
7
6
  ProviderName,
8
7
  WarningCodeEnum,
@@ -20,6 +19,7 @@ import {
20
19
  unknown,
21
20
  type z,
22
21
  } from "zod";
22
+ import { ErrorCode } from "../../types/quotes";
23
23
 
24
24
  export enum PriorityLabel {
25
25
  CHEAPEST = "CHEAPEST",
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ export * from "./modules/requestClient";
7
7
  export * from "./modules/swapKitError";
8
8
  export * from "./modules/swapKitNumber";
9
9
  export * from "./modules/swapKitConfig";
10
+ export * from "./modules/feeMultiplier";
10
11
 
11
12
  /**
12
13
  * Utils
@@ -794,6 +794,32 @@ describe("AssetValue", () => {
794
794
  type: "Native",
795
795
  }),
796
796
  );
797
+
798
+ const trxAsset = AssetValue.from({ chain: Chain.Tron });
799
+ expect(trxAsset).toEqual(
800
+ expect.objectContaining({
801
+ chain: Chain.Tron,
802
+ decimal: BaseDecimal.TRX,
803
+ isGasAsset: true,
804
+ isSynthetic: false,
805
+ symbol: "TRX",
806
+ ticker: "TRX",
807
+ type: "Native",
808
+ }),
809
+ );
810
+
811
+ const trxAssetFromString = AssetValue.from({ asset: "TRX.TRX" });
812
+ expect(trxAssetFromString).toEqual(
813
+ expect.objectContaining({
814
+ chain: Chain.Tron,
815
+ decimal: BaseDecimal.TRX,
816
+ isGasAsset: true,
817
+ isSynthetic: false,
818
+ symbol: "TRX",
819
+ ticker: "TRX",
820
+ type: "Native",
821
+ }),
822
+ );
797
823
  });
798
824
 
799
825
  test("keep SOL address casing", () => {
@@ -811,6 +837,23 @@ describe("AssetValue", () => {
811
837
  }),
812
838
  );
813
839
  });
840
+
841
+ test("TRC20 tokens are not marked as gas assets", () => {
842
+ const tronUsdt = AssetValue.from({
843
+ asset: "TRX.USDT-TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
844
+ });
845
+
846
+ expect(tronUsdt).toEqual(
847
+ expect.objectContaining({
848
+ address: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
849
+ chain: Chain.Tron,
850
+ isGasAsset: false,
851
+ isSynthetic: false,
852
+ symbol: "USDT-TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
853
+ ticker: "USDT",
854
+ }),
855
+ );
856
+ });
814
857
  });
815
858
  });
816
859
 
@@ -27,11 +27,11 @@ describe("SwapKitNumber", () => {
27
27
 
28
28
  const skNumber5 = new SwapKitNumber({ value: 0.1005, decimal: 3 });
29
29
  expect(skNumber5.getValue("string")).toBe("0.101");
30
- expect(skNumber5.getBaseValue("bigint")).toBe(100n);
30
+ expect(skNumber5.getBaseValue("bigint")).toBe(101n);
31
31
 
32
32
  const skNumber6 = new SwapKitNumber({ value: -0.1005, decimal: 3 });
33
33
  expect(skNumber6.getValue("string")).toBe("-0.101");
34
- expect(skNumber6.getBaseValue("bigint")).toBe(-100n);
34
+ expect(skNumber6.getBaseValue("bigint")).toBe(-101n);
35
35
  expect(skNumber6.decimal).toBe(3);
36
36
  expect(skNumber6.getValue("number")).toBe(-0.101);
37
37
  expect(skNumber6.decimalMultiplier).toBe(100000000n);
@@ -355,9 +355,8 @@ describe("SwapKitNumber", () => {
355
355
 
356
356
  const result = skNumber1.mul(skNumber2);
357
357
 
358
- // The exact result of 1.23 * 4.56 is 5.6088
359
358
  expect(result.getValue("string")).toBe("5.609");
360
- expect(result.getBaseValue("bigint")).toBe(5608n);
359
+ expect(result.getBaseValue("bigint")).toBe(5609n);
361
360
 
362
361
  const skNumber3 = new SwapKitNumber({ decimal: 2, value: 1.23 });
363
362
  const skNumber4 = new SwapKitNumber(-1.234567891);
@@ -367,7 +366,7 @@ describe("SwapKitNumber", () => {
367
366
  // The exact result of 1.23 * -1.234567891 is -1,518518505
368
367
  // If we round it to 2 decimal places, we should get 5.61
369
368
  expect(result2.getValue("string")).toBe("-1.52");
370
- expect(result2.getBaseValue("bigint")).toBe(-151n);
369
+ expect(result2.getBaseValue("bigint")).toBe(-152n);
371
370
  });
372
371
  });
373
372
 
@@ -1,3 +1,6 @@
1
+ import { getAddress } from "ethers";
2
+ import { match } from "ts-pattern";
3
+
1
4
  import {
2
5
  BaseDecimal,
3
6
  Chain,
@@ -19,12 +22,13 @@ import { warnOnce } from "../utils/others";
19
22
  import { type TokenListName, loadTokenLists } from "../utils/tokens";
20
23
  import { validateIdentifier } from "../utils/validators";
21
24
 
22
- import { getAddress } from "ethers";
23
25
  import type { NumberPrimitives } from "./bigIntArithmetics";
24
26
  import { BigIntArithmetics, formatBigIntToSafeValue } from "./bigIntArithmetics";
25
27
  import { SwapKitError } from "./swapKitError";
26
28
  import type { SwapKitValueType } from "./swapKitNumber";
27
29
 
30
+ const CASE_SENSITIVE_CHAINS = [Chain.Solana, Chain.Tron];
31
+
28
32
  const staticTokensMap = new Map<
29
33
  TokenNames | string,
30
34
  { tax?: TokenTax; decimal: number; identifier: string }
@@ -213,33 +217,15 @@ or by passing asyncTokenLookup: true to the from() function, which will make it
213
217
  export function getMinAmountByChain(chain: Chain) {
214
218
  const asset = AssetValue.from({ chain });
215
219
 
216
- switch (chain) {
217
- case Chain.Bitcoin:
218
- case Chain.Litecoin:
219
- case Chain.BitcoinCash:
220
- case Chain.Dash:
221
- return asset.set(0.00010001);
222
-
223
- case Chain.Dogecoin:
224
- return asset.set(1.00000001);
225
-
226
- case Chain.Avalanche:
227
- case Chain.Ethereum:
228
- case Chain.Arbitrum:
229
- case Chain.BinanceSmartChain:
230
- return asset.set(0.00000001);
231
-
232
- case Chain.THORChain:
233
- case Chain.Maya:
234
- return asset.set(0);
235
-
236
- case Chain.Cosmos:
237
- case Chain.Kujira:
238
- return asset.set(0.000001);
239
-
240
- default:
241
- return asset.set(0.00000001);
242
- }
220
+ return match(chain)
221
+ .with(Chain.Bitcoin, Chain.Litecoin, Chain.BitcoinCash, Chain.Dash, () => asset.set(0.00010001))
222
+ .with(Chain.Dogecoin, () => asset.set(1.00000001))
223
+ .with(Chain.Avalanche, Chain.Ethereum, Chain.Arbitrum, Chain.BinanceSmartChain, () =>
224
+ asset.set(0.00000001),
225
+ )
226
+ .with(Chain.THORChain, Chain.Maya, () => asset.set(0))
227
+ .with(Chain.Cosmos, Chain.Kujira, () => asset.set(0.000001))
228
+ .otherwise(() => asset.set(0.00000001));
243
229
  }
244
230
 
245
231
  async function createAssetValue(identifier: string, value: NumberPrimitives = 0) {
@@ -297,12 +283,15 @@ function safeValue(value: NumberPrimitives, decimal: number) {
297
283
  }
298
284
 
299
285
  function validateAssetChain(assetOrChain: AssetIdentifier) {
300
- const chain =
301
- "chain" in assetOrChain
302
- ? assetOrChain.chain
303
- : assetFromString(assetOrChain.asset).synth
304
- ? Chain.THORChain
305
- : assetFromString(assetOrChain.asset).chain;
286
+ const chain = match(assetOrChain)
287
+ .when(
288
+ (x): x is { chain: Chain } => "chain" in x && x.chain !== undefined,
289
+ ({ chain }) => chain,
290
+ )
291
+ .otherwise((x) => {
292
+ const assetInfo = assetFromString((x as { asset: string }).asset);
293
+ return assetInfo.synth ? Chain.THORChain : assetInfo.chain;
294
+ });
306
295
 
307
296
  // TODO: move to SKConfig chains once we support it throughout sdk
308
297
  if (!Object.values(Chain).includes(chain.toUpperCase() as Chain)) {
@@ -385,7 +374,9 @@ function getAssetBaseInfo({ symbol, chain }: { symbol: string; chain: Chain }) {
385
374
  const unformattedAddress =
386
375
  splitSymbol.length === 1 ? undefined : splitSymbol[splitSymbol.length - 1];
387
376
 
388
- const address = chain === Chain.Solana ? unformattedAddress : unformattedAddress?.toLowerCase();
377
+ const address = CASE_SENSITIVE_CHAINS.includes(chain)
378
+ ? unformattedAddress
379
+ : unformattedAddress?.toLowerCase();
389
380
  const ticker = (
390
381
  splitSymbol.length === 1 ? splitSymbol[0] : splitSymbol.slice(0, -1).join("-")
391
382
  ) as string;
@@ -54,6 +54,17 @@ export function formatBigIntToSafeValue({
54
54
  );
55
55
  }
56
56
 
57
+ function divideBigIntWithRounding(n: bigint, d: bigint) {
58
+ if (d === 0n) {
59
+ throw new Error("Cannot divide by zero");
60
+ }
61
+ const half = d / 2n;
62
+ if ((n >= 0n && d >= 0n) || (n < 0n && d < 0n)) {
63
+ return (n + half) / d;
64
+ }
65
+ return (n - half) / d;
66
+ }
67
+
57
68
  export class BigIntArithmetics {
58
69
  decimalMultiplier: bigint = 10n ** 8n;
59
70
  bigIntValue = 0n;
@@ -153,7 +164,7 @@ export class BigIntArithmetics {
153
164
  getBaseValue<T extends AllowedNumberTypes>(type: T, decimal?: number): NumberPrimitivesType[T] {
154
165
  const divisor =
155
166
  this.decimalMultiplier / toMultiplier(decimal || this.decimal || BaseDecimal.THOR);
156
- const baseValue = this.bigIntValue / divisor;
167
+ const baseValue = divideBigIntWithRounding(this.bigIntValue, divisor);
157
168
 
158
169
  switch (type) {
159
170
  case "number":
@@ -0,0 +1,87 @@
1
+ import { FeeOption } from "../types";
2
+ import { SKConfig } from "./swapKitConfig";
3
+
4
+ export interface FeeMultiplierConfig {
5
+ [FeeOption.Average]: number;
6
+ [FeeOption.Fast]: number;
7
+ [FeeOption.Fastest]: number;
8
+ }
9
+
10
+ const DEFAULT_FEE_MULTIPLIERS: FeeMultiplierConfig = {
11
+ [FeeOption.Average]: 1.0,
12
+ [FeeOption.Fast]: 1.5,
13
+ [FeeOption.Fastest]: 2.0,
14
+ };
15
+
16
+ /**
17
+ * Get fee multiplier for the given fee option.
18
+ * Checks SKConfig for custom multipliers first, then falls back to defaults.
19
+ *
20
+ * @param feeOption - The fee option (Average, Fast, Fastest)
21
+ * @returns The fee multiplier as a number
22
+ */
23
+ export function getFeeMultiplier(feeOption: FeeOption = FeeOption.Average): number {
24
+ const customMultipliers = SKConfig.get("feeMultipliers");
25
+
26
+ if (customMultipliers && customMultipliers[feeOption] !== undefined) {
27
+ return customMultipliers[feeOption];
28
+ }
29
+
30
+ return DEFAULT_FEE_MULTIPLIERS[feeOption];
31
+ }
32
+
33
+ /**
34
+ * Get fee multiplier as BigInt for EVM calculations.
35
+ * Returns numerator and denominator for precise BigInt arithmetic.
36
+ *
37
+ * @param feeOption - The fee option (Average, Fast, Fastest)
38
+ * @returns Object with numerator and denominator for BigInt calculations
39
+ */
40
+ export function getFeeMultiplierAsBigInt(feeOption: FeeOption = FeeOption.Average): {
41
+ numerator: bigint;
42
+ denominator: bigint;
43
+ } {
44
+ const multiplier = getFeeMultiplier(feeOption);
45
+
46
+ // Convert decimal multiplier to fraction for precise BigInt arithmetic
47
+ // e.g., 1.5 -> 15/10, 2.0 -> 20/10
48
+ const denominator = 10n;
49
+ const numerator = BigInt(Math.round(multiplier * 10));
50
+
51
+ return { numerator, denominator };
52
+ }
53
+
54
+ /**
55
+ * Apply fee multiplier to a BigInt value (for EVM chains).
56
+ *
57
+ * @param value - The base fee value as BigInt
58
+ * @param feeOption - The fee option (Average, Fast, Fastest)
59
+ * @returns The multiplied fee value as BigInt
60
+ */
61
+ export function applyFeeMultiplierToBigInt(
62
+ value: bigint,
63
+ feeOption: FeeOption = FeeOption.Average,
64
+ ): bigint {
65
+ const { numerator, denominator } = getFeeMultiplierAsBigInt(feeOption);
66
+ return (value * numerator) / denominator;
67
+ }
68
+
69
+ /**
70
+ * Apply fee multiplier to a number value (for non-EVM chains).
71
+ *
72
+ * @param value - The base fee value as number
73
+ * @param feeOption - The fee option (Average, Fast, Fastest)
74
+ * @param floor - Whether to floor the result (default: false)
75
+ * @returns The multiplied fee value as number
76
+ */
77
+ export function applyFeeMultiplier(
78
+ value: number,
79
+ feeOption: FeeOption = FeeOption.Average,
80
+ floor = false,
81
+ ): number {
82
+ const multiplier = getFeeMultiplier(feeOption);
83
+ const result = value * multiplier;
84
+ return floor ? Math.floor(result) : result;
85
+ }
86
+
87
+ export { DEFAULT_FEE_MULTIPLIERS };