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

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,51 @@ 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
+ if (contractCallParams && evmChain) {
106
+ const walletMethods = this.connectedWallets[evmChain];
107
+
108
+ if (!walletMethods?.call) {
109
+ throw new SwapKitError('core_wallet_connection_not_found');
110
+ }
111
+
112
+ const { contractAddress, contractMethod, contractParams, contractParamsStreaming } =
113
+ contractCallParams;
114
+
115
+ if (!(streamSwap ? contractParamsStreaming : contractParams)) {
116
+ throw new SwapKitError('core_swap_route_transaction_not_found');
117
+ }
118
+
119
+ return await walletMethods.call<string>({
120
+ contractAddress,
121
+ abi: lowercasedContractAbiMapping[contractAddress.toLowerCase()],
122
+ funcName: contractMethod,
123
+ funcParams: streamSwap ? contractParamsStreaming : contractParams,
124
+ });
125
+ }
126
+
127
+ if (AGG_SWAP.includes(quoteMode) && evmChain) {
90
128
  const walletMethods = this.connectedWallets[evmChain];
91
129
  if (!walletMethods?.sendTransaction) {
92
130
  throw new SwapKitError('core_wallet_connection_not_found');
@@ -95,7 +133,6 @@ export class SwapKitCore<T = ''> {
95
133
  const transaction = streamSwap ? route?.streamingSwap?.transaction : route?.transaction;
96
134
  if (!transaction) throw new SwapKitError('core_swap_route_transaction_not_found');
97
135
 
98
- const { isHexString, parseUnits } = await import('ethers');
99
136
  const { data, from, to, value } = route.transaction;
100
137
 
101
138
  const params = {
@@ -103,11 +140,7 @@ export class SwapKitCore<T = ''> {
103
140
  from,
104
141
  to: to.toLowerCase(),
105
142
  chainId: BigInt(ChainToChainId[evmChain]),
106
- value: value
107
- ? new SwapKitNumber({
108
- value: !isHexString(value) ? parseUnits(value, 'wei').toString(16) : value,
109
- }).baseValueBigInt
110
- : 0n,
143
+ value: value ? BigInt(value) : 0n,
111
144
  };
112
145
 
113
146
  return walletMethods.sendTransaction(params, feeOptionKey) as Promise<string>;
@@ -121,16 +154,23 @@ export class SwapKitCore<T = ''> {
121
154
  const { address: recipient } = await this.#getInboundDataByChain(asset.chain);
122
155
  const {
123
156
  contract: router,
124
- calldata: { amountIn, memo, memoStreamingSwap },
157
+ calldata: { expiration, amountIn, memo, memoStreamingSwap },
125
158
  } = route;
126
159
 
127
160
  const assetValue = asset.add(SwapKitNumber.fromBigInt(BigInt(amountIn), asset.decimal));
128
161
  const swapMemo = (streamSwap ? memoStreamingSwap || memo : memo) as string;
129
162
 
130
- return this.deposit({ assetValue, memo: swapMemo, feeOptionKey, router, recipient });
163
+ return this.deposit({
164
+ expiration,
165
+ assetValue,
166
+ memo: swapMemo,
167
+ feeOptionKey,
168
+ router,
169
+ recipient,
170
+ });
131
171
  }
132
172
 
133
- if (SWAP_IN.includes(quoteMode)) {
173
+ if (SWAP_IN.includes(quoteMode) && evmChain) {
134
174
  const { calldata, contract: contractAddress } = route;
135
175
  if (!contractAddress) throw new SwapKitError('core_swap_contract_not_found');
136
176
 
@@ -148,9 +188,7 @@ export class SwapKitCore<T = ''> {
148
188
 
149
189
  const contract = await walletMethods.createContract?.(contractAddress, abi, provider);
150
190
 
151
- // TODO: (@Towan) Contract evm methods should be generic
152
- // @ts-expect-error
153
- const tx = await contract.populateTransaction.swapIn?.(
191
+ const tx = await contract.getFunction('swapIn').populateTransaction(
154
192
  ...getSwapInParams({
155
193
  streamSwap,
156
194
  toChecksumAddress,
@@ -170,21 +208,27 @@ export class SwapKitCore<T = ''> {
170
208
  }
171
209
  };
172
210
 
173
- getWalletByChain = async (chain: Chain) => {
211
+ getWalletByChain = async (chain: Chain, potentialScamFilter?: boolean) => {
174
212
  const address = this.getAddress(chain);
175
213
  if (!address) return null;
214
+ const defaultBalance = [AssetValue.fromChainOrSignature(chain)];
215
+ const walletType = this.connectedChains[chain]?.walletType as WalletOption;
176
216
 
177
- const balance = (await this.getWallet(chain)?.getBalance(address)) ?? [
178
- AssetValue.fromChainOrSignature(chain),
179
- ];
217
+ try {
218
+ const balance = await this.getWallet(chain)?.getBalance(address, potentialScamFilter);
180
219
 
181
- this.connectedChains[chain] = {
182
- address,
183
- balance,
184
- walletType: this.connectedChains[chain]?.walletType as WalletOption,
185
- };
220
+ this.connectedChains[chain] = {
221
+ address,
222
+ balance: balance?.length ? balance : defaultBalance,
223
+ walletType,
224
+ };
225
+
226
+ return { ...this.connectedChains[chain] };
227
+ } catch (error) {
228
+ console.error(error);
186
229
 
187
- return { ...this.connectedChains[chain] };
230
+ return { address, balance: defaultBalance, walletType };
231
+ }
188
232
  };
189
233
 
190
234
  approveAssetValue = (assetValue: AssetValue, contractAddress?: string) =>
@@ -215,6 +259,8 @@ export class SwapKitCore<T = ''> {
215
259
  }: CoreTxParams & { router?: string }) => {
216
260
  const { chain, symbol, ticker } = assetValue;
217
261
  const walletInstance = this.connectedWallets[chain];
262
+ if (!(await validateAddressType({ address: await walletInstance?.getAddress(), chain })))
263
+ throw new SwapKitError('core_transaction_invalid_sender_address');
218
264
  if (!walletInstance) throw new SwapKitError('core_wallet_connection_not_found');
219
265
 
220
266
  const params = this.#prepareTxParams({ assetValue, recipient, router, ...rest });
@@ -235,10 +281,10 @@ export class SwapKitCore<T = ''> {
235
281
  chain === Chain.Avalanche
236
282
  ? TCAvalancheDepositABI
237
283
  : chain === Chain.BinanceSmartChain
238
- ? TCBscDepositABI
239
- : TCEthereumVaultAbi;
284
+ ? TCBscDepositABI
285
+ : TCEthereumVaultAbi;
240
286
 
241
- return (await (
287
+ const response = await (
242
288
  walletInstance as EVMWallet<typeof AVAXToolbox | typeof ETHToolbox | typeof BSCToolbox>
243
289
  ).call({
244
290
  abi,
@@ -248,13 +294,17 @@ export class SwapKitCore<T = ''> {
248
294
  funcParams: [
249
295
  recipient,
250
296
  getChecksumAddressFromAsset({ chain, symbol, ticker }, chain),
251
- // TODO: (@Towan) Re-Check on that conversion 🙏
252
- assetValue.baseValueBigInt.toString(),
297
+ assetValue.getBaseValue('string'),
253
298
  params.memo,
254
- rest.expiration,
299
+ rest.expiration || parseInt(`${(new Date().getTime() + 15 * 60 * 1000) / 1000}`),
255
300
  ],
256
- txOverrides: { from: params.from, value: assetValue.baseValueBigInt },
257
- })) as Promise<string>;
301
+ txOverrides: {
302
+ from: params.from,
303
+ value: assetValue.isGasAsset ? assetValue.getBaseValue('bigint') : undefined,
304
+ },
305
+ });
306
+
307
+ return response as string;
258
308
  }
259
309
 
260
310
  default: {
@@ -269,10 +319,10 @@ export class SwapKitCore<T = ''> {
269
319
  const errorKey: Keys = isInsufficientFunds
270
320
  ? 'core_transaction_deposit_insufficient_funds_error'
271
321
  : isGas
272
- ? 'core_transaction_deposit_gas_error'
273
- : isServer
274
- ? 'core_transaction_deposit_server_error'
275
- : 'core_transaction_deposit_error';
322
+ ? 'core_transaction_deposit_gas_error'
323
+ : isServer
324
+ ? 'core_transaction_deposit_server_error'
325
+ : 'core_transaction_deposit_error';
276
326
 
277
327
  throw new SwapKitError(errorKey, error);
278
328
  }
@@ -323,7 +373,6 @@ export class SwapKitCore<T = ''> {
323
373
  };
324
374
 
325
375
  addLiquidity = async ({
326
- poolIdentifier,
327
376
  runeAssetValue,
328
377
  assetValue,
329
378
  runeAddr,
@@ -331,7 +380,6 @@ export class SwapKitCore<T = ''> {
331
380
  isPendingSymmAsset,
332
381
  mode = 'sym',
333
382
  }: {
334
- poolIdentifier: string;
335
383
  runeAssetValue: AssetValue;
336
384
  assetValue: AssetValue;
337
385
  isPendingSymmAsset?: boolean;
@@ -339,7 +387,7 @@ export class SwapKitCore<T = ''> {
339
387
  assetAddr?: string;
340
388
  mode?: 'sym' | 'rune' | 'asset';
341
389
  }) => {
342
- const [chain, ...symbolPath] = poolIdentifier.split('.') as [Chain, string];
390
+ const { chain, symbol } = assetValue;
343
391
  const isSym = mode === 'sym';
344
392
  const runeTransfer = runeAssetValue?.gt(0) && (isSym || mode === 'rune');
345
393
  const assetTransfer = assetValue?.gt(0) && (isSym || mode === 'asset');
@@ -355,13 +403,12 @@ export class SwapKitCore<T = ''> {
355
403
  }
356
404
 
357
405
  let runeTx, assetTx;
358
- const sharedParams = { chain, symbol: symbolPath.join('.') };
359
406
 
360
407
  if (runeTransfer && runeAssetValue) {
361
408
  try {
362
409
  runeTx = await this.#depositToPool({
363
410
  assetValue: runeAssetValue,
364
- memo: getMemoFor(MemoType.DEPOSIT, { ...sharedParams, address: assetAddress }),
411
+ memo: getMemoFor(MemoType.DEPOSIT, { chain, symbol, address: assetAddress }),
365
412
  });
366
413
  } catch (error) {
367
414
  throw new SwapKitError('core_transaction_add_liquidity_rune_error', error);
@@ -372,7 +419,7 @@ export class SwapKitCore<T = ''> {
372
419
  try {
373
420
  assetTx = await this.#depositToPool({
374
421
  assetValue,
375
- memo: getMemoFor(MemoType.DEPOSIT, { ...sharedParams, address: runeAddress }),
422
+ memo: getMemoFor(MemoType.DEPOSIT, { chain, symbol, address: runeAddress }),
376
423
  });
377
424
  } catch (error) {
378
425
  throw new SwapKitError('core_transaction_add_liquidity_asset_error', error);
@@ -382,6 +429,29 @@ export class SwapKitCore<T = ''> {
382
429
  return { runeTx, assetTx };
383
430
  };
384
431
 
432
+ addLiquidityPart = ({
433
+ assetValue,
434
+ poolAddress,
435
+ address,
436
+ symmetric,
437
+ }: {
438
+ assetValue: AssetValue;
439
+ address?: string;
440
+ poolAddress: string;
441
+ symmetric: boolean;
442
+ }) => {
443
+ if (symmetric && !address) {
444
+ throw new SwapKitError('core_transaction_add_liquidity_invalid_params');
445
+ }
446
+ const memo = getMemoFor(MemoType.DEPOSIT, {
447
+ chain: poolAddress.split('.')[0] as Chain,
448
+ symbol: poolAddress.split('.')[1],
449
+ address: symmetric ? address : '',
450
+ });
451
+
452
+ return this.#depositToPool({ assetValue, memo });
453
+ };
454
+
385
455
  withdraw = async ({
386
456
  memo,
387
457
  assetValue,
@@ -396,31 +466,25 @@ export class SwapKitCore<T = ''> {
396
466
  to: 'sym' | 'rune' | 'asset';
397
467
  }) => {
398
468
  const targetAsset =
399
- to === 'rune'
469
+ to === 'rune' && from !== 'rune'
400
470
  ? AssetValue.fromChainOrSignature(Chain.THORChain)
401
471
  : (from === 'sym' && to === 'sym') || from === 'rune' || from === 'asset'
402
- ? undefined
403
- : assetValue;
472
+ ? undefined
473
+ : assetValue;
404
474
 
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
- }),
475
+ const value = getMinAmountByChain(from === 'asset' ? assetValue.chain : Chain.THORChain);
476
+ const memoString =
477
+ memo ||
478
+ getMemoFor(MemoType.WITHDRAW, {
479
+ symbol: assetValue.symbol,
480
+ chain: assetValue.chain,
481
+ ticker: assetValue.ticker,
482
+ basisPoints: Math.min(10000, Math.round(percent * 100)),
483
+ targetAssetString: targetAsset?.toString(),
484
+ singleSide: false,
418
485
  });
419
486
 
420
- return txHash;
421
- } catch (error) {
422
- throw new SwapKitError('core_transaction_withdraw_error', error);
423
- }
487
+ return this.#depositToPool({ assetValue: value, memo: memoString });
424
488
  };
425
489
 
426
490
  savings = async ({
@@ -440,10 +504,13 @@ export class SwapKitCore<T = ''> {
440
504
  symbol: assetValue.symbol,
441
505
  chain: assetValue.chain,
442
506
  singleSide: true,
443
- basisPoints: percent ? Math.max(10000, Math.round(percent * 100)) : undefined,
507
+ basisPoints: percent ? Math.min(10000, Math.round(percent * 100)) : undefined,
444
508
  });
445
509
 
446
- return this.#depositToPool({ assetValue, memo: memoString });
510
+ const value =
511
+ memoType === MemoType.DEPOSIT ? assetValue : getMinAmountByChain(assetValue.chain);
512
+
513
+ return this.#depositToPool({ memo: memoString, assetValue: value });
447
514
  };
448
515
 
449
516
  loan = ({
@@ -480,7 +547,7 @@ export class SwapKitCore<T = ''> {
480
547
  type === 'bond' ? MemoType.BOND : type === 'unbond' ? MemoType.UNBOND : MemoType.LEAVE;
481
548
  const memo = getMemoFor(memoType, {
482
549
  address,
483
- unbondAmount: type === 'unbond' ? assetValue.baseValueNumber : undefined,
550
+ unbondAmount: type === 'unbond' ? assetValue.getBaseValue('number') : undefined,
484
551
  });
485
552
 
486
553
  return this.#thorchainTransfer({
@@ -498,7 +565,7 @@ export class SwapKitCore<T = ''> {
498
565
  extend = ({ wallets, config, apis = {}, rpcUrls = {} }: ExtendParams<T>) => {
499
566
  try {
500
567
  wallets.forEach((wallet) => {
501
- // @ts-expect-error ANCHOR - Not Worth
568
+ // @ts-expect-error - this is fine as we are extending the class
502
569
  this[wallet.connectMethodName] = wallet.connect({
503
570
  addChain: this.#addConnectedChain,
504
571
  config: config || {},
@@ -612,7 +679,7 @@ export class SwapKitCore<T = ''> {
612
679
  };
613
680
 
614
681
  #approve = async <T = string>({
615
- assetValue: { baseValueBigInt, address, chain, isGasAsset, isSynthetic },
682
+ assetValue,
616
683
  type = 'checkOnly',
617
684
  contractAddress,
618
685
  }: {
@@ -620,6 +687,7 @@ export class SwapKitCore<T = ''> {
620
687
  type?: 'checkOnly' | 'approve';
621
688
  contractAddress?: string;
622
689
  }) => {
690
+ const { address, chain, isGasAsset, isSynthetic } = assetValue;
623
691
  const isEVMChain = [Chain.Ethereum, Chain.Avalanche, Chain.BinanceSmartChain].includes(chain);
624
692
  const isNativeEVM = isEVMChain && isGasAsset;
625
693
 
@@ -638,7 +706,7 @@ export class SwapKitCore<T = ''> {
638
706
  contractAddress || ((await this.#getInboundDataByChain(chain)).router as string);
639
707
 
640
708
  return walletAction({
641
- amount: baseValueBigInt,
709
+ amount: assetValue.getBaseValue('bigint'),
642
710
  assetAddress: address,
643
711
  from,
644
712
  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;