@swapkit/helpers 3.0.0-beta.2 → 3.0.0-beta.20

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 (73) 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-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 +6 -5
  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/api/thornode/endpoints.ts +22 -4
  53. package/src/api/thornode/types.ts +3 -2
  54. package/src/index.ts +1 -0
  55. package/src/modules/__tests__/assetValue.test.ts +66 -23
  56. package/src/modules/__tests__/swapKitNumber.test.ts +4 -5
  57. package/src/modules/assetValue.ts +84 -33
  58. package/src/modules/bigIntArithmetics.ts +12 -1
  59. package/src/modules/feeMultiplier.ts +87 -0
  60. package/src/modules/requestClient.ts +34 -23
  61. package/src/modules/swapKitConfig.ts +9 -1
  62. package/src/modules/swapKitError.ts +325 -105
  63. package/src/types/chains.ts +92 -44
  64. package/src/types/derivationPath.ts +2 -0
  65. package/src/types/quotes.ts +1 -2
  66. package/src/types/sdk.ts +0 -2
  67. package/src/types/wallet.ts +5 -0
  68. package/src/utils/__tests__/memo.test.ts +0 -20
  69. package/src/utils/asset.ts +18 -27
  70. package/src/utils/derivationPath.ts +6 -0
  71. package/src/utils/memo.ts +5 -42
  72. package/src/utils/others.ts +1 -2
  73. package/src/utils/wallets.ts +6 -3
@@ -1,4 +1,14 @@
1
- import { BaseDecimal, Chain, type ChainId, ChainToChainId } from "../types/chains";
1
+ import { getAddress } from "ethers";
2
+ import { match } from "ts-pattern";
3
+
4
+ import {
5
+ BaseDecimal,
6
+ Chain,
7
+ type ChainId,
8
+ ChainToChainId,
9
+ type EVMChain,
10
+ EVMChains,
11
+ } from "../types/chains";
2
12
  import type { TokenNames, TokenTax } from "../types/tokens";
3
13
  import {
4
14
  type CommonAssetString,
@@ -17,8 +27,10 @@ import { BigIntArithmetics, formatBigIntToSafeValue } from "./bigIntArithmetics"
17
27
  import { SwapKitError } from "./swapKitError";
18
28
  import type { SwapKitValueType } from "./swapKitNumber";
19
29
 
30
+ const CASE_SENSITIVE_CHAINS = [Chain.Solana, Chain.Tron];
31
+
20
32
  const staticTokensMap = new Map<
21
- TokenNames,
33
+ TokenNames | string,
22
34
  { tax?: TokenTax; decimal: number; identifier: string }
23
35
  >();
24
36
 
@@ -169,7 +181,9 @@ or by passing asyncTokenLookup: true to the from() function, which will make it
169
181
 
170
182
  for (const { tokens } of Object.values(lists)) {
171
183
  for (const { identifier, chain, ...rest } of tokens) {
172
- const tokenKey = (chain === "SOL" ? identifier : identifier.toUpperCase()) as TokenNames;
184
+ const tokenKey = (
185
+ chain === Chain.Solana ? identifier : identifier.toUpperCase()
186
+ ) as TokenNames;
173
187
  const tokenDecimal = "decimals" in rest ? rest.decimals : BaseDecimal[chain as Chain];
174
188
 
175
189
  staticTokensMap.set(tokenKey, { identifier, decimal: tokenDecimal });
@@ -178,38 +192,40 @@ or by passing asyncTokenLookup: true to the from() function, which will make it
178
192
 
179
193
  return true;
180
194
  }
195
+
196
+ static setStaticAssets(
197
+ tokenMap: Map<
198
+ string,
199
+ { tax?: TokenTax; identifier: string; chain: Chain } & (
200
+ | { decimal: number }
201
+ | { decimals: number }
202
+ )
203
+ >,
204
+ ) {
205
+ staticTokensMap.clear();
206
+ for (const [key, value] of tokenMap.entries()) {
207
+ const tokenKey = (
208
+ value.chain === Chain.Solana ? value.identifier : value.identifier.toUpperCase()
209
+ ) as TokenNames;
210
+ const tokenDecimal = "decimals" in value ? value.decimals : value.decimal;
211
+ staticTokensMap.set(key, { ...value, decimal: tokenDecimal, identifier: tokenKey });
212
+ }
213
+ return true;
214
+ }
181
215
  }
182
216
 
183
217
  export function getMinAmountByChain(chain: Chain) {
184
218
  const asset = AssetValue.from({ chain });
185
219
 
186
- switch (chain) {
187
- case Chain.Bitcoin:
188
- case Chain.Litecoin:
189
- case Chain.BitcoinCash:
190
- case Chain.Dash:
191
- return asset.set(0.00010001);
192
-
193
- case Chain.Dogecoin:
194
- return asset.set(1.00000001);
195
-
196
- case Chain.Avalanche:
197
- case Chain.Ethereum:
198
- case Chain.Arbitrum:
199
- case Chain.BinanceSmartChain:
200
- return asset.set(0.00000001);
201
-
202
- case Chain.THORChain:
203
- case Chain.Maya:
204
- return asset.set(0);
205
-
206
- case Chain.Cosmos:
207
- case Chain.Kujira:
208
- return asset.set(0.000001);
209
-
210
- default:
211
- return asset.set(0.00000001);
212
- }
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));
213
229
  }
