@swapkit/core 1.0.0-rc.8 → 1.0.0-rc.81

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.
@@ -54,6 +54,18 @@ const getEmptyWalletStructure = () =>
54
54
  {} as Record<Chain, null>,
55
55
  );
56
56
 
57
+ const validateAddressType = async ({ chain, address }: { chain: Chain; address?: string }) => {
58
+ if (!address) return false;
59
+
60
+ switch (chain) {
61
+ case Chain.Bitcoin:
62
+ // filter out taproot addresses
63
+ return !address.startsWith('bc1p');
64
+ default:
65
+ return true;
66
+ }
67
+ };
68
+
57
69
  export class SwapKitCore<T = ''> {
58
70
  public connectedChains: Wallet = getEmptyWalletStructure();
59
71
  public connectedWallets: WalletMethods = getEmptyWalletStructure();
@@ -68,25 +80,52 @@ export class SwapKitCore<T = ''> {
68
80
  getWallet = <T extends Chain>(chain: Chain) => this.connectedWallets[chain] as WalletMethods[T];
69
81
  getExplorerAddressUrl = (chain: Chain, address: string) =>
70
82
  getExplorerAddressUrl({ chain, address });
71
- getBalance = async (chain: Chain, refresh?: boolean) => {
72
- if (!refresh) return this.connectedChains[chain]?.balance || [];
73
- const wallet = await this.getWalletByChain(chain);
83
+ getBalance = async (chain: Chain, potentialScamFilter?: boolean) => {
84
+ const wallet = await this.getWalletByChain(chain, potentialScamFilter);
74
85
 
75
86
  return wallet?.balance || [];
76
87
  };
77
88
 
78
89
  swap = async ({ streamSwap, recipient, route, feeOptionKey }: SwapParams) => {
79
- const { quoteMode } = route.meta;
90
+ const {
91
+ meta: { quoteMode },
92
+ // evmTransactionDetails: contractCallParams,
93
+ } = route;
80
94
  const evmChain = quoteMode.startsWith('ERC20-')
81
95
  ? Chain.Ethereum
82
96
  : quoteMode.startsWith('ARC20-')
83
- ? Chain.Avalanche
84
- : Chain.BinanceSmartChain;
97
+ ? Chain.Avalanche
98
+ : quoteMode.startsWith('BEP20-')
99
+ ? Chain.BinanceSmartChain
100
+ : undefined;
85
101
 
86
102
  if (!route.complete) throw new SwapKitError('core_swap_route_not_complete');
87
103
 
88
104
  try {
89
- if (AGG_SWAP.includes(quoteMode)) {
105
+ // TODO enable when BE is ready
106
+ // if (contractCallParams && evmChain) {
107
+ // const walletMethods = this.connectedWallets[evmChain];
108
+
109
+ // if (!walletMethods?.call) {
110
+ // throw new SwapKitError('core_wallet_connection_not_found');
111
+ // }
112
+
113
+ // const { contractAddress, contractMethod, contractParams, contractParamsStreaming } =
114
+ // contractCallParams;
115
+
116
+ // if (!(streamSwap ? contractParamsStreaming : contractParams)) {
117
+ // throw new SwapKitError('core_swap_route_transaction_not_found');
118
+ // }
119
+
120
+ // return await walletMethods.call<string>({
121
+ // contractAddress,
122
+ // abi: lowercasedContractAbiMapping[contractAddress.toLowerCase()],
123
+ // funcName: contractMethod,
124
+ // funcParams: streamSwap ? contractParamsStreaming : contractParams,
125
+ // });
126
+ // }
127
+
128
+ if (AGG_SWAP.includes(quoteMode) && evmChain) {
90
129
  const walletMethods = this.connectedWallets[evmChain];
91
130
  if (!walletMethods?.sendTransaction) {
92
131
  throw new SwapKitError('core_wallet_connection_not_found');
@@ -95,7 +134,6 @@ export class SwapKitCore<T = ''> {
95
134
  const transaction = streamSwap ? route?.streamingSwap?.transaction : route?.transaction;
96
135
  if (!transaction) throw new SwapKitError('core_swap_route_transaction_not_found');
97
136
 
98
- const { isHexString, parseUnits } = await import('ethers');
99
137
  const { data, from, to, value } = route.transaction;
100
138
 
101
139
  const params = {
@@ -103,11 +141,7 @@ export class SwapKitCore<T = ''> {
103
141
  from,
104
142
  to: to.toLowerCase(),
105
143
  chainId: BigInt(ChainToChainId[evmChain]),
106
- value: value
107
- ? new SwapKitNumber({
108
- value: !isHexString(value) ? parseUnits(value, 'wei').toString(16) : value,
109
- }).baseValueBigInt
110
- : 0n,
144
+ value: value ? BigInt(value) : 0n,
111
145
  };
112
146
 
113
147
  return walletMethods.sendTransaction(params, feeOptionKey) as Promise<string>;
@@ -121,16 +155,23 @@ export class SwapKitCore<T = ''> {
121
155
  const { address: recipient } = await this.#getInboundDataByChain(asset.chain);
122
156
  const {
123
157
  contract: router,
124
- calldata: { amountIn, memo, memoStreamingSwap },
158
+ calldata: { expiration, amountIn, memo, memoStreamingSwap },
125
159
  } = route;
126
160
 
127
161
  const assetValue = asset.add(SwapKitNumber.fromBigInt(BigInt(amountIn), asset.decimal));
128
162
  const swapMemo = (streamSwap ? memoStreamingSwap || memo : memo) as string;
129
163
 
130
- return this.deposit({ assetValue, memo: swapMemo, feeOptionKey, router, recipient });
164
+ return this.deposit({
165
+ expiration,
166
+ assetValue,
167
+ memo: swapMemo,
168
+ feeOptionKey,
169
+ router,
170
+ recipient,
171
+ });
131
172
  }
132
173
 
133
- if (SWAP_IN.includes(quoteMode)) {
174
+ if (SWAP_IN.includes(quoteMode) && evmChain) {
134
175
  const { calldata, contract: contractAddress } = route;
135
176
  if (!contractAddress) throw new SwapKitError('core_swap_contract_not_found');
136
177
 
@@ -148,9 +189,7 @@ export class SwapKitCore<T = ''> {
148
189
 
149
190
  const contract = await walletMethods.createContract?.(contractAddress, abi, provider);
150
191
 
151
- // TODO: (@Towan) Contract evm methods should be generic
152
- // @ts-expect-error
153
- const tx = await contract.populateTransaction.swapIn?.(
192
+ const tx = await contract.getFunction('swapIn').populateTransaction(
154
193
  ...getSwapInParams({
155
194
  streamSwap,
156
195
  toChecksumAddress,
@@ -170,21 +209,27 @@ export class SwapKitCore<T = ''> {
170
209
  }
171
210
  };
172
211
 
173
- getWalletByChain = async (chain: Chain) => {
212
+ getWalletByChain = async (chain: Chain, potentialScamFilter?: boolean) => {
174
213
  const address = this.getAddress(chain);
175
214
  if (!address) return null;
215
+ const defaultBalance = [AssetValue.fromChainOrSignature(chain)];
216
+ const walletType = this.connectedChains[chain]?.walletType as WalletOption;
176
217
 
177
- const balance = (await this.getWallet(chain)?.getBalance(address)) ?? [
178
- AssetValue.fromChainOrSignature(chain),
179
- ];
218
+ try {
219
+ const balance = await this.getWallet(chain)?.getBalance(address, potentialScamFilter);
180
220
 
181
- this.connectedChains[chain] = {
182
- address,
183
- balance,
184
- walletType: this.connectedChains[chain]?.walletType as WalletOption,
185
- };
221
+ this.connectedChains[chain] = {
222
+ address,
223
+ balance: balance?.length ? balance : defaultBalance,
224
+ walletType,
225
+ };
186
226
 
187
- return { ...this.connectedChains[chain] };
227
+ return { ...this.connectedChains[chain] };
228
+ } catch (error) {
229
+ console.error(error);
230
+
231
+ return { address, balance: defaultBalance, walletType };
232
+ }
188
233
  };
189
234
 
190
235
  approveAssetValue = (assetValue: AssetValue, contractAddress?: string) =>
@@ -215,6 +260,8 @@ export class SwapKitCore<T = ''> {
215
260
  }: CoreTxParams & { router?: string }) => {
216
261
  const { chain, symbol, ticker } = assetValue;
217
262
  const walletInstance = this.connectedWallets[chain];
263
+ if (!(await validateAddressType({ address: await walletInstance?.getAddress(), chain })))
264
+ throw new SwapKitError('core_transaction_invalid_sender_address');
218
265
  if (!walletInstance) throw new SwapKitError('core_wallet_connection_not_found');
219
266
 
220
267
  const params = this.#prepareTxParams({ assetValue, recipient, router, ...rest });
@@ -235,10 +282,10 @@ export class SwapKitCore<T = ''> {
235
282
  chain === Chain.Avalanche
236
283
  ? TCAvalancheDepositABI
237
284
  : chain === Chain.BinanceSmartChain
238
- ? TCBscDepositABI
239
- : TCEthereumVaultAbi;
285
+ ? TCBscDepositABI
286
+ : TCEthereumVaultAbi;
240
287
 
241
- return (await (
288
+ const response = await (
242
289
  walletInstance as EVMWallet<typeof AVAXToolbox | typeof ETHToolbox | typeof BSCToolbox>
243
290
  ).call({
244
291
  abi,
@@ -248,13 +295,17 @@ export class SwapKitCore<T = ''> {
248
295
  funcParams: [
249
296
  recipient,
250
297
  getChecksumAddressFromAsset({ chain, symbol, ticker }, chain),
251
- // TODO: (@Towan) Re-Check on that conversion 🙏
252
- assetValue.baseValueBigInt.toString(),
298
+ assetValue.getBaseValue('string'),
253
299
  params.memo,
254
- rest.expiration,
300
+ rest.expiration || parseInt(`${(new Date().getTime() + 15 * 60 * 1000) / 1000}`),
255
301
  ],
256
- txOverrides: { from: params.from, value: assetValue.baseValueBigInt },
257
- })) as Promise<string>;
302
+ txOverrides: {
303
+ from: params.from,
304
+ value: assetValue.isGasAsset ? assetValue.getBaseValue('bigint') : undefined,
305
+ },
306
+ });
307
+
308
+ return response as string;
258
309
  }
259
310
 
260
311
  default: {
@@ -269,10 +320,10 @@ export class SwapKitCore<T = ''> {
269
320
  const errorKey: Keys = isInsufficientFunds
270
321
  ? 'core_transaction_deposit_insufficient_funds_error'
271
322
  : isGas
272
- ? 'core_transaction_deposit_gas_error'
273
- : isServer
274
- ? 'core_transaction_deposit_server_error'
275
- : 'core_transaction_deposit_error';
323
+ ? 'core_transaction_deposit_gas_error'
324
+ : isServer
325
+ ? 'core_transaction_deposit_server_error'
326
+ : 'core_transaction_deposit_error';
276
327
 
277
328
  throw new SwapKitError(errorKey, error);
278
329
  }
@@ -323,7 +374,6 @@ export class SwapKitCore<T = ''> {
323
374
  };
324
375
 
325
376
  addLiquidity = async ({
326
- poolIdentifier,
327
377
  runeAssetValue,
328
378
  assetValue,
329
379
  runeAddr,
@@ -331,7 +381,6 @@ export class SwapKitCore<T = ''> {
331
381
  isPendingSymmAsset,
332
382
  mode = 'sym',
333
383
  }: {
334
- poolIdentifier: string;
335
384
  runeAssetValue: AssetValue;
336
385
  assetValue: AssetValue;
337
386
  isPendingSymmAsset?: boolean;
@@ -339,7 +388,7 @@ export class SwapKitCore<T = ''> {
339
388
  assetAddr?: string;
340
389
  mode?: 'sym' | 'rune' | 'asset';
341
390
  }) => {
342
- const [chain, ...symbolPath] = poolIdentifier.split('.') as [Chain, string];
391
+ const { chain, symbol } = assetValue;
343
392
  const isSym = mode === 'sym';
344
393
  const runeTransfer = runeAssetValue?.gt(0) && (isSym || mode === 'rune');
345
394
  const assetTransfer = assetValue?.gt(0) && (isSym || mode === 'asset');
@@ -355,13 +404,12 @@ export class SwapKitCore<T = ''> {
355
404
  }
356
405
 
357
406
  let runeTx, assetTx;
358
- const sharedParams = { chain, symbol: symbolPath.join('.') };
359
407
 
360
408
  if (runeTransfer && runeAssetValue) {
361
409
  try {
362
410
  runeTx = await this.#depositToPool({
363
411
  assetValue: runeAssetValue,
364
- memo: getMemoFor(MemoType.DEPOSIT, { ...sharedParams, address: assetAddress }),
412
+ memo: getMemoFor(MemoType.DEPOSIT, { chain, symbol, address: assetAddress }),
365
413
  });
366
414
  } catch (error) {
367
415
  throw new SwapKitError('core_transaction_add_liquidity_rune_error', error);
@@ -372,7 +420,7 @@ export class SwapKitCore<T = ''> {
372
420
  try {
373
421
  assetTx = await this.#depositToPool({
374
422
  assetValue,
375
- memo: getMemoFor(MemoType.DEPOSIT, { ...sharedParams, address: runeAddress }),
423
+ memo: getMemoFor(MemoType.DEPOSIT, { chain, symbol, address: runeAddress }),
376
424
  });
377
425
  } catch (error) {
378
426
  throw new SwapKitError('core_transaction_add_liquidity_asset_error', error);
@@ -382,6 +430,29 @@ export class SwapKitCore<T = ''> {
382
430
  return { runeTx, assetTx };
383
431
  };
384
432
 
433
+ addLiquidityPart = ({
434
+ assetValue,
435
+ poolAddress,
436
+ address,
437
+ symmetric,
438
+ }: {
439
+ assetValue: AssetValue;
440
+ address?: string;
441
+ poolAddress: string;
442
+ symmetric: boolean;
443
+ }) => {
444
+ if (symmetric && !address) {
445
+ throw new SwapKitError('core_transaction_add_liquidity_invalid_params');
446
+ }
447
+ const memo = getMemoFor(MemoType.DEPOSIT, {
448
+ chain: poolAddress.split('.')[0] as Chain,
449
+ symbol: poolAddress.split('.')[1],
450
+ address: symmetric ? address : '',
451
+ });
452
+
453
+ return this.#depositToPool({ assetValue, memo });
454
+ };
455
+
385
456
  withdraw = async ({
386
457
  memo,
387
458
  assetValue,
@@ -396,31 +467,25 @@ export class SwapKitCore<T = ''> {
396
467
  to: 'sym' | 'rune' | 'asset';
397
468
  }) => {
398
469
  const targetAsset =
399
- to === 'rune'
470
+ to === 'rune' && from !== 'rune'
400
471
  ? AssetValue.fromChainOrSignature(Chain.THORChain)
401
472
  : (from === 'sym' && to === 'sym') || from === 'rune' || from === 'asset'
402
- ? undefined
403
- : assetValue;
473
+ ? undefined
474
+ : assetValue;
404
475
 
405
- try {
406
- const txHash = await this.#depositToPool({
407
- assetValue: getMinAmountByChain(from === 'asset' ? assetValue.chain : Chain.THORChain),
408
- memo:
409
- memo ||
410
- getMemoFor(MemoType.WITHDRAW, {
411
- symbol: assetValue.symbol,
412
- chain: assetValue.chain,
413
- ticker: assetValue.ticker,
414
- basisPoints: Math.max(10000, Math.round(percent * 100)),
415
- targetAssetString: targetAsset?.toString(),
416
- singleSide: false,
417
- }),
476
+ const value = getMinAmountByChain(from === 'asset' ? assetValue.chain : Chain.THORChain);
477
+ const memoString =
478
+ memo ||
479
+ getMemoFor(MemoType.WITHDRAW, {
480
+ symbol: assetValue.symbol,
481
+ chain: assetValue.chain,
482
+ ticker: assetValue.ticker,
483
+ basisPoints: Math.min(10000, Math.round(percent * 100)),
484
+ targetAssetString: targetAsset?.toString(),
485
+ singleSide: false,
418
486
  });
419
487
 
420
- return txHash;
421
- } catch (error) {
422
- throw new SwapKitError('core_transaction_withdraw_error', error);
423
- }
488
+ return this.#depositToPool({ assetValue: value, memo: memoString });
424
489
  };
425
490
 
426
491
  savings = async ({
@@ -440,10 +505,13 @@ export class SwapKitCore<T = ''> {
440
505
  symbol: assetValue.symbol,
441
506
  chain: assetValue.chain,
442
507
  singleSide: true,
443
- basisPoints: percent ? Math.max(10000, Math.round(percent * 100)) : undefined,
508
+ basisPoints: percent ? Math.min(10000, Math.round(percent * 100)) : undefined,
444
509
  });
445
510
 
446
- return this.#depositToPool({ assetValue, memo: memoString });
511
+ const value =
512
+ memoType === MemoType.DEPOSIT ? assetValue : getMinAmountByChain(assetValue.chain);
513
+
514
+ return this.#depositToPool({ memo: memoString, assetValue: value });
447
515
  };
448
516
 
449
517
  loan = ({
@@ -480,7 +548,7 @@ export class SwapKitCore<T = ''> {
480
548
  type === 'bond' ? MemoType.BOND : type === 'unbond' ? MemoType.UNBOND : MemoType.LEAVE;
481
549
  const memo = getMemoFor(memoType, {
482
550
  address,
483
- unbondAmount: type === 'unbond' ? assetValue.baseValueNumber : undefined,
551
+ unbondAmount: type === 'unbond' ? assetValue.getBaseValue('number') : undefined,
484
552
  });
485
553
 
486
554
  return this.#thorchainTransfer({
@@ -498,7 +566,7 @@ export class SwapKitCore<T = ''> {
498
566
  extend = ({ wallets, config, apis = {}, rpcUrls = {} }: ExtendParams<T>) => {
499
567
  try {
500
568
  wallets.forEach((wallet) => {
501
- // @ts-expect-error ANCHOR - Not Worth
569
+ // @ts-expect-error - this is fine as we are extending the class
502
570
  this[wallet.connectMethodName] = wallet.connect({
503
571
  addChain: this.#addConnectedChain,
504
572
  config: config || {},
@@ -612,7 +680,7 @@ export class SwapKitCore<T = ''> {
612
680
  };
613
681
 
614
682
  #approve = async <T = string>({
615
- assetValue: { baseValueBigInt, address, chain, isGasAsset, isSynthetic },
683
+ assetValue,
616
684
  type = 'checkOnly',
617
685
  contractAddress,
618
686
  }: {
@@ -620,6 +688,7 @@ export class SwapKitCore<T = ''> {
620
688
  type?: 'checkOnly' | 'approve';
621
689
  contractAddress?: string;
622
690
  }) => {
691
+ const { address, chain, isGasAsset, isSynthetic } = assetValue;
623
692
  const isEVMChain = [Chain.Ethereum, Chain.Avalanche, Chain.BinanceSmartChain].includes(chain);
624
693
  const isNativeEVM = isEVMChain && isGasAsset;
625
694
 
@@ -638,7 +707,7 @@ export class SwapKitCore<T = ''> {
638
707
  contractAddress || ((await this.#getInboundDataByChain(chain)).router as string);
639
708
 
640
709
  return walletAction({
641
- amount: baseValueBigInt,
710
+ amount: assetValue.getBaseValue('bigint'),
642
711
  assetAddress: address,
643
712
  from,
644
713
  spenderAddress,
@@ -1,4 +1,4 @@
1
- import { getRequest } from '@swapkit/helpers';
1
+ import { RequestClient } from '@swapkit/helpers';
2
2
  import type { Chain } from '@swapkit/types';
3
3
  import { ApiUrl } from '@swapkit/types';
4
4
 
@@ -21,11 +21,11 @@ type InboundAddressData = {
21
21
  export const getInboundData = (stagenet: boolean) => {
22
22
  const baseUrl = stagenet ? ApiUrl.ThornodeStagenet : ApiUrl.ThornodeMainnet;
23
23
 
24
- return getRequest<InboundAddressData>(`${baseUrl}/thorchain/inbound_addresses`);
24
+ return RequestClient.get<InboundAddressData>(`${baseUrl}/thorchain/inbound_addresses`);
25
25
  };
26
26
 
27
27
  export const getMimirData = (stagenet: boolean) => {
28
28
  const baseUrl = stagenet ? ApiUrl.ThornodeStagenet : ApiUrl.ThornodeMainnet;
29
29
 
30
- return getRequest<Record<string, number>>(`${baseUrl}/thorchain/mimir`);
30
+ return RequestClient.get<Record<string, number>>(`${baseUrl}/thorchain/mimir`);
31
31
  };
@@ -1 +0,0 @@
1
- "use strict";var nt=Object.defineProperty;var st=(e,t,r)=>t in e?nt(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r;var j=(e,t,r)=>(st(e,typeof t!="symbol"?t+"":t,r),r),D=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var s=(e,t,r)=>(D(e,t,"read from private field"),r?r.call(e):t.get(e)),b=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r)},M=(e,t,r,i)=>(D(e,t,"write to private field"),i?i.call(e,r):t.set(e,r),r);var u=(e,t,r)=>(D(e,t,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Q="6.7.1";function ot(e,t,r){const i=t.split("|").map(o=>o.trim());for(let o=0;o<i.length;o++)switch(t){case"any":return;case"bigint":case"boolean":case"number":case"string":if(typeof e===t)return}const n=new Error(`invalid value for type ${t}`);throw n.code="INVALID_ARGUMENT",n.argument=`value.${r}`,n.value=e,n}function K(e,t,r){for(let i in t){let n=t[i];const o=r?r[i]:null;o&&ot(n,o,i),Object.defineProperty(e,i,{enumerable:!0,value:n,writable:!1})}}function x(e){if(e==null)return"null";if(Array.isArray(e))return"[ "+e.map(x).join(", ")+" ]";if(e instanceof Uint8Array){const t="0123456789abcdef";let r="0x";for(let i=0;i<e.length;i++)r+=t[e[i]>>4],r+=t[e[i]&15];return r}if(typeof e=="object"&&typeof e.toJSON=="function")return x(e.toJSON());switch(typeof e){case"boolean":case"symbol":return e.toString();case"bigint":return BigInt(e).toString();case"number":return e.toString();case"string":return JSON.stringify(e);case"object":{const t=Object.keys(e);return t.sort(),"{ "+t.map(r=>`${x(r)}: ${x(e[r])}`).join(", ")+" }"}}return"[ COULD NOT SERIALIZE ]"}function W(e,t,r){{const n=[];if(r){if("message"in r||"code"in r||"name"in r)throw new Error(`value will overwrite populated values: ${x(r)}`);for(const o in r){const l=r[o];n.push(o+"="+x(l))}}n.push(`code=${t}`),n.push(`version=${Q}`),n.length&&(e+=" ("+n.join(", ")+")")}let i;switch(t){case"INVALID_ARGUMENT":i=new TypeError(e);break;case"NUMERIC_FAULT":case"BUFFER_OVERRUN":i=new RangeError(e);break;default:i=new Error(e)}return K(i,{code:t}),r&&Object.assign(i,r),i}function g(e,t,r,i){if(!e)throw W(t,r,i)}function c(e,t,r,i){g(e,t,"INVALID_ARGUMENT",{argument:r,value:i})}["NFD","NFC","NFKD","NFKC"].reduce((e,t)=>{try{if("test".normalize(t)!=="test")throw new Error("bad");if(t==="NFD"){const r=String.fromCharCode(233).normalize("NFD"),i=String.fromCharCode(101,769);if(r!==i)throw new Error("broken")}e.push(t)}catch{}return e},[]);function Y(e,t,r){if(r==null&&(r=""),e!==t){let i=r,n="new";r&&(i+=".",n+=" "+r),g(!1,`private constructor; use ${i}from* methods`,"UNSUPPORTED_OPERATION",{operation:n})}}function ft(e,t,r){if(e instanceof Uint8Array)return r?new Uint8Array(e):e;if(typeof e=="string"&&e.match(/^0x([0-9a-f][0-9a-f])*$/i)){const i=new Uint8Array((e.length-2)/2);let n=2;for(let o=0;o<i.length;o++)i[o]=parseInt(e.substring(n,n+2),16),n+=2;return i}c(!1,"invalid BytesLike value",t||"value",e)}function tt(e,t){return ft(e,t,!1)}function ut(e,t){return!(typeof e!="string"||!e.match(/^0x[0-9A-Fa-f]*$/)||typeof t=="number"&&e.length!==2+2*t||t===!0&&e.length%2!==0)}const et=BigInt(0),E=BigInt(1),S=9007199254740991;function k(e,t){const r=q(e,"value"),i=BigInt(T(t,"width"));if(g(r>>i===et,"overflow","NUMERIC_FAULT",{operation:"fromTwos",fault:"overflow",value:e}),r>>i-E){const n=(E<<i)-E;return-((~r&n)+E)}return r}function z(e,t){const r=q(e,"value"),i=BigInt(T(t,"bits"));return r&(E<<i)-E}function V(e,t){switch(typeof e){case"bigint":return e;case"number":return c(Number.isInteger(e),"underflow",t||"value",e),c(e>=-S&&e<=S,"overflow",t||"value",e),BigInt(e);case"string":try{if(e==="")throw new Error("empty string");return e[0]==="-"&&e[1]!=="-"?-BigInt(e.substring(1)):BigInt(e)}catch(r){c(!1,`invalid BigNumberish string: ${r.message}`,t||"value",e)}}c(!1,"invalid BigNumberish value",t||"value",e)}function q(e,t){const r=V(e,t);return g(r>=et,"unsigned value cannot be negative","NUMERIC_FAULT",{fault:"overflow",operation:"getUint",value:e}),r}const X="0123456789abcdef";function rt(e){if(e instanceof Uint8Array){let t="0x0";for(const r of e)t+=X[r>>4],t+=X[r&15];return BigInt(t)}return V(e)}function T(e,t){switch(typeof e){case"bigint":return c(e>=-S&&e<=S,"overflow",t||"value",e),Number(e);case"number":return c(Number.isInteger(e),"underflow",t||"value",e),c(e>=-S&&e<=S,"overflow",t||"value",e),e;case"string":try{if(e==="")throw new Error("empty string");return T(BigInt(e),t)}catch(r){c(!1,`invalid numeric string: ${r.message}`,t||"value",e)}}c(!1,"invalid numeric value",t||"value",e)}const ct=BigInt(-1),d=BigInt(0),F=BigInt(1),lt=BigInt(5),B={};let A="0000";for(;A.length<80;)A+=A;function y(e){let t=A;for(;t.length<e;)t+=t;return BigInt("1"+t.substring(0,e))}function C(e,t,r){const i=BigInt(t.width);if(t.signed){const n=F<<i-F;g(r==null||e>=-n&&e<n,"overflow","NUMERIC_FAULT",{operation:r,fault:"overflow",value:e}),e>d?e=k(z(e,i),i):e=-k(z(-e,i),i)}else{const n=F<<i;g(r==null||e>=0&&e<n,"overflow","NUMERIC_FAULT",{operation:r,fault:"overflow",value:e}),e=(e%n+n)%n&n-F}return e}function P(e){typeof e=="number"&&(e=`fixed128x${e}`);let t=!0,r=128,i=18;if(typeof e=="string"){if(e!=="fixed")if(e==="ufixed")t=!1;else{const o=e.match(/^(u?)fixed([0-9]+)x([0-9]+)$/);c(o,"invalid fixed format","format",e),t=o[1]!=="u",r=parseInt(o[2]),i=parseInt(o[3])}}else if(e){const o=e,l=(h,R,it)=>o[h]==null?it:(c(typeof o[h]===R,"invalid fixed format ("+h+" not "+R+")","format."+h,o[h]),o[h]);t=l("signed","boolean",t),r=l("width","number",r),i=l("decimals","number",i)}c(r%8===0,"invalid FixedNumber width (not byte aligned)","format.width",r),c(i<=80,"invalid FixedNumber decimals (too large)","format.decimals",i);const n=(t?"":"u")+"fixed"+String(r)+"x"+String(i);return{signed:t,width:r,decimals:i,name:n}}function at(e,t){let r="";e<d&&(r="-",e*=ct);let i=e.toString();if(t===0)return r+i;for(;i.length<=t;)i=A+i;const n=i.length-t;for(i=i.substring(0,n)+"."+i.substring(n);i[0]==="0"&&i[1]!==".";)i=i.substring(1);for(;i[i.length-1]==="0"&&i[i.length-2]!==".";)i=i.substring(0,i.length-1);return r+i}var m,f,a,N,U,w,p,$,G,L,H,v,J,_,Z;const I=class I{constructor(t,r,i){b(this,N);b(this,w);b(this,$);b(this,L);b(this,v);b(this,_);j(this,"format");b(this,m,void 0);b(this,f,void 0);b(this,a,void 0);j(this,"_value");Y(t,B,"FixedNumber"),M(this,f,r),M(this,m,i);const n=at(r,i.decimals);K(this,{format:i.name,_value:n}),M(this,a,y(i.decimals))}get signed(){return s(this,m).signed}get width(){return s(this,m).width}get decimals(){return s(this,m).decimals}get value(){return s(this,f)}addUnsafe(t){return u(this,$,G).call(this,t)}add(t){return u(this,$,G).call(this,t,"add")}subUnsafe(t){return u(this,L,H).call(this,t)}sub(t){return u(this,L,H).call(this,t,"sub")}mulUnsafe(t){return u(this,v,J).call(this,t)}mul(t){return u(this,v,J).call(this,t,"mul")}mulSignal(t){u(this,N,U).call(this,t);const r=s(this,f)*s(t,f);return g(r%s(this,a)===d,"precision lost during signalling mul","NUMERIC_FAULT",{operation:"mulSignal",fault:"underflow",value:this}),u(this,w,p).call(this,r/s(this,a),"mulSignal")}divUnsafe(t){return u(this,_,Z).call(this,t)}div(t){return u(this,_,Z).call(this,t,"div")}divSignal(t){g(s(t,f)!==d,"division by zero","NUMERIC_FAULT",{operation:"div",fault:"divide-by-zero",value:this}),u(this,N,U).call(this,t);const r=s(this,f)*s(this,a);return g(r%s(t,f)===d,"precision lost during signalling div","NUMERIC_FAULT",{operation:"divSignal",fault:"underflow",value:this}),u(this,w,p).call(this,r/s(t,f),"divSignal")}cmp(t){let r=this.value,i=t.value;const n=this.decimals-t.decimals;return n>0?i*=y(n):n<0&&(r*=y(-n)),r<i?-1:r>i?1:0}eq(t){return this.cmp(t)===0}lt(t){return this.cmp(t)<0}lte(t){return this.cmp(t)<=0}gt(t){return this.cmp(t)>0}gte(t){return this.cmp(t)>=0}floor(){let t=s(this,f);return s(this,f)<d&&(t-=s(this,a)-F),t=s(this,f)/s(this,a)*s(this,a),u(this,w,p).call(this,t,"floor")}ceiling(){let t=s(this,f);return s(this,f)>d&&(t+=s(this,a)-F),t=s(this,f)/s(this,a)*s(this,a),u(this,w,p).call(this,t,"ceiling")}round(t){if(t==null&&(t=0),t>=this.decimals)return this;const r=this.decimals-t,i=lt*y(r-1);let n=this.value+i;const o=y(r);return n=n/o*o,C(n,s(this,m),"round"),new I(B,n,s(this,m))}isZero(){return s(this,f)===d}isNegative(){return s(this,f)<d}toString(){return this._value}toUnsafeFloat(){return parseFloat(this.toString())}toFormat(t){return I.fromString(this.toString(),t)}static fromValue(t,r,i){const n=r==null?0:T(r),o=P(i);let l=V(t,"value");const h=n-o.decimals;if(h>0){const R=y(h);g(l%R===d,"value loses precision for format","NUMERIC_FAULT",{operation:"fromValue",fault:"underflow",value:t}),l/=R}else h<0&&(l*=y(-h));return C(l,o,"fromValue"),new I(B,l,o)}static fromString(t,r){const i=t.match(/^(-?)([0-9]*)\.?([0-9]*)$/);c(i&&i[2].length+i[3].length>0,"invalid FixedNumber string value","value",t);const n=P(r);let o=i[2]||"0",l=i[3]||"";for(;l.length<n.decimals;)l+=A;g(l.substring(n.decimals).match(/^0*$/),"too many decimals for format","NUMERIC_FAULT",{operation:"fromString",fault:"underflow",value:t}),l=l.substring(0,n.decimals);const h=BigInt(i[1]+o+l);return C(h,n,"fromString"),new I(B,h,n)}static fromBytes(t,r){let i=rt(tt(t,"value"));const n=P(r);return n.signed&&(i=k(i,n.width)),C(i,n,"fromBytes"),new I(B,i,n)}};m=new WeakMap,f=new WeakMap,a=new WeakMap,N=new WeakSet,U=function(t){c(this.format===t.format,"incompatible format; use fixedNumber.toFormat","other",t)},w=new WeakSet,p=function(t,r){return t=C(t,s(this,m),r),new I(B,t,s(this,m))},$=new WeakSet,G=function(t,r){return u(this,N,U).call(this,t),u(this,w,p).call(this,s(this,f)+s(t,f),r)},L=new WeakSet,H=function(t,r){return u(this,N,U).call(this,t),u(this,w,p).call(this,s(this,f)-s(t,f),r)},v=new WeakSet,J=function(t,r){return u(this,N,U).call(this,t),u(this,w,p).call(this,s(this,f)*s(t,f)/s(this,a),r)},_=new WeakSet,Z=function(t,r){return g(s(t,f)!==d,"division by zero","NUMERIC_FAULT",{operation:"div",fault:"divide-by-zero",value:this}),u(this,N,U).call(this,t),u(this,w,p).call(this,s(this,f)*s(this,a)/s(t,f),r)};let O=I;const ht=["wei","kwei","mwei","gwei","szabo","finney","ether"];function gt(e,t){c(typeof e=="string","value must be a string","value",e);let r=18;if(typeof t=="string"){const i=ht.indexOf(t);c(i>=0,"invalid unit","unit",t),r=3*i}else t!=null&&(r=T(t,"unit"));return O.fromString(e,{decimals:r,width:512}).value}exports.FixedNumber=O;exports.assert=g;exports.assertArgument=c;exports.assertPrivate=Y;exports.defineProperties=K;exports.fromTwos=k;exports.getBigInt=V;exports.getBytes=tt;exports.getNumber=T;exports.getUint=q;exports.isHexString=ut;exports.makeError=W;exports.mask=z;exports.parseUnits=gt;exports.toBigInt=rt;exports.version=Q;