214
230
 
215
231
  async function createAssetValue(identifier: string, value: NumberPrimitives = 0) {
@@ -266,7 +282,29 @@ function safeValue(value: NumberPrimitives, decimal: number) {
266
282
  : value;
267
283
  }
268
284
 
285
+ function validateAssetChain(assetOrChain: AssetIdentifier) {
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
+ });
295
+
296
+ // TODO: move to SKConfig chains once we support it throughout sdk
297
+ if (!Object.values(Chain).includes(chain.toUpperCase() as Chain)) {
298
+ throw new SwapKitError({
299
+ errorKey: "helpers_invalid_asset_identifier",
300
+ info: { message: "Please use the AssetValue constructor for unsupported chains" },
301
+ });
302
+ }
303
+ }
304
+
269
305
  function getAssetString(assetOrChain: AssetIdentifier) {
306
+ validateAssetChain(assetOrChain);
307
+
270
308
  if ("chain" in assetOrChain) return assetOrChain.chain;
271
309
 
272
310
  const { chain, symbol } = assetFromString(assetOrChain.asset);
@@ -304,12 +342,23 @@ function getAssetInfo(identifier: string) {
304
342
  const assetSymbol = isSynthOrTrade ? synthSymbol : rest.join(".");
305
343
 
306
344
  const { address, ticker } = getAssetBaseInfo({ symbol: assetSymbol, chain });
345
+
346
+ let formattedAddress: string | undefined;
347
+ try {
348
+ formattedAddress =
349
+ address && EVMChains.includes(chain as EVMChain) && getAddress(address)
350
+ ? getAddress(address)
351
+ : address;
352
+ } catch (_error) {
353
+ formattedAddress = address;
354
+ }
355
+
307
356
  const symbol =
308
357
  (isSynthOrTrade ? `${synthChain}${assetSeparator}` : "") +
309
- (address ? `${ticker}-${address ?? ""}` : assetSymbol);
358
+ (formattedAddress ? `${ticker}-${formattedAddress ?? ""}` : assetSymbol);
310
359
 
311
360
  return {
312
- address,
361
+ address: formattedAddress,
313
362
  chain,
314
363
  isSynthOrTrade,
315
364
  isSynthetic,
@@ -325,7 +374,9 @@ function getAssetBaseInfo({ symbol, chain }: { symbol: string; chain: Chain }) {
325
374
  const unformattedAddress =
326
375
  splitSymbol.length === 1 ? undefined : splitSymbol[splitSymbol.length - 1];
327
376
 
328
- const address = chain === Chain.Solana ? unformattedAddress : unformattedAddress?.toLowerCase();
377
+ const address = CASE_SENSITIVE_CHAINS.includes(chain)
378
+ ? unformattedAddress
379
+ : unformattedAddress?.toLowerCase();
329
380
  const ticker = (
330
381
  splitSymbol.length === 1 ? splitSymbol[0] : splitSymbol.slice(0, -1).join("-")
331
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 };
@@ -1,14 +1,15 @@
1
- import { SKConfig } from "./swapKitConfig";
1
+ import { SwapKitError } from "./swapKitError";
2
2
 
3
3
  type Options = RequestInit & {
4
4
  /**
5
- * @deprecated Use onSuccess instead
5
+ * @deprecated Use onSuccess instead - will be removed in next major @MarkedV4
6
6
  */
7
7
  responseHandler?: (response: any) => any;
8
8
  json?: unknown;
9
9
  onError?: (error: any) => any;
10
10
  onSuccess?: (response: any) => any;
11
11
  searchParams?: Record<string, string>;
12
+ getDynamicHeader?: () => Record<string, string> | {};
12
13
  };
13
14
 
14
15
  export const RequestClient = {
@@ -24,40 +25,50 @@ export const RequestClient = {
24
25
  function fetchWithConfig(method: "GET" | "POST", extendOptions: Options = {}) {
25
26
  return async <T>(url: string, options: Options = {}): Promise<T> => {
26
27
  const { searchParams, json, body, headers: headersOptions } = { ...extendOptions, ...options };
27
- const { swapKit } = SKConfig.get("apiKeys");
28
28
 
29
- const isJson = json || url.endsWith(".json");
29
+ const isJson = !!json || url.endsWith(".json");
30
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
31
 
43
32
  try {
44
- const response = await fetch(urlInstance.toString(), {
45
- ...options,
46
- method,
47
- body: bodyToSend,
48
- headers,
49
- });
33
+ const requestUrl = buildUrl(url, searchParams);
34
+ const headers = buildHeaders(isJson, { ...headersOptions, ...options.getDynamicHeader?.() });
35
+
36
+ const response = await fetch(requestUrl, { ...options, method, body: bodyToSend, headers });
50
37
 
51
38
  if (!response.ok) {
52
39
  const message = await response.text();
53
- throw new Error(`${response.statusText}(${response.status}): ${message}`);
40
+ throw new SwapKitError("helpers_invalid_response", {
41
+ status: response.status,
42
+ statusText: response.statusText,
43
+ message,
44
+ });
54
45
  }
55
46
 
56
47
  const body = await response.json();
57
48
 
58
49
  return options.onSuccess?.(body) || options.responseHandler?.(body) || body;
59
50
  } catch (error) {
60
- return options.onError?.(error) || console.error(error);
51
+ if (options.onError) {
52
+ return options.onError(error);
53
+ }
54
+ throw error;
61
55
  }
62
56
  };
63
57
  }
58
+
59
+ function buildHeaders(isJson: boolean, headersOptions?: HeadersInit) {
60
+ return {
61
+ ...headersOptions,
62
+ ...(isJson ? { "Content-Type": "application/json" } : {}),
63
+ };
64
+ }
65
+
66
+ function buildUrl(url: string, searchParams?: Record<string, string>) {
67
+ const urlInstance = new URL(url);
68
+
69
+ if (searchParams) {
70
+ urlInstance.search = new URLSearchParams(searchParams).toString();
71
+ }
72
+
73
+ return urlInstance.toString();
74
+ }
@@ -1,5 +1,6 @@
1
1
  import { createStore } from "zustand/vanilla";
2
2
  import { Chain, EXPLORER_URLS, NODE_URLS, RPC_URLS, WalletOption } from "../types";
3
+ import type { FeeMultiplierConfig } from "./feeMultiplier";
3
4
 
4
5
  export type SKConfigIntegrations = {
5
6
  chainflip?: { useSDKBroker?: boolean; brokerUrl: string };
@@ -36,7 +37,6 @@ const initialState = {
36
37
 
37
38
  apiKeys: {
38
39
  blockchair: "",
39
- kado: "",
40
40
  keepKey: "",
41
41
  swapKit: "",
42
42
  walletConnectProjectId: "",
@@ -61,6 +61,8 @@ const initialState = {
61
61
  },
62
62
  },
63
63
  } as SKConfigIntegrations,
64
+
65
+ feeMultipliers: undefined as FeeMultiplierConfig | undefined,
64
66
  };
65
67
  type SKState = typeof initialState;
66
68
 
@@ -73,6 +75,7 @@ export type SKConfigState = {
73
75
  nodeUrls?: Partial<SKState["nodeUrls"]>;
74
76
  rpcUrls?: Partial<SKState["rpcUrls"]>;
75
77
  wallets?: SKState["wallets"];
78
+ feeMultipliers?: FeeMultiplierConfig;
76
79
  };
77
80
 
78
81
  type SwapKitConfigStore = SKState & {
@@ -86,6 +89,7 @@ type SwapKitConfigStore = SKState & {
86
89
  integration: keyof SKState["integrations"],
87
90
  config: SKConfigIntegrations[keyof SKConfigIntegrations],
88
91
  ) => void;
92
+ setFeeMultipliers: (multipliers: FeeMultiplierConfig) => void;
89
93
  };
90
94
 
91
95
  const swapKitState = createStore<SwapKitConfigStore>((set) => ({
@@ -99,6 +103,7 @@ const swapKitState = createStore<SwapKitConfigStore>((set) => ({
99
103
  setRpcUrl: (chain, url) => set((s) => ({ rpcUrls: { ...s.rpcUrls, [chain]: url } })),
100
104
  setIntegrationConfig: (integration, config) =>
101
105
  set((s) => ({ integrations: { ...s.integrations, [integration]: config } })),
106
+ setFeeMultipliers: (multipliers) => set(() => ({ feeMultipliers: multipliers })),
102
107
  setConfig: (config) =>
103
108
  set((s) => ({
104
109
  apiKeys: { ...s.apiKeys, ...config.apiKeys },
@@ -107,6 +112,7 @@ const swapKitState = createStore<SwapKitConfigStore>((set) => ({
107
112
  integrations: { ...s.integrations, ...config.integrations },
108
113
  nodeUrls: { ...s.nodeUrls, ...config.nodeUrls },
109
114
  rpcUrls: { ...s.rpcUrls, ...config.rpcUrls },
115
+ feeMultipliers: config.feeMultipliers || s.feeMultipliers,
110
116
  chains: s.chains.concat(config.chains || []),
111
117
  wallets: s.wallets.concat(config.wallets || []),
112
118
  })),
@@ -131,4 +137,6 @@ export const SKConfig = {
131
137
  integration: T,
132
138
  config: SKConfigIntegrations[T],
133
139
  ) => swapKitState.getState().setIntegrationConfig(integration, config),
140
+ setFeeMultipliers: (multipliers: FeeMultiplierConfig) =>
141
+ swapKitState.getState().setFeeMultipliers(multipliers),
134
142
  };