@hyperbridge/sdk 1.2.2 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
1
  import { createConsola, LogLevels } from 'consola';
2
2
  import { flatten, zip, capitalize, maxBy, isNil } from 'lodash-es';
3
- import { toHex, createPublicClient, http, hexToBytes, bytesToHex, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, keccak256, encodePacked, encodeAbiParameters, concatHex, maxUint256, parseUnits } from 'viem';
3
+ import { hexToBytes, encodePacked, toHex, keccak256, encodeAbiParameters, bytesToHex, concatHex, createPublicClient, http, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, maxUint256, parseUnits } from 'viem';
4
4
  import mergeRace from '@async-generator/merge-race';
5
+ import { hasWindow, isNode, env } from 'std-env';
6
+ import { Vector, u8, Struct, Tuple, Enum, _void, u64, u32, Option, bool, u128 } from 'scale-ts';
5
7
  import { gnosisChiado, gnosis, bscTestnet, bsc, soneium, baseSepolia, base, optimismSepolia, optimism, arbitrumSepolia, arbitrum, mainnet, sepolia } from 'viem/chains';
6
8
  import { match } from 'ts-pattern';
7
9
  import { WsProvider, ApiPromise } from '@polkadot/api';
8
10
  import { RpcWebSocketClient } from 'rpc-websocket-client';
9
- import { Vector, u8, Struct, Tuple, Enum, _void, u64, u32, Option, bool, u128 } from 'scale-ts';
10
11
  import { keccakAsU8a, decodeAddress, xxhashAsU8a } from '@polkadot/util-crypto';
11
- import { hasWindow, isNode, env } from 'std-env';
12
12
  import { GraphQLClient } from 'graphql-request';
13
13
  import { u8aToHex } from '@polkadot/util';
14
14
 
@@ -279,234 +279,6 @@ var init_web = __esm({
279
279
  }
280
280
  });
281
281
 
282
- // src/queries.ts
283
- var POST_REQUEST_STATUS = `
284
- query RequestStatusM($hash: String!) {
285
- requests(
286
- filter: { commitment: { equalTo: $hash } }
287
- ) {
288
- nodes {
289
- commitment
290
- timeoutTimestamp
291
- source
292
- dest
293
- to
294
- from
295
- nonce
296
- body
297
- statusMetadata {
298
- nodes {
299
- blockHash
300
- blockNumber
301
- timestamp
302
- chain
303
- status
304
- transactionHash
305
- }
306
- }
307
- }
308
- }
309
- }
310
- `;
311
- var GET_REQUEST_STATUS = `
312
- query GetRequestDetails($commitment: String!) {
313
- getRequests(
314
- filter: { commitment: { equalTo: $commitment } }
315
- ) {
316
- nodes {
317
- id
318
- source
319
- dest
320
- from
321
- keys
322
- nonce
323
- height
324
- context
325
- timeoutTimestamp
326
- fee
327
- blockNumber
328
- blockHash
329
- transactionHash
330
- blockTimestamp
331
- status
332
- chain
333
- commitment
334
- statusMetadata {
335
- nodes {
336
- status
337
- chain
338
- timestamp
339
- blockNumber
340
- blockHash
341
- transactionHash
342
- }
343
- }
344
- }
345
- }
346
- }`;
347
- var STATE_MACHINE_UPDATES_BY_HEIGHT = `
348
- query StateMachineUpdatesByHeight($statemachineId: String!, $height: Int!, $chain: String!) {
349
- stateMachineUpdateEvents(
350
- filter: {
351
- and: [
352
- { stateMachineId: { equalTo: $statemachineId } }
353
- { height: { greaterThanOrEqualTo: $height } }
354
- { chain: { equalTo: $chain } }
355
- ]
356
- }
357
- orderBy: HEIGHT_ASC
358
- first: 1
359
- ) {
360
- nodes {
361
- height
362
- stateMachineId
363
- chain
364
- blockHash
365
- blockNumber
366
- transactionHash
367
- createdAt
368
- }
369
- }
370
- }
371
- `;
372
- var STATE_MACHINE_UPDATES_BY_TIMESTAMP = `
373
- query StateMachineUpdatesByTimestamp($statemachineId: String!, $commitmentTimestamp: BigFloat!, $chain: String!) {
374
- stateMachineUpdateEvents(
375
- filter: {
376
- and: [
377
- { stateMachineId: { equalTo: $statemachineId } }
378
- { commitmentTimestamp: { greaterThanOrEqualTo: $commitmentTimestamp } }
379
- { chain: { equalTo: $chain } }
380
- ]
381
- }
382
- orderBy: COMMITMENT_TIMESTAMP_DESC
383
- first: 1
384
- ) {
385
- nodes {
386
- height
387
- stateMachineId
388
- chain
389
- blockHash
390
- blockNumber
391
- transactionHash
392
- commitmentTimestamp
393
- createdAt
394
- }
395
- }
396
- }
397
- `;
398
- var ASSET_TELEPORTED_BY_PARAMS = `
399
- query AssetTeleportedByParams($from: String!, $to: String!, $dest: String!, $blockNumber: Int!) {
400
- assetTeleporteds(
401
- filter: {
402
- and: [
403
- { from: { equalTo: $from } }
404
- { to: { equalTo: $to } }
405
- { dest: { includes: $dest } }
406
- { blockNumber: { greaterThanOrEqualTo: $blockNumber } }
407
- ]
408
- }
409
- orderBy: CREATED_AT_DESC
410
- first: 1
411
- ) {
412
- nodes {
413
- id
414
- from
415
- to
416
- amount
417
- dest
418
- commitment
419
- createdAt
420
- blockNumber
421
- }
422
- }
423
- }
424
- `;
425
- var GET_RESPONSE_BY_REQUEST_ID = `
426
- query GetResponseByRequestId($requestId: String!) {
427
- getResponses(filter: {requestId: {equalTo: $requestId}}) {
428
- nodes {
429
- id
430
- commitment
431
- responseMessage
432
- }
433
- }
434
- }
435
- `;
436
- var ORDER_STATUS = `
437
- query OrderStatus($commitment: String!) {
438
- orderPlaceds(
439
- filter: { commitment: { equalTo: $commitment } }
440
- ) {
441
- nodes {
442
- id
443
- user
444
- sourceChain
445
- destChain
446
- commitment
447
- deadline
448
- nonce
449
- fees
450
- inputTokens
451
- inputAmounts
452
- inputValuesUSD
453
- inputUSD
454
- outputTokens
455
- outputAmounts
456
- outputBeneficiaries
457
- calldata
458
- status
459
- createdAt
460
- blockNumber
461
- blockTimestamp
462
- transactionHash
463
- statusMetadata {
464
- nodes {
465
- status
466
- chain
467
- timestamp
468
- blockNumber
469
- transactionHash
470
- filler
471
- }
472
- }
473
- }
474
- }
475
- }`;
476
- var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
477
- query TokenGatewayAssetTeleportedStatus($commitment: String!) {
478
- tokenGatewayAssetTeleporteds(
479
- filter: { commitment: { equalTo: $commitment } }
480
- ) {
481
- nodes {
482
- id
483
- from
484
- to
485
- sourceChain
486
- destChain
487
- commitment
488
- amount
489
- usdValue
490
- assetId
491
- redeem
492
- status
493
- createdAt
494
- blockNumber
495
- blockTimestamp
496
- transactionHash
497
- statusMetadata {
498
- nodes {
499
- status
500
- chain
501
- timestamp
502
- blockNumber
503
- transactionHash
504
- }
505
- }
506
- }
507
- }
508
- }`;
509
-
510
282
  // src/types/index.ts
511
283
  var RequestStatus = Object.freeze({
512
284
  SOURCE: "SOURCE",
@@ -554,16 +326,6 @@ var RequestKind = /* @__PURE__ */ ((RequestKind2) => {
554
326
  RequestKind2[RequestKind2["UpdateParams"] = 2] = "UpdateParams";
555
327
  return RequestKind2;
556
328
  })(RequestKind || {});
557
- var AbortSignalInternal = class _AbortSignalInternal extends Error {
558
- constructor(message) {
559
- super();
560
- this.name = "AbortSignalInternal";
561
- this.message = message;
562
- }
563
- static isError(error) {
564
- return error instanceof _AbortSignalInternal;
565
- }
566
- };
567
329
 
568
330
  // src/abis/evmHost.ts
569
331
  var ABI = [
@@ -3590,1985 +3352,2290 @@ var ABI2 = [
3590
3352
  }
3591
3353
  ];
3592
3354
  var handler_default = { ABI: ABI2 };
3593
- var Chains = /* @__PURE__ */ ((Chains2) => {
3594
- Chains2["BSC_CHAPEL"] = "EVM-97";
3595
- Chains2["GNOSIS_CHIADO"] = "EVM-10200";
3596
- Chains2["HYPERBRIDGE_GARGANTUA"] = "KUSAMA-4009";
3597
- Chains2["SEPOLIA"] = "EVM-11155111";
3598
- Chains2["MAINNET"] = "EVM-1";
3599
- Chains2["BSC_MAINNET"] = "EVM-56";
3600
- return Chains2;
3601
- })(Chains || {});
3602
- var chainIds = {
3603
- ["EVM-97" /* BSC_CHAPEL */]: 97,
3604
- ["EVM-10200" /* GNOSIS_CHIADO */]: 10200,
3605
- ["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: 4009,
3606
- ["EVM-11155111" /* SEPOLIA */]: 11155111,
3607
- ["EVM-1" /* MAINNET */]: 1,
3608
- ["EVM-56" /* BSC_MAINNET */]: 56
3609
- };
3610
- var viemChains = {
3611
- "97": bscTestnet,
3612
- "10200": gnosisChiado,
3613
- "11155111": sepolia,
3614
- "1": mainnet,
3615
- "56": bsc
3616
- };
3617
- var WrappedNativeDecimals = {
3618
- ["EVM-97" /* BSC_CHAPEL */]: 18,
3619
- ["EVM-10200" /* GNOSIS_CHIADO */]: 18,
3620
- ["EVM-11155111" /* SEPOLIA */]: 18,
3621
- ["EVM-1" /* MAINNET */]: 18,
3622
- ["EVM-56" /* BSC_MAINNET */]: 18
3623
- };
3624
- var assets = {
3625
- ["EVM-97" /* BSC_CHAPEL */]: {
3626
- WETH: "0xae13d989dac2f0debff460ac112a837c89baa7cd".toLowerCase(),
3627
- DAI: "0x1938165569A5463327fb206bE06d8D9253aa06b7".toLowerCase(),
3628
- USDC: "0xC625ec7D30A4b1AAEfb1304610CdAcD0d606aC92".toLowerCase(),
3629
- USDT: "0xc043f483373072f7f27420d6e7d7ad269c018e18".toLowerCase()
3630
- },
3631
- ["EVM-10200" /* GNOSIS_CHIADO */]: {
3632
- WETH: "0x0000000000000000000000000000000000000000".toLowerCase(),
3633
- DAI: "0x50B1d3c7c073c9caa1Ef207365A2c9C976bD70b9".toLowerCase(),
3634
- USDC: "0x0000000000000000000000000000000000000000".toLowerCase(),
3635
- USDT: "0x0000000000000000000000000000000000000000".toLowerCase()
3636
- },
3637
- ["EVM-11155111" /* SEPOLIA */]: {
3638
- WETH: "0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9".toLowerCase(),
3639
- USDC: "0x0000000000000000000000000000000000000000".toLowerCase(),
3640
- USDT: "0x0000000000000000000000000000000000000000".toLowerCase(),
3641
- DAI: "0x0000000000000000000000000000000000000000".toLowerCase()
3642
- },
3643
- ["EVM-1" /* MAINNET */]: {
3644
- WETH: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".toLowerCase(),
3645
- DAI: "0x6B175474E89094C44Da98b954EedeAC495271d0F".toLowerCase(),
3646
- USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".toLowerCase(),
3647
- USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7".toLowerCase()
3648
- },
3649
- ["EVM-56" /* BSC_MAINNET */]: {
3650
- WETH: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c".toLowerCase(),
3651
- DAI: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3".toLowerCase(),
3652
- USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d".toLowerCase(),
3653
- USDT: "0x55d398326f99059fF775485246999027B3197955".toLowerCase()
3654
- }
3655
- };
3656
- var addresses = {
3657
- IntentGateway: {
3658
- ["EVM-97" /* BSC_CHAPEL */]: "0xb6C27F4beF379d0b5e2fe3Bb36c248D6B71f91A6",
3659
- ["EVM-10200" /* GNOSIS_CHIADO */]: "0xb6C27F4beF379d0b5e2fe3Bb36c248D6B71f91A6",
3660
- ["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
3661
- ["EVM-1" /* MAINNET */]: "0xd54165e45926720b062C192a5bacEC64d5bB08DA",
3662
- ["EVM-56" /* BSC_MAINNET */]: "0xd54165e45926720b062C192a5bacEC64d5bB08DA"
3663
- },
3664
- Host: {
3665
- ["EVM-97" /* BSC_CHAPEL */]: "0x8Aa0Dea6D675d785A882967Bf38183f6117C09b7",
3666
- ["EVM-10200" /* GNOSIS_CHIADO */]: "0x58a41b89f4871725e5d898d98ef4bf917601c5eb",
3667
- ["EVM-11155111" /* SEPOLIA */]: "0x2EdB74C269948b60ec1000040E104cef0eABaae8",
3668
- ["EVM-1" /* MAINNET */]: "0x792A6236AF69787C40cF76b69B4c8c7B28c4cA20",
3669
- ["EVM-56" /* BSC_MAINNET */]: "0x24B5d421Ec373FcA57325dd2F0C074009Af021F7"
3670
- },
3671
- UniswapRouter02: {
3672
- ["EVM-97" /* BSC_CHAPEL */]: "0x9639379819420704457B07A0C33B678D9E0F8Df0",
3673
- ["EVM-10200" /* GNOSIS_CHIADO */]: "0x0000000000000000000000000000000000000000",
3674
- ["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
3675
- ["EVM-1" /* MAINNET */]: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
3676
- ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
3677
- },
3678
- UniswapV2Factory: {
3679
- ["EVM-97" /* BSC_CHAPEL */]: "0x12e036669DA18F4A2777853d6e2136b32AceEC86",
3680
- ["EVM-10200" /* GNOSIS_CHIADO */]: "0x0000000000000000000000000000000000000000",
3681
- ["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
3682
- ["EVM-1" /* MAINNET */]: "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f",
3683
- ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
3684
- },
3685
- BatchExecutor: {
3686
- ["EVM-97" /* BSC_CHAPEL */]: "0x4CC58B5D8FBf838d062E4b21F75C327835B5F0ef",
3687
- ["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
3688
- ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
3689
- },
3690
- UniversalRouter: {
3691
- ["EVM-97" /* BSC_CHAPEL */]: "0xcc6d5ece3d4a57245bf5a2f64f3ed9179b81f714",
3692
- ["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
3693
- ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
3694
- },
3695
- UniswapV3Router: {
3696
- ["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
3697
- ["EVM-1" /* MAINNET */]: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
3698
- ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
3699
- },
3700
- UniswapV3Factory: {
3701
- ["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
3702
- ["EVM-1" /* MAINNET */]: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
3703
- ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
3704
- },
3705
- UniswapV3Quoter: {
3706
- ["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
3707
- ["EVM-1" /* MAINNET */]: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
3708
- ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
3709
- },
3710
- UniswapV4PoolManager: {
3711
- ["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
3712
- ["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
3713
- ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
3714
- },
3715
- UniswapV4Quoter: {
3716
- ["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
3717
- ["EVM-1" /* MAINNET */]: "0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203",
3718
- ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
3719
- },
3720
- Calldispatcher: {
3721
- ["EVM-11155111" /* SEPOLIA */]: "0xC7f13b6D03A0A7F3239d38897503E90553ABe155"
3355
+ function getPeakPosByHeight(height) {
3356
+ return (1n << BigInt(height + 1)) - 2n;
3357
+ }
3358
+ function leftPeakHeightPos(mmrSize) {
3359
+ let height = 1;
3360
+ let prevPos = 0n;
3361
+ let pos = getPeakPosByHeight(height);
3362
+ while (pos < mmrSize) {
3363
+ height += 1;
3364
+ prevPos = pos;
3365
+ pos = getPeakPosByHeight(height);
3722
3366
  }
3723
- };
3724
- var createRpcUrls = (env2) => ({
3725
- ["EVM-97" /* BSC_CHAPEL */]: env2.BSC_CHAPEL || "https://bnb-testnet.api.onfinality.io/public",
3726
- ["EVM-10200" /* GNOSIS_CHIADO */]: env2.GNOSIS_CHIADO || "https://gnosis-chiado-rpc.publicnode.com",
3727
- ["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: env2.HYPERBRIDGE_GARGANTUA || "",
3728
- ["EVM-11155111" /* SEPOLIA */]: env2.SEPOLIA || "https://1rpc.io/sepolia",
3729
- ["EVM-1" /* MAINNET */]: env2.ETH_MAINNET || "https://eth-mainnet.g.alchemy.com/v2/demo",
3730
- ["EVM-56" /* BSC_MAINNET */]: env2.BSC_MAINNET || "https://binance.llamarpc.com"
3731
- });
3732
- var consensusStateIds = {
3733
- ["EVM-97" /* BSC_CHAPEL */]: "BSC0",
3734
- ["EVM-10200" /* GNOSIS_CHIADO */]: "GNO0",
3735
- ["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: "PAS0",
3736
- ["EVM-11155111" /* SEPOLIA */]: "ETH0",
3737
- ["EVM-1" /* MAINNET */]: "ETH0",
3738
- ["EVM-56" /* BSC_MAINNET */]: "BSC0"
3739
- };
3740
-
3741
- // src/configs/ChainConfigService.ts
3742
- var ChainConfigService = class {
3743
- rpcUrls;
3744
- constructor(env2 = process.env) {
3745
- this.rpcUrls = createRpcUrls(env2);
3367
+ return [height - 1, prevPos];
3368
+ }
3369
+ function getRightPeak(initialHeight, initialPos, mmrSize) {
3370
+ let height = initialHeight;
3371
+ let pos = initialPos;
3372
+ pos += siblingOffset(height);
3373
+ while (pos > mmrSize - 1n) {
3374
+ if (height === 0) {
3375
+ return null;
3376
+ }
3377
+ pos -= parentOffset(height - 1);
3378
+ height -= 1;
3746
3379
  }
3747
- getChainConfig(chain) {
3748
- return {
3749
- chainId: chainIds[chain],
3750
- rpcUrl: this.rpcUrls[chain],
3751
- intentGatewayAddress: addresses.IntentGateway[chain]
3752
- };
3380
+ return [height, pos];
3381
+ }
3382
+ function getPeaks(mmrSize) {
3383
+ const positions = [];
3384
+ let [height, pos] = leftPeakHeightPos(mmrSize);
3385
+ positions.push(pos);
3386
+ while (height > 0) {
3387
+ const peak = getRightPeak(height, pos, mmrSize);
3388
+ if (!peak) break;
3389
+ [height, pos] = peak;
3390
+ positions.push(pos);
3753
3391
  }
3754
- getIntentGatewayAddress(chain) {
3755
- return addresses.IntentGateway[chain];
3392
+ return positions;
3393
+ }
3394
+ function allOnes(num) {
3395
+ if (num === 0n) return false;
3396
+ return num.toString(2).split("").every((bit) => bit === "1");
3397
+ }
3398
+ function jumpLeft(pos) {
3399
+ const bitLength = pos.toString(2).length;
3400
+ const mostSignificantBits = 1n << BigInt(bitLength - 1);
3401
+ return pos - (mostSignificantBits - 1n);
3402
+ }
3403
+ function posHeightInTree(initialPos) {
3404
+ let pos = initialPos + 1n;
3405
+ while (!allOnes(pos)) {
3406
+ pos = jumpLeft(pos);
3756
3407
  }
3757
- getHostAddress(chain) {
3758
- return addresses.Host[chain];
3408
+ return pos.toString(2).length - 1;
3409
+ }
3410
+ function parentOffset(height) {
3411
+ return 2n << BigInt(height);
3412
+ }
3413
+ function siblingOffset(height) {
3414
+ return (2n << BigInt(height)) - 1n;
3415
+ }
3416
+ function takeWhileVec(v, p) {
3417
+ const index = v.findIndex((item) => !p(item));
3418
+ if (index === -1) {
3419
+ const result = [...v];
3420
+ v.length = 0;
3421
+ return result;
3759
3422
  }
3760
- getWrappedNativeAssetWithDecimals(chain) {
3761
- return {
3762
- asset: assets[chain].WETH,
3763
- decimals: WrappedNativeDecimals[chain]
3764
- };
3423
+ return v.splice(0, index);
3424
+ }
3425
+ function mmrPositionToKIndex(initialLeaves, mmrSize) {
3426
+ const leaves = [...initialLeaves];
3427
+ const peaks = getPeaks(mmrSize);
3428
+ const leavesWithKIndices = [];
3429
+ for (const peak of peaks) {
3430
+ const peakLeaves = takeWhileVec(leaves, (pos) => pos <= peak);
3431
+ if (peakLeaves.length > 0) {
3432
+ for (const pos of peakLeaves) {
3433
+ const height = posHeightInTree(peak);
3434
+ let index = 0n;
3435
+ let parentPos = peak;
3436
+ for (let h = height; h >= 1; h--) {
3437
+ const leftChild = parentPos - parentOffset(h - 1);
3438
+ const rightChild = leftChild + siblingOffset(h - 1);
3439
+ index *= 2n;
3440
+ if (leftChild >= pos) {
3441
+ parentPos = leftChild;
3442
+ } else {
3443
+ parentPos = rightChild;
3444
+ index += 1n;
3445
+ }
3446
+ }
3447
+ leavesWithKIndices.push([pos, index]);
3448
+ }
3449
+ }
3765
3450
  }
3766
- getDaiAsset(chain) {
3767
- return assets[chain].DAI;
3451
+ return leavesWithKIndices;
3452
+ }
3453
+ function calculateMMRSize(numberOfLeaves) {
3454
+ const numberOfPeaks = numberOfLeaves.toString(2).split("1").length - 1;
3455
+ return 2n * numberOfLeaves - BigInt(numberOfPeaks);
3456
+ }
3457
+ async function generateRootWithProof(postRequest, treeSize) {
3458
+ const { generate_root_with_proof: generate_root_with_proof2 } = await load_ckb_mmr();
3459
+ const { commitment: hash, encodePacked: encodePacked2 } = postRequestCommitment(postRequest);
3460
+ const result = JSON.parse(generate_root_with_proof2(hexToBytes(encodePacked2), treeSize));
3461
+ const { root, proof, mmr_size, leaf_positions, keccak_hash_calldata } = result;
3462
+ if (keccak_hash_calldata !== hash) {
3463
+ console.log("keccak_hash", keccak_hash_calldata);
3464
+ console.log("hash", hash);
3465
+ throw new Error("Abi keccak hash mismatch");
3768
3466
  }
3769
- getUsdtAsset(chain) {
3770
- return assets[chain].USDT;
3467
+ const [[, kIndex]] = mmrPositionToKIndex(leaf_positions, BigInt(mmr_size));
3468
+ return {
3469
+ root,
3470
+ proof,
3471
+ index: treeSize - 1n,
3472
+ kIndex,
3473
+ treeSize,
3474
+ mmrSize: mmr_size
3475
+ };
3476
+ }
3477
+ async function load_ckb_mmr() {
3478
+ if (hasWindow) {
3479
+ const wasm2 = await Promise.resolve().then(() => (init_web(), web_exports));
3480
+ await wasm2.default();
3481
+ return wasm2;
3771
3482
  }
3772
- getUsdcAsset(chain) {
3773
- return assets[chain].USDC;
3774
- }
3775
- getChainId(chain) {
3776
- return chainIds[chain];
3777
- }
3778
- getConsensusStateId(chain) {
3779
- return toHex(consensusStateIds[chain]);
3780
- }
3781
- getHyperbridgeChainId() {
3782
- return chainIds["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */];
3783
- }
3784
- getRpcUrl(chain) {
3785
- return this.rpcUrls[chain];
3786
- }
3787
- getUniswapRouterV2Address(chain) {
3788
- return addresses.UniswapRouter02[chain];
3789
- }
3790
- getUniswapV2FactoryAddress(chain) {
3791
- return addresses.UniswapV2Factory[chain];
3792
- }
3793
- getBatchExecutorAddress(chain) {
3794
- return addresses.BatchExecutor[chain];
3795
- }
3796
- getUniversalRouterAddress(chain) {
3797
- return addresses.UniversalRouter[chain];
3798
- }
3799
- getUniswapV3RouterAddress(chain) {
3800
- return addresses.UniswapV3Router[chain];
3801
- }
3802
- getUniswapV3FactoryAddress(chain) {
3803
- return addresses.UniswapV3Factory[chain];
3804
- }
3805
- getUniswapV3QuoterAddress(chain) {
3806
- return addresses.UniswapV3Quoter[chain];
3807
- }
3808
- getUniswapV4PoolManagerAddress(chain) {
3809
- return addresses.UniswapV4PoolManager[chain];
3810
- }
3811
- getUniswapV4QuoterAddress(chain) {
3812
- return addresses.UniswapV4Quoter[chain];
3813
- }
3814
- };
3815
-
3816
- // src/chains/evm.ts
3817
- var chains = {
3818
- [mainnet.id]: mainnet,
3819
- [arbitrum.id]: arbitrum,
3820
- [arbitrumSepolia.id]: arbitrumSepolia,
3821
- [optimism.id]: optimism,
3822
- [optimismSepolia.id]: optimismSepolia,
3823
- [base.id]: base,
3824
- [baseSepolia.id]: baseSepolia,
3825
- [soneium.id]: soneium,
3826
- [bsc.id]: bsc,
3827
- [bscTestnet.id]: bscTestnet,
3828
- [gnosis.id]: gnosis,
3829
- [gnosisChiado.id]: gnosisChiado
3830
- };
3831
- var DEFAULT_ADDRESS = "0x0000000000000000000000000000000000000000";
3832
- var EvmChain = class {
3833
- constructor(params) {
3834
- this.params = params;
3835
- this.publicClient = createPublicClient({
3836
- // @ts-ignore
3837
- chain: chains[params.chainId],
3838
- transport: http(params.url)
3839
- });
3840
- this.chainConfigService = new ChainConfigService();
3841
- }
3842
- publicClient;
3843
- chainConfigService;
3844
- // Expose minimal getters for external helpers/classes
3845
- get client() {
3846
- return this.publicClient;
3847
- }
3848
- get host() {
3849
- return this.params.host;
3850
- }
3851
- get config() {
3852
- return this.chainConfigService;
3483
+ if (isNode) {
3484
+ const wasm2 = await Promise.resolve().then(() => (init_web(), web_exports));
3485
+ return wasm2;
3853
3486
  }
3487
+ throw new Error(`SDK not setup for ${env}`);
3488
+ }
3489
+ async function __test() {
3490
+ const { generate_root_with_proof: generate_root_with_proof2 } = await load_ckb_mmr();
3491
+ return generate_root_with_proof2(new Uint8Array(), 120n);
3492
+ }
3493
+ var H256 = Vector(u8, 32);
3494
+ var EvmStateProof = Struct({
3854
3495
  /**
3855
- * Derives the key for the request receipt.
3856
- * @param {HexString} commitment - The commitment to derive the key from.
3857
- * @returns {HexString} The derived key.
3496
+ * Proof of the contract state.
3858
3497
  */
3859
- requestReceiptKey(commitment) {
3860
- return deriveMapKey(hexToBytes(commitment), REQUEST_RECEIPTS_SLOT);
3861
- }
3498
+ contractProof: Vector(Vector(u8)),
3862
3499
  /**
3863
- * Queries the request receipt.
3864
- * @param {HexString} commitment - The commitment to query.
3865
- * @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
3500
+ * Proof of the storage state.
3866
3501
  */
3867
- async queryRequestReceipt(commitment) {
3868
- const relayer = await this.publicClient.readContract({
3869
- address: this.params.host,
3870
- abi: evmHost_default.ABI,
3871
- functionName: "requestReceipts",
3872
- args: [commitment]
3873
- });
3874
- return relayer === DEFAULT_ADDRESS ? void 0 : relayer;
3875
- }
3502
+ storageProof: Vector(Tuple(Vector(u8), Vector(Vector(u8))))
3503
+ });
3504
+ var SubstrateHashing = Enum({
3505
+ /* For chains that use keccak as their hashing algo */
3506
+ Keccak: _void,
3507
+ /* For chains that use blake2b as their hashing algo */
3508
+ Blake2: _void
3509
+ });
3510
+ var SubstrateStateMachineProof = Struct({
3876
3511
  /**
3877
- * Queries the proof of the commitments.
3878
- * @param {IMessage} message - The message to query.
3879
- * @param {string} counterparty - The counterparty address.
3880
- * @param {bigint} [at] - The block number to query at.
3881
- * @returns {Promise<HexString>} The proof.
3512
+ * The hasher used to hash the state machine state.
3882
3513
  */
3883
- async queryProof(message, counterparty, at) {
3884
- const commitmentKeys = "Requests" in message ? message.Requests.map((key) => requestCommitmentKey(key)) : message.Responses.map((key) => responseCommitmentKey(key));
3885
- const config = {
3886
- address: this.params.host,
3887
- storageKeys: commitmentKeys
3888
- };
3889
- if (!at) {
3890
- config.blockTag = "latest";
3891
- } else {
3892
- config.blockNumber = at;
3893
- }
3894
- const proof = await this.publicClient.getProof(config);
3895
- const flattenedProof = Array.from(new Set(flatten(proof.storageProof.map((item) => item.proof))));
3896
- const encoded = EvmStateProof.enc({
3897
- contractProof: proof.accountProof.map((item) => Array.from(hexToBytes(item))),
3898
- storageProof: [
3899
- [Array.from(hexToBytes(this.params.host)), flattenedProof.map((item) => Array.from(hexToBytes(item)))]
3900
- ]
3901
- });
3902
- return toHex(encoded);
3903
- }
3514
+ hasher: SubstrateHashing,
3904
3515
  /**
3905
- * Query and return the encoded storage proof for the provided keys at the given height.
3906
- * @param {bigint} at - The block height at which to query the storage proof.
3907
- * @param {HexString[]} keys - The keys for which to query the storage proof.
3908
- * @returns {Promise<HexString>} The encoded storage proof.
3516
+ * Proof of the state machine state.
3909
3517
  */
3910
- async queryStateProof(at, keys) {
3911
- const config = {
3912
- address: this.params.host,
3913
- storageKeys: keys
3914
- };
3915
- if (!at) {
3916
- config.blockTag = "latest";
3917
- } else {
3918
- config.blockNumber = at;
3919
- }
3920
- const proof = await this.publicClient.getProof(config);
3921
- const flattenedProof = Array.from(new Set(flatten(proof.storageProof.map((item) => item.proof))));
3922
- const encoded = EvmStateProof.enc({
3923
- contractProof: proof.accountProof.map((item) => Array.from(hexToBytes(item))),
3924
- storageProof: [
3925
- [Array.from(hexToBytes(this.params.host)), flattenedProof.map((item) => Array.from(hexToBytes(item)))]
3926
- ]
3927
- });
3928
- return toHex(encoded);
3929
- }
3930
- /**
3931
- * Returns the current timestamp of the chain.
3932
- * @returns {Promise<bigint>} The current timestamp.
3518
+ storageProof: Vector(Vector(u8))
3519
+ });
3520
+ var SubstrateStateProof = Enum({
3521
+ /*
3522
+ * Uses overlay root for verification
3933
3523
  */
3934
- async timestamp() {
3935
- const data = await this.publicClient.readContract({
3936
- address: this.params.host,
3937
- abi: evmHost_default.ABI,
3938
- functionName: "timestamp"
3939
- });
3940
- return BigInt(data);
3941
- }
3942
- /**
3943
- * Get the latest state machine height for a given state machine ID.
3944
- * @param {StateMachineIdParams} stateMachineId - The state machine ID.
3945
- * @returns {Promise<bigint>} The latest state machine height.
3524
+ OverlayProof: SubstrateStateMachineProof,
3525
+ /*
3526
+ * Uses state root for verification
3946
3527
  */
3947
- async latestStateMachineHeight(stateMachineId) {
3948
- if (!this.publicClient) throw new Error("API not initialized");
3949
- const id = stateMachineId.stateId.Polkadot || stateMachineId.stateId.Kusama;
3950
- if (!id)
3951
- throw new Error(
3952
- "Expected Polakdot or Kusama State machine id when reading latest state machine height on evm"
3953
- );
3954
- const data = await this.publicClient.readContract({
3955
- address: this.params.host,
3956
- abi: evmHost_default.ABI,
3957
- functionName: "latestStateMachineHeight",
3958
- args: [BigInt(id)]
3959
- });
3960
- return data;
3961
- }
3962
- /**
3963
- * Get the state machine update time for a given state machine height.
3964
- * @param {StateMachineHeight} stateMachineHeight - The state machine height.
3965
- * @returns {Promise<bigint>} The statemachine update time in seconds.
3528
+ StateProof: SubstrateStateMachineProof
3529
+ });
3530
+ var BasicProof = Vector(Vector(u8));
3531
+ var LeafIndexAndPos = Struct({
3532
+ /*
3533
+ * Leaf index
3966
3534
  */
3967
- async stateMachineUpdateTime(stateMachineHeight) {
3968
- if (!this.publicClient) throw new Error("API not initialized");
3969
- const id = stateMachineHeight.id.stateId.Polkadot || stateMachineHeight.id.stateId.Kusama;
3970
- if (!id) throw new Error("Expected Polkadot or Kusama State machine id when reading state machine update time");
3971
- const data = await this.publicClient.readContract({
3972
- address: this.params.host,
3973
- abi: evmHost_default.ABI,
3974
- functionName: "stateMachineCommitmentUpdateTime",
3975
- args: [{ stateMachineId: BigInt(id), height: stateMachineHeight.height }]
3976
- });
3977
- return data;
3978
- }
3979
- /**
3980
- * Get the challenge period for a given state machine id.
3981
- * @param {StateMachineIdParams} stateMachineId - The state machine ID.
3982
- * @returns {Promise<bigint>} The challenge period in seconds.
3535
+ leafIndex: u64,
3536
+ /*
3537
+ * Leaf position in the MMR
3983
3538
  */
3984
- async challengePeriod(stateMachineId) {
3985
- if (!this.publicClient) throw new Error("API not initialized");
3986
- const id = stateMachineId.stateId.Polkadot || stateMachineId.stateId.Kusama;
3987
- if (!id)
3988
- throw new Error(
3989
- "Expected Polkadot or Kusama State machine id when reading latest state machine height on evm"
3990
- );
3991
- const data = await this.publicClient.readContract({
3992
- address: this.params.host,
3993
- abi: evmHost_default.ABI,
3994
- functionName: "challengePeriod"
3995
- });
3996
- return data;
3997
- }
3998
- /**
3999
- * Encodes an ISMP message for the EVM chain.
4000
- * @param {IIsmpMessage} message The ISMP message to encode.
4001
- * @returns {HexString} The encoded calldata.
3539
+ pos: u64
3540
+ });
3541
+ var MmrProof = Struct({
3542
+ /*
3543
+ * Proof of the leaf index and position.
4002
3544
  */
4003
- encode(message) {
4004
- const encoded = match(message).with({ kind: "PostRequest" }, (request) => {
4005
- const mmrProof = MmrProof.dec(request.proof.proof);
4006
- const requests = zip(request.requests, mmrProof.leafIndexAndPos).map(([req, leafIndexAndPos]) => {
4007
- if (!req || !leafIndexAndPos) return;
4008
- const [[, kIndex]] = mmrPositionToKIndex(
4009
- [leafIndexAndPos?.pos],
4010
- calculateMMRSize(mmrProof.leafCount)
4011
- );
4012
- return {
4013
- request: {
4014
- source: toHex(req.source),
4015
- dest: toHex(req.dest),
4016
- to: req.to,
4017
- from: req.from,
4018
- nonce: req.nonce,
4019
- timeoutTimestamp: req.timeoutTimestamp,
4020
- body: req.body
4021
- },
4022
- index: leafIndexAndPos?.leafIndex,
4023
- kIndex
4024
- };
4025
- }).filter((item) => !!item);
4026
- const proof = {
4027
- height: {
4028
- stateMachineId: BigInt(Number.parseInt(request.proof.stateMachine.split("-")[1])),
4029
- height: request.proof.height
4030
- },
4031
- multiproof: mmrProof.items.map((item) => bytesToHex(new Uint8Array(item))),
4032
- leafCount: mmrProof.leafCount
4033
- };
4034
- const encoded2 = encodeFunctionData({
4035
- abi: handler_default.ABI,
4036
- functionName: "handlePostRequests",
4037
- args: [
4038
- this.params.host,
4039
- {
4040
- proof,
4041
- requests
4042
- }
4043
- ]
4044
- });
4045
- return encoded2;
4046
- }).with({ kind: "TimeoutPostRequest" }, (timeout) => {
4047
- const proof = SubstrateStateProof.dec(timeout.proof.proof).value.storageProof.map(
4048
- (item) => toHex(new Uint8Array(item))
4049
- );
4050
- const encoded2 = encodeFunctionData({
4051
- abi: handler_default.ABI,
4052
- functionName: "handlePostRequestTimeouts",
4053
- args: [
4054
- this.params.host,
4055
- {
4056
- height: {
4057
- stateMachineId: BigInt(Number.parseInt(timeout.proof.stateMachine.split("-")[1])),
4058
- height: timeout.proof.height
4059
- },
4060
- timeouts: timeout.requests.map((req) => ({
4061
- source: toHex(req.source),
4062
- dest: toHex(req.dest),
4063
- to: req.to,
4064
- from: req.from,
4065
- nonce: req.nonce,
4066
- timeoutTimestamp: req.timeoutTimestamp,
4067
- body: req.body
4068
- })),
4069
- proof
4070
- }
4071
- ]
4072
- });
4073
- return encoded2;
4074
- }).with({ kind: "GetResponse" }, (request) => {
4075
- const mmrProof = MmrProof.dec(request.proof.proof);
4076
- const responses = zip(request.responses, mmrProof.leafIndexAndPos).map(([req, leafIndexAndPos]) => {
4077
- if (!req || !leafIndexAndPos) return;
4078
- const [[, kIndex]] = mmrPositionToKIndex(
4079
- [leafIndexAndPos?.pos],
4080
- calculateMMRSize(mmrProof.leafCount)
4081
- );
4082
- return {
4083
- response: {
4084
- request: {
4085
- source: toHex(req.get.source),
4086
- dest: toHex(req.get.dest),
4087
- from: req.get.from,
4088
- nonce: req.get.nonce,
4089
- timeoutTimestamp: req.get.timeoutTimestamp,
4090
- keys: req.get.keys,
4091
- context: req.get.context,
4092
- height: req.get.height
4093
- },
4094
- values: req.values
4095
- },
4096
- index: leafIndexAndPos?.leafIndex,
4097
- kIndex
4098
- };
4099
- }).filter((item) => !!item);
4100
- const proof = {
4101
- height: {
4102
- stateMachineId: BigInt(Number.parseInt(request.proof.stateMachine.split("-")[1])),
4103
- height: request.proof.height
4104
- },
4105
- multiproof: mmrProof.items.map((item) => bytesToHex(new Uint8Array(item))),
4106
- leafCount: mmrProof.leafCount
4107
- };
4108
- const encoded2 = encodeFunctionData({
4109
- abi: handler_default.ABI,
4110
- functionName: "handleGetResponses",
4111
- args: [
4112
- this.params.host,
4113
- {
4114
- proof,
4115
- responses
4116
- }
4117
- ]
4118
- });
4119
- return encoded2;
4120
- }).exhaustive();
4121
- return encoded;
4122
- }
4123
- /**
4124
- * Calculates the fee required to send a post request to the destination chain.
4125
- * The fee is calculated based on the per-byte fee for the destination chain
4126
- * multiplied by the size of the request body.
4127
- *
4128
- * @param request - The post request to calculate the fee for
4129
- * @returns The total fee in wei required to send the post request
3545
+ leafIndexAndPos: Vector(LeafIndexAndPos),
3546
+ /*
3547
+ * Proof of the leaf data.
3548
+ */
3549
+ leafCount: u64,
3550
+ /*
3551
+ * Proof elements (hashes of siblings of inner nodes on the path to the leaf).
3552
+ */
3553
+ items: Vector(H256)
3554
+ });
3555
+ var ConsensusStateId = Vector(u8, 4);
3556
+ var ConsensusMessage = Struct({
3557
+ /*
3558
+ * Consensus message data.
3559
+ */
3560
+ consensusProof: Vector(u8),
3561
+ /*
3562
+ * Consensus state Id
3563
+ */
3564
+ consensusStateId: ConsensusStateId,
3565
+ /*
3566
+ * Public key of the sender
3567
+ */
3568
+ signer: Vector(u8)
3569
+ });
3570
+ var FraudProofMessage = Struct({
3571
+ /*
3572
+ * The first valid consensus proof
3573
+ */
3574
+ proof1: Vector(u8),
3575
+ /*
3576
+ * The second valid consensus proof
3577
+ */
3578
+ proof2: Vector(u8),
3579
+ /*
3580
+ * Consensus state Id
3581
+ */
3582
+ consensusStateId: ConsensusStateId
3583
+ });
3584
+ var StateMachine = Enum({
3585
+ /*
3586
+ * Evm state machines
3587
+ */
3588
+ Evm: u32,
3589
+ /*
3590
+ * Polkadot parachains
3591
+ */
3592
+ Polkadot: u32,
3593
+ /*
3594
+ * Kusama parachains
3595
+ */
3596
+ Kusama: u32,
3597
+ /*
3598
+ * Substrate-based standalone chain
3599
+ */
3600
+ Substrate: ConsensusStateId,
3601
+ /*
3602
+ * Tendermint chains
3603
+ */
3604
+ Tendermint: ConsensusStateId
3605
+ });
3606
+ var StateMachineId = Struct({
3607
+ /*
3608
+ * The state machine id
3609
+ */
3610
+ id: StateMachine,
3611
+ /*
3612
+ * The consensus state id
3613
+ */
3614
+ consensusStateId: ConsensusStateId
3615
+ });
3616
+ var StateMachineHeight = Struct({
3617
+ /*
3618
+ * The state machine id
3619
+ */
3620
+ id: StateMachineId,
3621
+ /*
3622
+ * The height of the state machine
3623
+ */
3624
+ height: u64
3625
+ });
3626
+ var Proof = Struct({
3627
+ /*
3628
+ * The height of the state machine
3629
+ */
3630
+ height: StateMachineHeight,
3631
+ /*
3632
+ * The proof
3633
+ */
3634
+ proof: Vector(u8)
3635
+ });
3636
+ var PostRequest = Struct({
3637
+ /*
3638
+ * The source state machine of this request.
3639
+ */
3640
+ source: StateMachine,
3641
+ /*
3642
+ * The destination state machine of this request.
3643
+ */
3644
+ dest: StateMachine,
3645
+ /*
3646
+ * The nonce of this request on the source chain
3647
+ */
3648
+ nonce: u64,
3649
+ /*
3650
+ * Module identifier of the sending module
3651
+ */
3652
+ from: Vector(u8),
3653
+ /*
3654
+ * Module identifier of the receiving module
3655
+ */
3656
+ to: Vector(u8),
3657
+ /*
3658
+ * Timestamp which this request expires in seconds.
3659
+ */
3660
+ timeoutTimestamp: u64,
3661
+ /*
3662
+ * Encoded request body
3663
+ */
3664
+ body: Vector(u8)
3665
+ });
3666
+ var PostResponse = Struct({
3667
+ /*
3668
+ * The request that triggered this response.
3669
+ */
3670
+ post: PostRequest,
3671
+ /*
3672
+ * The response message.
3673
+ */
3674
+ response: Vector(u8),
3675
+ /*
3676
+ * Timestamp at which this response expires in seconds.
3677
+ */
3678
+ timeoutTimestamp: u64
3679
+ });
3680
+ var GetRequest = Struct({
3681
+ /*
3682
+ * The source state machine of this request.
3683
+ */
3684
+ source: StateMachine,
3685
+ /*
3686
+ * The destination state machine of this request.
3687
+ */
3688
+ dest: StateMachine,
3689
+ /*
3690
+ * The nonce of this request on the source chain
3691
+ */
3692
+ nonce: u64,
3693
+ /*
3694
+ * Module identifier of the sending module
3695
+ */
3696
+ from: Vector(u8),
3697
+ /*
3698
+ * Raw Storage keys that would be used to fetch the values from the counterparty
3699
+ * For deriving storage keys for ink contract fields follow the guide in the link below
3700
+ * `<https://use.ink/datastructures/storage-in-metadata#a-full-example>`
3701
+ * Substrate Keys
3702
+ */
3703
+ keys: Vector(Vector(u8)),
3704
+ /*
3705
+ * Some application-specific metadata relating to this request
3706
+ */
3707
+ context: Vector(u8),
3708
+ /*
3709
+ * Host timestamp at which this request expires in seconds
3710
+ */
3711
+ timeoutTimestamp: u64
3712
+ });
3713
+ var StorageValue = Struct({
3714
+ /*
3715
+ * The request storage keys
3716
+ */
3717
+ key: Vector(u8),
3718
+ /*
3719
+ * The verified value
3720
+ */
3721
+ value: Option(Vector(u8))
3722
+ });
3723
+ var GetResponse = Struct({
3724
+ /*
3725
+ * The Get request that triggered this response.
3726
+ */
3727
+ get: GetRequest,
3728
+ /*
3729
+ * Values derived from the state proof
3730
+ */
3731
+ values: Vector(StorageValue)
3732
+ });
3733
+ var Request2 = Enum({
3734
+ /*
3735
+ * A post request allows a module on a state machine to send arbitrary bytes to another module
3736
+ * living in another state machine.
3737
+ */
3738
+ Post: PostRequest,
3739
+ /*
3740
+ * A get request allows a module on a state machine to read the storage of another module
3741
+ * living in another state machine.
3742
+ */
3743
+ Get: GetRequest
3744
+ });
3745
+ var Response2 = Enum({
3746
+ /*
3747
+ * The response to a POST request
3748
+ */
3749
+ Post: PostResponse,
3750
+ /*
3751
+ * The response to a GET request
3752
+ */
3753
+ Get: GetResponse
3754
+ });
3755
+ var RequestMessage = Struct({
3756
+ /*
3757
+ * Requests from source chain
4130
3758
  */
4131
- async quote(request) {
4132
- const perByteFee = await this.publicClient.readContract({
4133
- address: this.params.host,
4134
- abi: evmHost_default.ABI,
4135
- functionName: "perByteFee",
4136
- args: [toHex(request.dest)]
4137
- });
4138
- const bodyByteLength = Math.floor((request.body.length - 2) / 2);
4139
- const length = bodyByteLength < 32 ? 32 : bodyByteLength;
4140
- return perByteFee * BigInt(length);
4141
- }
4142
- /**
4143
- * Estimates the gas required for a post request execution on this chain.
4144
- * This function generates mock proofs for the post request, creates a state override
4145
- * with the necessary overlay root, and estimates the gas cost for executing the
4146
- * handlePostRequests transaction on the handler contract.
4147
- *
4148
- * @param request - The post request to estimate gas for
4149
- * @param paraId - The ID of the parachain (Hyperbridge) that will process the request
4150
- * @returns The estimated gas amount in gas units
3759
+ requests: Vector(PostRequest),
3760
+ /*
3761
+ * Membership batch proof for these requests
4151
3762
  */
4152
- async estimateGas(request) {
4153
- const hostParams = await this.publicClient.readContract({
4154
- address: this.params.host,
4155
- abi: evmHost_default.ABI,
4156
- functionName: "hostParams"
4157
- });
4158
- const { root, proof, index, kIndex, treeSize } = await generateRootWithProof(request, 2n ** 10n);
4159
- const latestStateMachineHeight = 6291991n;
4160
- const paraId = 4009n;
4161
- const overlayRootSlot = getStateCommitmentFieldSlot(
4162
- paraId,
4163
- // Hyperbridge chain id
4164
- latestStateMachineHeight,
4165
- // Hyperbridge chain height
4166
- 1
4167
- // For overlayRoot
4168
- );
4169
- const postParams = {
4170
- height: {
4171
- stateMachineId: BigInt(paraId),
4172
- height: latestStateMachineHeight
4173
- },
4174
- multiproof: proof,
4175
- leafCount: treeSize
4176
- };
4177
- const gas = await this.publicClient.estimateContractGas({
4178
- address: hostParams.handler,
4179
- abi: handler_default.ABI,
4180
- functionName: "handlePostRequests",
4181
- args: [
4182
- this.params.host,
4183
- {
4184
- proof: postParams,
4185
- requests: [
4186
- {
4187
- request: {
4188
- ...request,
4189
- source: toHex(request.source),
4190
- dest: toHex(request.dest)
4191
- },
4192
- index,
4193
- kIndex
4194
- }
4195
- ]
4196
- }
4197
- ],
4198
- stateOverride: [
4199
- {
4200
- address: this.params.host,
4201
- stateDiff: [
4202
- {
4203
- slot: overlayRootSlot,
4204
- value: root
4205
- }
4206
- ]
4207
- }
4208
- ]
4209
- });
4210
- return gas;
4211
- }
4212
- /**
4213
- * Gets the fee token address and decimals for the chain.
4214
- * This function gets the fee token address and decimals for the chain.
4215
- *
4216
- * @returns The fee token address and decimals
3763
+ proof: Proof,
3764
+ /*
3765
+ * Signer information. Ideally should be their account identifier
4217
3766
  */
4218
- async getFeeTokenWithDecimals() {
4219
- const hostParams = await this.publicClient.readContract({
4220
- abi: evmHost_default.ABI,
4221
- address: this.params.host,
4222
- functionName: "hostParams"
4223
- });
4224
- const feeTokenAddress = hostParams.feeToken;
4225
- const feeTokenDecimals = await this.publicClient.readContract({
4226
- address: feeTokenAddress,
4227
- abi: erc20Abi,
4228
- functionName: "decimals"
4229
- });
4230
- return { address: feeTokenAddress, decimals: feeTokenDecimals };
4231
- }
4232
- /**
4233
- * Gets the nonce of the host.
4234
- * This function gets the nonce of the host.
4235
- *
4236
- * @returns The nonce of the host
3767
+ signer: Vector(u8)
3768
+ });
3769
+ var RequestResponse = Enum({
3770
+ /*
3771
+ * A set of requests
4237
3772
  */
4238
- async getHostNonce() {
4239
- const nonce = await this.publicClient.readContract({
4240
- abi: evmHost_default.ABI,
4241
- address: this.params.host,
4242
- functionName: "nonce"
4243
- });
4244
- return nonce;
4245
- }
4246
- };
4247
- var REQUEST_COMMITMENTS_SLOT = 0n;
4248
- var RESPONSE_COMMITMENTS_SLOT = 1n;
4249
- var REQUEST_RECEIPTS_SLOT = 2n;
4250
- var RESPONSE_RECEIPTS_SLOT = 3n;
4251
- var STATE_COMMITMENTS_SLOT = 5n;
4252
- function requestCommitmentKey(key) {
4253
- const keyBytes = hexToBytes(key);
4254
- const slot = REQUEST_COMMITMENTS_SLOT;
4255
- const mappedKey = deriveMapKey(keyBytes, slot);
4256
- const number = bytesToBigInt(hexToBytes(mappedKey)) + 1n;
4257
- return pad(`0x${number.toString(16)}`, { size: 32 });
4258
- }
4259
- function responseCommitmentKey(key) {
4260
- const keyBytes = hexToBytes(key);
4261
- const slot = RESPONSE_COMMITMENTS_SLOT;
4262
- const mappedKey = deriveMapKey(keyBytes, slot);
4263
- const number = bytesToBigInt(hexToBytes(mappedKey)) + 1n;
4264
- return pad(`0x${number.toString(16)}`, { size: 32 });
4265
- }
4266
- function deriveMapKey(key, slot) {
4267
- const slotBytes = pad(`0x${slot.toString(16)}`, { size: 32 });
4268
- const combined = new Uint8Array([...key, ...toBytes(slotBytes)]);
4269
- return keccak256(combined);
4270
- }
4271
- function getStateCommitmentFieldSlot(stateMachineId, height, field) {
4272
- const baseSlot = getStateCommitmentSlot(stateMachineId, height);
4273
- const slotNumber = bytesToBigInt(toBytes(baseSlot)) + BigInt(field);
4274
- return pad(`0x${slotNumber.toString(16)}`, { size: 32 });
4275
- }
4276
- function getStateCommitmentSlot(stateMachineId, height) {
4277
- const firstLevelSlot = deriveFirstLevelSlot(stateMachineId, STATE_COMMITMENTS_SLOT);
4278
- return deriveSecondLevelSlot(height, firstLevelSlot);
4279
- }
4280
- function deriveFirstLevelSlot(key, slot) {
4281
- const keyHex = pad(`0x${key.toString(16)}`, { size: 32 });
4282
- const keyBytes = toBytes(keyHex);
4283
- const slotBytes = toBytes(pad(`0x${slot.toString(16)}`, { size: 32 }));
4284
- const combined = new Uint8Array([...keyBytes, ...slotBytes]);
4285
- return keccak256(combined);
4286
- }
4287
- function deriveSecondLevelSlot(key, firstLevelSlot) {
4288
- const keyHex = pad(`0x${key.toString(16)}`, { size: 32 });
4289
- const keyBytes = toBytes(keyHex);
4290
- const slotBytes = toBytes(firstLevelSlot);
4291
- const combined = new Uint8Array([...keyBytes, ...slotBytes]);
4292
- return keccak256(combined);
4293
- }
4294
- var SubstrateChain = class {
4295
- constructor(params) {
4296
- this.params = params;
4297
- }
3773
+ Request: Vector(Request2),
4298
3774
  /*
4299
- * api: The Polkadot API instance for the Substrate chain.
3775
+ * A set of responses
4300
3776
  */
4301
- api;
3777
+ Response: Vector(Response2)
3778
+ });
3779
+ var ResponseMessage = Struct({
4302
3780
  /*
4303
- * connect: Connects to the Substrate chain using the provided WebSocket URL.
3781
+ * A set of either POST requests or responses to be handled
4304
3782
  */
4305
- async connect() {
4306
- const wsProvider = new WsProvider(this.params.ws);
4307
- const typesBundle = this.params.hasher === "Keccak" ? {
4308
- spec: {
4309
- nexus: {
4310
- hasher: keccakAsU8a
4311
- },
4312
- gargantua: {
4313
- hasher: keccakAsU8a
4314
- }
4315
- }
4316
- } : {};
4317
- this.api = await ApiPromise.create({
4318
- provider: wsProvider,
4319
- typesBundle
4320
- });
4321
- }
4322
- /**
4323
- * Disconnects the Substrate chain connection.
3783
+ datagram: Vector(RequestResponse),
3784
+ /*
3785
+ * Membership batch proof for these requests/responses
3786
+ */
3787
+ proof: Proof,
3788
+ /*
3789
+ * Signer information. Ideally should be their account identifier
3790
+ */
3791
+ signer: Vector(u8)
3792
+ });
3793
+ var TimeoutMessage = Enum({
3794
+ /*
3795
+ * A non memership proof for POST requests
3796
+ */
3797
+ Post: Struct({
3798
+ /*
3799
+ * Timed out requests
3800
+ */
3801
+ requests: Vector(Request2),
3802
+ /*
3803
+ * Membership batch proof for these requests
3804
+ */
3805
+ proof: Proof
3806
+ }),
3807
+ /*
3808
+ * A non memership proof for POST responses
3809
+ */
3810
+ PostResponse: Struct({
3811
+ /*
3812
+ * Timed out responses
3813
+ */
3814
+ responses: Vector(Response2),
3815
+ /*
3816
+ * Membership batch proof for these responses
3817
+ */
3818
+ proof: Proof
3819
+ }),
3820
+ /*
3821
+ * There are no proofs for Get timeouts
3822
+ */
3823
+ Get: Struct({
3824
+ /*
3825
+ * Timed out requests
3826
+ */
3827
+ requests: Vector(Request2)
3828
+ })
3829
+ });
3830
+ var Message = Enum({
3831
+ /*
3832
+ * A consensus update message
3833
+ */
3834
+ ConsensusMessage,
3835
+ /*
3836
+ * A fraud proof message
3837
+ */
3838
+ FraudProofMessage,
3839
+ /*
3840
+ * A request message
3841
+ */
3842
+ RequestMessage,
3843
+ /*
3844
+ * A response message
4324
3845
  */
4325
- async disconnect() {
4326
- if (this.api) {
4327
- await this.api.disconnect();
4328
- this.api = void 0;
4329
- }
4330
- }
4331
- /**
4332
- * Returns the storage key for a request receipt in the child trie
4333
- * The request commitment is the key
4334
- * @param key - The H256 hash key (as a 0x-prefixed hex string)
4335
- * @returns The storage key as a hex string
3846
+ ResponseMessage,
3847
+ /*
3848
+ * A request timeout message
4336
3849
  */
4337
- requestReceiptKey(key) {
4338
- const prefix = new TextEncoder().encode("RequestReceipts");
4339
- const keyBytes = hexToBytes(key);
4340
- return bytesToHex(new Uint8Array([...prefix, ...keyBytes]));
3850
+ TimeoutMessage
3851
+ });
3852
+
3853
+ // src/utils.ts
3854
+ var DEFAULT_POLL_INTERVAL = 5e3;
3855
+ var ADDRESS_ZERO = "0x0000000000000000000000000000000000000000";
3856
+ var MOCK_ADDRESS = "0x1234567890123456789012345678901234567890";
3857
+ var DUMMY_PRIVATE_KEY = "0x0000000000000000000000000000000000000000000000000000000000000000";
3858
+ var DEFAULT_GRAFFITI = "0x0000000000000000000000000000000000000000000000000000000000000000";
3859
+ function sleep(ms) {
3860
+ return new Promise((resolve) => setTimeout(resolve, ms || DEFAULT_POLL_INTERVAL));
3861
+ }
3862
+ async function waitForChallengePeriod(chain, stateMachineHeight) {
3863
+ const challengePeriod = await chain.challengePeriod(stateMachineHeight.id);
3864
+ if (challengePeriod === BigInt(0)) return;
3865
+ const updateTime = await chain.stateMachineUpdateTime(stateMachineHeight);
3866
+ let currentTimestamp = await chain.timestamp();
3867
+ let timeElapsed = currentTimestamp - updateTime;
3868
+ if (timeElapsed > challengePeriod) return;
3869
+ await sleep(Number(challengePeriod) * 1e3);
3870
+ while (timeElapsed <= challengePeriod) {
3871
+ const remainingTime = challengePeriod - timeElapsed;
3872
+ await sleep(Number(remainingTime) * 1e3);
3873
+ currentTimestamp = await chain.timestamp();
3874
+ timeElapsed = currentTimestamp - updateTime;
4341
3875
  }
4342
- /**
4343
- * Returns the storage key for a request commitment in the child trie
4344
- * The request commitment is the key
4345
- * @param key - The H256 hash key (as a 0x-prefixed hex string)
4346
- * @returns The storage key as a hex string
4347
- */
4348
- requestCommitmentKey(key) {
4349
- const prefix = new TextEncoder().encode("RequestCommitments");
4350
- const keyBytes = hexToBytes(key);
4351
- return bytesToHex(new Uint8Array([...prefix, ...keyBytes]));
3876
+ }
3877
+ function isEvmChain(stateMachineId) {
3878
+ return stateMachineId.startsWith("EVM");
3879
+ }
3880
+ function isSubstrateChain(stateMachineId) {
3881
+ return stateMachineId.startsWith("POLKADOT") || stateMachineId.startsWith("KUSAMA") || stateMachineId.startsWith("SUBSTRATE");
3882
+ }
3883
+ function parseStateMachineId(stateMachineId) {
3884
+ const [type, value] = stateMachineId.split("-");
3885
+ if (!type || !value) {
3886
+ throw new Error(
3887
+ `Invalid state machine ID format: ${stateMachineId}. Expected format like "EVM-97" or "SUBSTRATE-cere"`
3888
+ );
4352
3889
  }
4353
- /**
4354
- * Queries a request commitment from the ISMP child trie storage.
4355
- * @param {HexString} commitment - The commitment hash to look up.
4356
- * @returns {Promise<HexString | undefined>} The commitment data if found, undefined otherwise.
4357
- */
4358
- async queryRequestCommitment(commitment) {
4359
- const prefix = toHex(":child_storage:default:ISMP");
4360
- const key = this.requestCommitmentKey(commitment);
4361
- const rpc = new RpcWebSocketClient();
4362
- await rpc.connect(this.params.ws);
4363
- const item = await rpc.call("childstate_getStorage", [prefix, key]);
4364
- return item;
3890
+ const stateId = {};
3891
+ switch (type.toUpperCase()) {
3892
+ case "EVM": {
3893
+ const evmChainId = Number.parseInt(value, 10);
3894
+ if (Number.isNaN(evmChainId)) {
3895
+ throw new Error(`Invalid EVM chain ID: ${value}. Expected a number.`);
3896
+ }
3897
+ stateId.Evm = evmChainId;
3898
+ break;
3899
+ }
3900
+ case "SUBSTRATE": {
3901
+ const bytes = Buffer.from(value, "utf8");
3902
+ stateId.Substrate = `0x${bytes.toString("hex")}`;
3903
+ break;
3904
+ }
3905
+ case "POLKADOT": {
3906
+ const polkadotChainId = Number.parseInt(value, 10);
3907
+ if (Number.isNaN(polkadotChainId)) {
3908
+ throw new Error(`Invalid Polkadot chain ID: ${value}. Expected a number.`);
3909
+ }
3910
+ stateId.Polkadot = polkadotChainId;
3911
+ break;
3912
+ }
3913
+ case "KUSAMA": {
3914
+ const kusamaChainId = Number.parseInt(value, 10);
3915
+ if (Number.isNaN(kusamaChainId)) {
3916
+ throw new Error(`Invalid Kusama chain ID: ${value}. Expected a number.`);
3917
+ }
3918
+ stateId.Kusama = kusamaChainId;
3919
+ break;
3920
+ }
3921
+ default:
3922
+ throw new Error(`Unsupported chain type: ${type}. Expected one of: EVM, SUBSTRATE, POLKADOT, KUSAMA.`);
4365
3923
  }
4366
- /**
4367
- * Queries the request receipt.
4368
- * @param {HexString} commitment - The commitment to query.
4369
- * @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
4370
- */
4371
- async queryRequestReceipt(commitment) {
4372
- const prefix = toHex(":child_storage:default:ISMP");
4373
- const key = this.requestReceiptKey(commitment);
4374
- const rpc = new RpcWebSocketClient();
4375
- await rpc.connect(this.params.ws);
4376
- const item = await rpc.call("childstate_getStorage", [prefix, key]);
4377
- return item;
3924
+ return { stateId };
3925
+ }
3926
+ function postRequestCommitment(post) {
3927
+ const data = encodePacked(
3928
+ ["bytes", "bytes", "uint64", "uint64", "bytes", "bytes", "bytes"],
3929
+ [toHex(post.source), toHex(post.dest), post.nonce, post.timeoutTimestamp, post.from, post.to, post.body]
3930
+ );
3931
+ return {
3932
+ commitment: keccak256(data),
3933
+ encodePacked: data
3934
+ };
3935
+ }
3936
+ function orderCommitment(order) {
3937
+ const encodedOrder = encodeAbiParameters(
3938
+ [
3939
+ {
3940
+ name: "order",
3941
+ type: "tuple",
3942
+ components: [
3943
+ { name: "user", type: "bytes32" },
3944
+ { name: "sourceChain", type: "bytes" },
3945
+ { name: "destChain", type: "bytes" },
3946
+ { name: "deadline", type: "uint256" },
3947
+ { name: "nonce", type: "uint256" },
3948
+ { name: "fees", type: "uint256" },
3949
+ {
3950
+ name: "outputs",
3951
+ type: "tuple[]",
3952
+ components: [
3953
+ { name: "token", type: "bytes32" },
3954
+ { name: "amount", type: "uint256" },
3955
+ { name: "beneficiary", type: "bytes32" }
3956
+ ]
3957
+ },
3958
+ {
3959
+ name: "inputs",
3960
+ type: "tuple[]",
3961
+ components: [
3962
+ { name: "token", type: "bytes32" },
3963
+ { name: "amount", type: "uint256" }
3964
+ ]
3965
+ },
3966
+ { name: "callData", type: "bytes" }
3967
+ ]
3968
+ }
3969
+ ],
3970
+ [
3971
+ {
3972
+ user: order.user,
3973
+ sourceChain: order.sourceChain.startsWith("0x") ? order.sourceChain : toHex(order.sourceChain),
3974
+ destChain: order.destChain.startsWith("0x") ? order.destChain : toHex(order.destChain),
3975
+ deadline: order.deadline,
3976
+ nonce: order.nonce,
3977
+ fees: order.fees,
3978
+ outputs: order.outputs,
3979
+ inputs: order.inputs,
3980
+ callData: order.callData
3981
+ }
3982
+ ]
3983
+ );
3984
+ return keccak256(encodedOrder);
3985
+ }
3986
+ function bytes32ToBytes20(bytes32Address) {
3987
+ if (bytes32Address === ADDRESS_ZERO) {
3988
+ return ADDRESS_ZERO;
4378
3989
  }
4379
- /**
4380
- * Returns the current timestamp of the chain.
4381
- * @returns {Promise<bigint>} The current timestamp.
4382
- */
4383
- async timestamp() {
4384
- if (!this.api) throw new Error("API not initialized");
4385
- const now = await this.api.query.timestamp.now();
4386
- return BigInt(now.toJSON()) / BigInt(1e3);
3990
+ const bytes = hexToBytes(bytes32Address);
3991
+ const addressBytes = bytes.slice(12);
3992
+ return bytesToHex(addressBytes);
3993
+ }
3994
+ function bytes20ToBytes32(bytes20Address) {
3995
+ return `0x${bytes20Address.slice(2).padStart(64, "0")}`;
3996
+ }
3997
+ function hexToString(hex) {
3998
+ const hexWithoutPrefix = hex.startsWith("0x") ? hex.slice(2) : hex;
3999
+ const bytes = new Uint8Array(hexWithoutPrefix.length / 2);
4000
+ for (let i = 0; i < hexWithoutPrefix.length; i += 2) {
4001
+ bytes[i / 2] = Number.parseInt(hexWithoutPrefix.slice(i, i + 2), 16);
4387
4002
  }
4388
- /**
4389
- * Queries the proof of the commitments.
4390
- * @param {IMessage} message - The message to query.
4391
- * @param {string} counterparty - The counterparty address.
4392
- * @param {bigint} [at] - The block number to query at.
4393
- * @returns {Promise<HexString>} The proof.
4394
- */
4395
- async queryProof(message, counterparty, at) {
4396
- const rpc = new RpcWebSocketClient();
4397
- await rpc.connect(this.params.ws);
4398
- if (isEvmChain(counterparty)) {
4399
- const proof = await rpc.call("mmr_queryProof", [Number(at), message]);
4400
- return toHex(proof.proof);
4003
+ return new TextDecoder().decode(bytes);
4004
+ }
4005
+ var DEFAULT_LOGGER = createConsola({
4006
+ level: LogLevels.silent
4007
+ });
4008
+ async function retryPromise(operation, retryConfig) {
4009
+ const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed" } = retryConfig;
4010
+ let lastError;
4011
+ for (let i = 0; i < retryConfig.maxRetries; i++) {
4012
+ try {
4013
+ return await operation();
4014
+ } catch (error) {
4015
+ logger.trace(`Retrying(${i}) > ${logMessage}`);
4016
+ lastError = error;
4017
+ await new Promise((resolve) => setTimeout(resolve, retryConfig.backoffMs * 2 ** i));
4401
4018
  }
4402
- if (isSubstrateChain(counterparty)) {
4403
- const childTrieKeys = "Requests" in message ? message.Requests.map(requestCommitmentStorageKey) : message.Responses.map(responseCommitmentStorageKey);
4404
- const proof = await rpc.call("ismp_queryChildTrieProof", [Number(at), childTrieKeys]);
4405
- const basicProof = BasicProof.dec(toHex(proof.proof));
4406
- const encoded = SubstrateStateProof.enc({
4407
- tag: "OverlayProof",
4408
- value: {
4409
- hasher: {
4410
- tag: this.params.hasher,
4411
- value: void 0
4019
+ }
4020
+ throw lastError;
4021
+ }
4022
+ function getRequestCommitment(get) {
4023
+ const keysEncoding = "0x".concat(get.keys.map((key) => key.slice(2)).join(""));
4024
+ return keccak256(
4025
+ encodePacked(
4026
+ ["bytes", "bytes", "uint64", "uint64", "uint64", "bytes", "bytes", "bytes"],
4027
+ [
4028
+ toHex(get.source),
4029
+ toHex(get.dest),
4030
+ get.nonce,
4031
+ get.height,
4032
+ get.timeoutTimestamp,
4033
+ get.from,
4034
+ keysEncoding,
4035
+ get.context
4036
+ ]
4037
+ )
4038
+ );
4039
+ }
4040
+ var REQUEST_STATUS_WEIGHTS = {
4041
+ [RequestStatus.SOURCE]: 0,
4042
+ [RequestStatus.SOURCE_FINALIZED]: 1,
4043
+ [RequestStatus.HYPERBRIDGE_DELIVERED]: 2,
4044
+ [RequestStatus.HYPERBRIDGE_FINALIZED]: 3,
4045
+ [RequestStatus.DESTINATION]: 4,
4046
+ [RequestStatus.HYPERBRIDGE_TIMED_OUT]: 5,
4047
+ [RequestStatus.TIMED_OUT]: 6
4048
+ };
4049
+ var TIMEOUT_STATUS_WEIGHTS = {
4050
+ [TimeoutStatus.PENDING_TIMEOUT]: 1,
4051
+ [TimeoutStatus.DESTINATION_FINALIZED_TIMEOUT]: 2,
4052
+ [TimeoutStatus.HYPERBRIDGE_TIMED_OUT]: 3,
4053
+ [TimeoutStatus.HYPERBRIDGE_FINALIZED_TIMEOUT]: 4,
4054
+ [TimeoutStatus.TIMED_OUT]: 5
4055
+ };
4056
+ var COMBINED_STATUS_WEIGHTS = {
4057
+ [RequestStatus.SOURCE]: 0,
4058
+ [RequestStatus.SOURCE_FINALIZED]: 1,
4059
+ [RequestStatus.HYPERBRIDGE_DELIVERED]: 2,
4060
+ [RequestStatus.HYPERBRIDGE_FINALIZED]: 3,
4061
+ [RequestStatus.DESTINATION]: 4,
4062
+ [TimeoutStatus.PENDING_TIMEOUT]: 5,
4063
+ [TimeoutStatus.DESTINATION_FINALIZED_TIMEOUT]: 6,
4064
+ [TimeoutStatus.HYPERBRIDGE_TIMED_OUT]: 7,
4065
+ [TimeoutStatus.HYPERBRIDGE_FINALIZED_TIMEOUT]: 8,
4066
+ [TimeoutStatus.TIMED_OUT]: 9
4067
+ };
4068
+ async function estimateGasForPost(params) {
4069
+ const hostParams = await params.sourceClient.readContract({
4070
+ address: params.hostAddress,
4071
+ abi: evmHost_default.ABI,
4072
+ functionName: "hostParams"
4073
+ });
4074
+ const { root, proof, index, kIndex, treeSize } = await generateRootWithProof(params.postRequest, 2n ** 10n);
4075
+ const latestStateMachineHeight = params.hostLatestStateMachineHeight;
4076
+ const overlayRootSlot = getStateCommitmentFieldSlot(
4077
+ BigInt(4009n),
4078
+ // Hyperbridge chain id
4079
+ latestStateMachineHeight,
4080
+ // Hyperbridge chain height
4081
+ 1
4082
+ // For overlayRoot
4083
+ );
4084
+ const postParams = {
4085
+ height: {
4086
+ stateMachineId: BigInt(4009n),
4087
+ height: latestStateMachineHeight
4088
+ },
4089
+ multiproof: proof,
4090
+ leafCount: treeSize
4091
+ };
4092
+ const call_data = [
4093
+ params.hostAddress,
4094
+ {
4095
+ proof: postParams,
4096
+ requests: [
4097
+ {
4098
+ request: {
4099
+ ...params.postRequest,
4100
+ source: toHex(params.postRequest.source),
4101
+ dest: toHex(params.postRequest.dest)
4412
4102
  },
4413
- storageProof: basicProof
4103
+ index,
4104
+ kIndex
4414
4105
  }
4415
- });
4416
- return toHex(encoded);
4106
+ ]
4417
4107
  }
4418
- throw new Error(`Unsupported chain type for counterparty: ${counterparty}`);
4108
+ ];
4109
+ const gas_fee = await params.sourceClient.estimateContractGas({
4110
+ address: hostParams.handler,
4111
+ abi: handler_default.ABI,
4112
+ functionName: "handlePostRequests",
4113
+ args: call_data,
4114
+ stateOverride: [
4115
+ {
4116
+ address: params.hostAddress,
4117
+ stateDiff: [
4118
+ {
4119
+ slot: overlayRootSlot,
4120
+ value: root
4121
+ }
4122
+ ]
4123
+ }
4124
+ ]
4125
+ });
4126
+ return { gas_fee, call_data };
4127
+ }
4128
+ function constructRedeemEscrowRequestBody(order, beneficiary) {
4129
+ const commitment = order.id;
4130
+ const inputs = order.inputs;
4131
+ const requestKind = encodePacked(["uint8"], [0 /* RedeemEscrow */]);
4132
+ const requestBody = {
4133
+ commitment,
4134
+ beneficiary: bytes20ToBytes32(beneficiary),
4135
+ tokens: inputs
4136
+ };
4137
+ const encodedRequestBody = encodeAbiParameters(
4138
+ [
4139
+ {
4140
+ name: "requestBody",
4141
+ type: "tuple",
4142
+ components: [
4143
+ { name: "commitment", type: "bytes32" },
4144
+ { name: "beneficiary", type: "bytes32" },
4145
+ {
4146
+ name: "tokens",
4147
+ type: "tuple[]",
4148
+ components: [
4149
+ { name: "token", type: "bytes32" },
4150
+ { name: "amount", type: "uint256" }
4151
+ ]
4152
+ }
4153
+ ]
4154
+ }
4155
+ ],
4156
+ [requestBody]
4157
+ );
4158
+ return concatHex([requestKind, encodedRequestBody]);
4159
+ }
4160
+ var dateStringtoTimestamp = (date) => {
4161
+ if (!date.endsWith("Z")) {
4162
+ date = `${date}Z`;
4419
4163
  }
4420
- /**
4421
- * Submit an unsigned ISMP transaction to the chain. Resolves when the transaction is finalized.
4422
- * @param message - The message to be submitted.
4423
- * @returns A promise that resolves to an object containing the transaction hash, block hash, and block number.
4424
- */
4425
- async submitUnsigned(message) {
4426
- if (!this.api) throw new Error("API not initialized");
4427
- const { api } = this;
4428
- const args = hexToBytes(this.encode(message)).slice(2);
4429
- const tx = api.tx.ismp.handleUnsigned(args);
4430
- return new Promise((resolve, reject) => {
4431
- let unsub = () => {
4432
- };
4433
- tx.send(async ({ isInBlock, isFinalized, isError, dispatchError, txHash, status }) => {
4434
- if (isFinalized || isInBlock) {
4435
- unsub();
4436
- const blockHash = isInBlock ? status.asInBlock.toHex() : status.asFinalized.toHex();
4437
- const header = await api.rpc.chain.getHeader(blockHash);
4438
- const apiAt = await api.at(blockHash);
4439
- const timestamp = await apiAt.query.timestamp.now();
4440
- resolve({
4441
- transactionHash: txHash.toHex(),
4442
- blockHash,
4443
- blockNumber: header.number.toNumber(),
4444
- timestamp: Number(timestamp.toJSON()) / 1e3
4445
- });
4446
- } else if (isError) {
4447
- unsub();
4448
- console.error("Unsigned transaction failed: ", dispatchError);
4449
- reject(dispatchError);
4450
- }
4451
- }).then((unsubscribe) => {
4452
- unsub = unsubscribe;
4453
- }).catch(reject);
4454
- });
4164
+ return new Date(date).getTime();
4165
+ };
4166
+ function mapTestnetToMainnet(identifier) {
4167
+ identifier = identifier.toLowerCase();
4168
+ switch (identifier) {
4169
+ case "bnb":
4170
+ return "wbnb";
4171
+ case "eth":
4172
+ return "weth";
4173
+ case "tbnb":
4174
+ return "wbnb";
4175
+ case "0xc043f483373072f7f27420d6e7d7ad269c018e18".toLowerCase():
4176
+ return "dai";
4177
+ case "0xae13d989dac2f0debff460ac112a837c89baa7cd".toLowerCase():
4178
+ return "wbnb";
4179
+ case "0x1938165569A5463327fb206bE06d8D9253aa06b7".toLowerCase():
4180
+ return "dai";
4181
+ case "0xC625ec7D30A4b1AAEfb1304610CdAcD0d606aC92".toLowerCase():
4182
+ return "dai";
4183
+ case "0x50B1d3c7c073c9caa1Ef207365A2c9C976bD70b9".toLowerCase():
4184
+ return "dai";
4185
+ case "0xa801da100bf16d07f668f4a49e1f71fc54d05177".toLowerCase():
4186
+ return "dai";
4187
+ default:
4188
+ return identifier;
4455
4189
  }
4456
- /**
4457
- * Query the state proof for a given set of keys at a specific block height.
4458
- * @param at The block height to query the state proof at.
4459
- * @param keys The keys to query the state proof for.
4460
- * @returns The state proof as a hexadecimal string.
4461
- */
4462
- async queryStateProof(at, keys) {
4463
- const rpc = new RpcWebSocketClient();
4464
- await rpc.connect(this.params.ws);
4465
- const encodedKeys = keys.map((key) => Array.from(hexToBytes(key)));
4466
- const proof = await rpc.call("ismp_queryChildTrieProof", [Number(at), encodedKeys]);
4467
- const basicProof = BasicProof.dec(toHex(proof.proof));
4468
- const encoded = SubstrateStateProof.enc({
4469
- tag: "OverlayProof",
4470
- value: {
4471
- hasher: {
4472
- tag: this.params.hasher,
4473
- value: void 0
4474
- },
4475
- storageProof: basicProof
4476
- }
4477
- });
4478
- return toHex(encoded);
4190
+ }
4191
+ async function fetchTokenUsdPrice(identifier) {
4192
+ try {
4193
+ const coinGeckoPrice = await fetchFromCoinGecko(identifier);
4194
+ return coinGeckoPrice;
4195
+ } catch (error) {
4196
+ try {
4197
+ const defillamaPrice = await fetchFromDefillama(identifier);
4198
+ return defillamaPrice;
4199
+ } catch (fallbackError) {
4200
+ console.log(
4201
+ `Both APIs failed for ${identifier}. CoinGecko: ${error}, Defillama: ${fallbackError}. Returning 1`
4202
+ );
4203
+ return 1;
4204
+ }
4479
4205
  }
4480
- /**
4481
- * Get the latest state machine height for a given state machine ID.
4482
- * @param {StateMachineIdParams} stateMachineId - The state machine ID.
4483
- * @returns {Promise<bigint>} The latest state machine height.
4484
- */
4485
- async latestStateMachineHeight(stateMachineId) {
4486
- if (!this.api) throw new Error("API not initialized");
4487
- const latestHeight = await this.api.query.ismp.latestStateMachineHeight(stateMachineId);
4488
- return BigInt(latestHeight.toString());
4206
+ }
4207
+ async function fetchFromCoinGecko(identifier) {
4208
+ const mappedIdentifier = mapTestnetToMainnet(identifier);
4209
+ const url = mappedIdentifier.startsWith("0x") ? `https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=${mappedIdentifier}&vs_currencies=usd` : `https://api.coingecko.com/api/v3/simple/price?ids=${mappedIdentifier}&vs_currencies=usd`;
4210
+ const response = await fetch(url);
4211
+ if (!response.ok) {
4212
+ throw new Error(`CoinGecko API error: ${response.status} ${response.statusText}`);
4489
4213
  }
4490
- /**
4491
- * Get the state machine update time for a given state machine height.
4492
- * @param {StateMachineHeight} stateMachineheight - The state machine height.
4493
- * @returns {Promise<bigint>} The statemachine update time in seconds.
4494
- */
4495
- async stateMachineUpdateTime(stateMachineHeight) {
4496
- if (!this.api) throw new Error("API not initialized");
4497
- const updateTime = await this.api.query.ismp.stateMachineUpdateTime(stateMachineHeight);
4498
- return BigInt(updateTime.toString());
4214
+ const data = await response.json();
4215
+ const key = mappedIdentifier.toLowerCase();
4216
+ if (!data[key]?.usd) {
4217
+ throw new Error(`Price not found for token: ${mappedIdentifier}`);
4499
4218
  }
4500
- /**
4501
- * Get the challenge period for a given state machine id.
4502
- * @param {StateMachineIdParams} stateMachineId - The state machine ID.
4503
- * @returns {Promise<bigint>} The challenge period in seconds.
4504
- */
4505
- async challengePeriod(stateMachineId) {
4506
- if (!this.api) throw new Error("API not initialized");
4507
- const challengePeriod = await this.api.query.ismp.challengePeriod(stateMachineId);
4508
- return BigInt(challengePeriod.toString());
4219
+ return data[key].usd;
4220
+ }
4221
+ async function fetchFromDefillama(identifier) {
4222
+ const mappedIdentifier = mapTestnetToMainnet(identifier);
4223
+ const coinId = mappedIdentifier.startsWith("0x") ? `ethereum:${mappedIdentifier}` : `coingecko:${mappedIdentifier}`;
4224
+ const url = `https://coins.llama.fi/prices/current/${coinId}`;
4225
+ const response = await fetch(url);
4226
+ if (!response.ok) {
4227
+ throw new Error(`Defillama API error: ${response.status} ${response.statusText}`);
4509
4228
  }
4510
- /**
4511
- * Encode an ISMP calldata for a substrate chain.
4512
- * @param message The ISMP message to encode.
4513
- * @returns The encoded message as a hexadecimal string.
4514
- */
4515
- encode(message) {
4516
- const palletIndex = this.getPalletIndex("Ismp");
4517
- const args = encodeISMPMessage(message);
4518
- const call = Vector(u8, 2).enc([palletIndex, 0]);
4519
- return toHex(new Uint8Array([...call, ...args]));
4229
+ const data = await response.json();
4230
+ const price = data.coins?.[coinId]?.price;
4231
+ if (!price && price !== 0) {
4232
+ throw new Error(`Price not found for token: ${mappedIdentifier}`);
4520
4233
  }
4521
- /**
4522
- * Returns the index of a pallet by its name, by looking up the pallets in the runtime metadata.
4523
- * @param {string} name - The name of the pallet.
4524
- * @returns {number} The index of the pallet.
4525
- */
4526
- getPalletIndex(name) {
4527
- if (!this.api) throw new Error("API not initialized");
4528
- const pallets = this.api.runtimeMetadata.asLatest.pallets.entries();
4529
- for (const p of pallets) {
4530
- if (p[1].name.toString() === name) {
4531
- const index = p[1].index.toNumber();
4532
- return index;
4234
+ return price;
4235
+ }
4236
+ var ERC20Method = /* @__PURE__ */ ((ERC20Method2) => {
4237
+ ERC20Method2["BALANCE_OF"] = "0x70a08231";
4238
+ ERC20Method2["ALLOWANCE"] = "0xdd62ed3e";
4239
+ return ERC20Method2;
4240
+ })(ERC20Method || {});
4241
+ async function getStorageSlot(client, contractAddress, data) {
4242
+ const traceCallClient = client.extend((client2) => ({
4243
+ async traceCall(args) {
4244
+ return client2.request({
4245
+ // @ts-ignore
4246
+ method: "debug_traceCall",
4247
+ // @ts-ignore
4248
+ params: [args, "latest", {}]
4249
+ });
4250
+ }
4251
+ }));
4252
+ const response = await traceCallClient.traceCall({
4253
+ to: contractAddress,
4254
+ data
4255
+ });
4256
+ const methodSignature = data.slice(0, 10);
4257
+ const logs = response.structLogs;
4258
+ for (let i = logs.length - 1; i >= 0; i--) {
4259
+ const log = logs[i];
4260
+ if (log.op === "SLOAD" && log.stack?.length >= 3) {
4261
+ const sigHash = log.stack[0];
4262
+ const slotHex = log.stack[log.stack.length - 1];
4263
+ if (sigHash === methodSignature && slotHex.length === 66) {
4264
+ return slotHex;
4533
4265
  }
4534
4266
  }
4535
- throw new Error(`${name} not found in runtime`);
4536
4267
  }
4537
- };
4538
- function requestCommitmentStorageKey(key) {
4539
- const prefix = new TextEncoder().encode("RequestCommitments");
4540
- const keyBytes = hexToBytes(key);
4541
- return Array.from(new Uint8Array([...prefix, ...keyBytes]));
4542
- }
4543
- function responseCommitmentStorageKey(key) {
4544
- const prefix = new TextEncoder().encode("ResponseCommitments");
4545
- const keyBytes = hexToBytes(key);
4546
- return Array.from(new Uint8Array([...prefix, ...keyBytes]));
4268
+ throw new Error(`Storage slot not found for data: ${methodSignature}`);
4547
4269
  }
4548
- function convertStateMachineIdToEnum(id) {
4549
- let [tag, value] = id.split("-");
4550
- tag = capitalize(tag);
4551
- if (["Evm", "Polkadot", "Kusama"].includes(tag)) {
4552
- value = Number.parseInt(value);
4270
+ function adjustFeeDecimals(feeInFeeToken, fromDecimals, toDecimals) {
4271
+ if (fromDecimals === toDecimals) return feeInFeeToken;
4272
+ if (fromDecimals < toDecimals) {
4273
+ const scaleFactor = BigInt(10 ** (toDecimals - fromDecimals));
4274
+ return feeInFeeToken * scaleFactor;
4553
4275
  } else {
4554
- value = Array.from(toBytes(value));
4276
+ const scaleFactor = BigInt(10 ** (fromDecimals - toDecimals));
4277
+ return (feeInFeeToken + scaleFactor - 1n) / scaleFactor;
4555
4278
  }
4556
- return { tag, value };
4557
- }
4558
- function convertIPostRequestToCodec(request) {
4559
- return {
4560
- tag: "Post",
4561
- value: {
4562
- source: convertStateMachineIdToEnum(request.source),
4563
- dest: convertStateMachineIdToEnum(request.dest),
4564
- from: Array.from(hexToBytes(request.from)),
4565
- to: Array.from(hexToBytes(request.to)),
4566
- nonce: request.nonce,
4567
- body: Array.from(hexToBytes(request.body)),
4568
- timeoutTimestamp: request.timeoutTimestamp
4569
- }
4570
- };
4571
4279
  }
4572
- function encodeISMPMessage(message) {
4573
- try {
4574
- return match(message).with({ kind: "PostRequest" }, (message2) => {
4575
- return Vector(Message).enc([
4576
- {
4577
- tag: "RequestMessage",
4578
- value: {
4579
- requests: message2.requests.map(
4580
- (post_request) => convertIPostRequestToCodec(post_request).value
4581
- ),
4582
- proof: {
4583
- height: {
4584
- height: message2.proof.height,
4585
- id: {
4586
- consensusStateId: Array.from(toBytes(message2.proof.consensusStateId)),
4587
- id: convertStateMachineIdToEnum(message2.proof.stateMachine)
4588
- }
4589
- },
4590
- proof: Array.from(hexToBytes(message2.proof.proof))
4591
- },
4592
- signer: Array.from(hexToBytes(message2.signer))
4593
- }
4594
- }
4595
- ]);
4596
- }).with({ kind: "GetResponse" }, (message2) => {
4597
- throw new Error("GetResponse is not yet supported on Substrate chains");
4598
- }).with({ kind: "TimeoutPostRequest" }, (message2) => {
4599
- return Vector(Message).enc([
4600
- {
4601
- tag: "TimeoutMessage",
4602
- value: {
4603
- tag: "Post",
4604
- value: {
4605
- requests: message2.requests.map((r) => convertIPostRequestToCodec(r)),
4606
- proof: {
4607
- height: {
4608
- height: message2.proof.height,
4609
- id: {
4610
- consensusStateId: Array.from(toBytes(message2.proof.consensusStateId)),
4611
- id: convertStateMachineIdToEnum(message2.proof.stateMachine)
4612
- }
4613
- },
4614
- proof: Array.from(hexToBytes(message2.proof.proof))
4615
- }
4616
- }
4617
- }
4618
- }
4619
- ]);
4620
- }).exhaustive();
4621
- } catch (error) {
4622
- throw new Error("Failed to encode ISMP message", { cause: error });
4280
+
4281
+ // src/utils/exceptions.ts
4282
+ var AbortSignalInternal = class _AbortSignalInternal extends Error {
4283
+ constructor(message) {
4284
+ super();
4285
+ this.name = "Hyperbridge/SDK/AbortSignalInternal";
4286
+ this.message = message;
4287
+ }
4288
+ static isError(error) {
4289
+ return error instanceof _AbortSignalInternal;
4290
+ }
4291
+ };
4292
+ var ExpectedError = class _ExpectedError extends Error {
4293
+ constructor(message) {
4294
+ super();
4295
+ this.name = "Hyperbridge/SDK/ExpectedError";
4296
+ this.message = message;
4297
+ }
4298
+ static isError(error) {
4299
+ return error instanceof _ExpectedError;
4300
+ }
4301
+ };
4302
+ var Chains = /* @__PURE__ */ ((Chains2) => {
4303
+ Chains2["BSC_CHAPEL"] = "EVM-97";
4304
+ Chains2["GNOSIS_CHIADO"] = "EVM-10200";
4305
+ Chains2["HYPERBRIDGE_GARGANTUA"] = "KUSAMA-4009";
4306
+ Chains2["SEPOLIA"] = "EVM-11155111";
4307
+ Chains2["MAINNET"] = "EVM-1";
4308
+ Chains2["BSC_MAINNET"] = "EVM-56";
4309
+ Chains2["ARBITRUM_MAINNET"] = "EVM-42161";
4310
+ Chains2["BASE_MAINNET"] = "EVM-8453";
4311
+ return Chains2;
4312
+ })(Chains || {});
4313
+ var chainIds = {
4314
+ ["EVM-97" /* BSC_CHAPEL */]: 97,
4315
+ ["EVM-10200" /* GNOSIS_CHIADO */]: 10200,
4316
+ ["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: 4009,
4317
+ ["EVM-11155111" /* SEPOLIA */]: 11155111,
4318
+ ["EVM-1" /* MAINNET */]: 1,
4319
+ ["EVM-56" /* BSC_MAINNET */]: 56,
4320
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: 42161,
4321
+ ["EVM-8453" /* BASE_MAINNET */]: 8453
4322
+ };
4323
+ var viemChains = {
4324
+ "97": bscTestnet,
4325
+ "10200": gnosisChiado,
4326
+ "11155111": sepolia,
4327
+ "1": mainnet,
4328
+ "56": bsc,
4329
+ "42161": arbitrum,
4330
+ "8453": base
4331
+ };
4332
+ var WrappedNativeDecimals = {
4333
+ ["EVM-97" /* BSC_CHAPEL */]: 18,
4334
+ ["EVM-10200" /* GNOSIS_CHIADO */]: 18,
4335
+ ["EVM-11155111" /* SEPOLIA */]: 18,
4336
+ ["EVM-1" /* MAINNET */]: 18,
4337
+ ["EVM-56" /* BSC_MAINNET */]: 18,
4338
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: 18,
4339
+ ["EVM-8453" /* BASE_MAINNET */]: 18
4340
+ };
4341
+ var assets = {
4342
+ ["EVM-97" /* BSC_CHAPEL */]: {
4343
+ WETH: "0xae13d989dac2f0debff460ac112a837c89baa7cd".toLowerCase(),
4344
+ DAI: "0x1938165569A5463327fb206bE06d8D9253aa06b7".toLowerCase(),
4345
+ USDC: "0xC625ec7D30A4b1AAEfb1304610CdAcD0d606aC92".toLowerCase(),
4346
+ USDT: "0xc043f483373072f7f27420d6e7d7ad269c018e18".toLowerCase()
4347
+ },
4348
+ ["EVM-10200" /* GNOSIS_CHIADO */]: {
4349
+ WETH: "0x0000000000000000000000000000000000000000".toLowerCase(),
4350
+ DAI: "0x50B1d3c7c073c9caa1Ef207365A2c9C976bD70b9".toLowerCase(),
4351
+ USDC: "0x0000000000000000000000000000000000000000".toLowerCase(),
4352
+ USDT: "0x0000000000000000000000000000000000000000".toLowerCase()
4353
+ },
4354
+ ["EVM-11155111" /* SEPOLIA */]: {
4355
+ WETH: "0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9".toLowerCase(),
4356
+ USDC: "0x0000000000000000000000000000000000000000".toLowerCase(),
4357
+ USDT: "0x0000000000000000000000000000000000000000".toLowerCase(),
4358
+ DAI: "0x0000000000000000000000000000000000000000".toLowerCase()
4359
+ },
4360
+ ["EVM-1" /* MAINNET */]: {
4361
+ WETH: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".toLowerCase(),
4362
+ DAI: "0x6B175474E89094C44Da98b954EedeAC495271d0F".toLowerCase(),
4363
+ USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".toLowerCase(),
4364
+ USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7".toLowerCase()
4365
+ },
4366
+ ["EVM-56" /* BSC_MAINNET */]: {
4367
+ WETH: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c".toLowerCase(),
4368
+ DAI: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3".toLowerCase(),
4369
+ USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d".toLowerCase(),
4370
+ USDT: "0x55d398326f99059fF775485246999027B3197955".toLowerCase()
4371
+ },
4372
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: {
4373
+ WETH: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1".toLowerCase(),
4374
+ DAI: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1".toLowerCase(),
4375
+ USDC: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831".toLowerCase(),
4376
+ USDT: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9".toLowerCase()
4377
+ },
4378
+ ["EVM-8453" /* BASE_MAINNET */]: {
4379
+ WETH: "0x4200000000000000000000000000000000000006".toLowerCase(),
4380
+ DAI: "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb".toLowerCase(),
4381
+ USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913".toLowerCase(),
4382
+ USDT: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2".toLowerCase()
4383
+ }
4384
+ };
4385
+ var addresses = {
4386
+ IntentGateway: {
4387
+ ["EVM-97" /* BSC_CHAPEL */]: "0x016b6ffC9f890d1e28f9Fdb9eaDA776b02F89509",
4388
+ ["EVM-10200" /* GNOSIS_CHIADO */]: "0x016b6ffC9f890d1e28f9Fdb9eaDA776b02F89509",
4389
+ ["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
4390
+ ["EVM-1" /* MAINNET */]: "0xd54165e45926720b062C192a5bacEC64d5bB08DA",
4391
+ ["EVM-56" /* BSC_MAINNET */]: "0xd54165e45926720b062C192a5bacEC64d5bB08DA",
4392
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0xd54165e45926720b062C192a5bacEC64d5bB08DA",
4393
+ ["EVM-8453" /* BASE_MAINNET */]: "0xd54165e45926720b062C192a5bacEC64d5bB08DA"
4394
+ },
4395
+ Host: {
4396
+ ["EVM-97" /* BSC_CHAPEL */]: "0x8Aa0Dea6D675d785A882967Bf38183f6117C09b7",
4397
+ ["EVM-10200" /* GNOSIS_CHIADO */]: "0x58a41b89f4871725e5d898d98ef4bf917601c5eb",
4398
+ ["EVM-11155111" /* SEPOLIA */]: "0x2EdB74C269948b60ec1000040E104cef0eABaae8",
4399
+ ["EVM-1" /* MAINNET */]: "0x792A6236AF69787C40cF76b69B4c8c7B28c4cA20",
4400
+ ["EVM-56" /* BSC_MAINNET */]: "0x24B5d421Ec373FcA57325dd2F0C074009Af021F7",
4401
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0xE05AFD4Eb2ce6d65c40e1048381BD0Ef8b4B299e",
4402
+ ["EVM-8453" /* BASE_MAINNET */]: "0x6FFe92e4d7a9D589549644544780e6725E84b248"
4403
+ },
4404
+ UniswapRouter02: {
4405
+ ["EVM-97" /* BSC_CHAPEL */]: "0x9639379819420704457B07A0C33B678D9E0F8Df0",
4406
+ ["EVM-10200" /* GNOSIS_CHIADO */]: "0x0000000000000000000000000000000000000000",
4407
+ ["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
4408
+ ["EVM-1" /* MAINNET */]: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
4409
+ ["EVM-56" /* BSC_MAINNET */]: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
4410
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0x0000000000000000000000000000000000000000",
4411
+ ["EVM-8453" /* BASE_MAINNET */]: "0x0000000000000000000000000000000000000000"
4412
+ },
4413
+ UniswapV2Factory: {
4414
+ ["EVM-97" /* BSC_CHAPEL */]: "0x12e036669DA18F4A2777853d6e2136b32AceEC86",
4415
+ ["EVM-10200" /* GNOSIS_CHIADO */]: "0x0000000000000000000000000000000000000000",
4416
+ ["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
4417
+ ["EVM-1" /* MAINNET */]: "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f",
4418
+ ["EVM-56" /* BSC_MAINNET */]: "0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6",
4419
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0x0000000000000000000000000000000000000000",
4420
+ ["EVM-8453" /* BASE_MAINNET */]: "0x0000000000000000000000000000000000000000"
4421
+ },
4422
+ BatchExecutor: {
4423
+ ["EVM-97" /* BSC_CHAPEL */]: "0x4CC58B5D8FBf838d062E4b21F75C327835B5F0ef",
4424
+ ["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
4425
+ ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000",
4426
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0x0000000000000000000000000000000000000000",
4427
+ ["EVM-8453" /* BASE_MAINNET */]: "0x0000000000000000000000000000000000000000"
4428
+ },
4429
+ UniversalRouter: {
4430
+ ["EVM-97" /* BSC_CHAPEL */]: "0xcc6d5ece3d4a57245bf5a2f64f3ed9179b81f714",
4431
+ ["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
4432
+ ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000",
4433
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0x0000000000000000000000000000000000000000",
4434
+ ["EVM-8453" /* BASE_MAINNET */]: "0x0000000000000000000000000000000000000000"
4435
+ },
4436
+ UniswapV3Router: {
4437
+ ["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
4438
+ ["EVM-1" /* MAINNET */]: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
4439
+ ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000",
4440
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0x0000000000000000000000000000000000000000",
4441
+ ["EVM-8453" /* BASE_MAINNET */]: "0x0000000000000000000000000000000000000000"
4442
+ },
4443
+ UniswapV3Factory: {
4444
+ ["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
4445
+ ["EVM-1" /* MAINNET */]: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
4446
+ ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000",
4447
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0x0000000000000000000000000000000000000000",
4448
+ ["EVM-8453" /* BASE_MAINNET */]: "0x0000000000000000000000000000000000000000"
4449
+ },
4450
+ UniswapV3Quoter: {
4451
+ ["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
4452
+ ["EVM-1" /* MAINNET */]: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
4453
+ ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000",
4454
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0x0000000000000000000000000000000000000000",
4455
+ ["EVM-8453" /* BASE_MAINNET */]: "0x0000000000000000000000000000000000000000"
4456
+ },
4457
+ UniswapV4PoolManager: {
4458
+ ["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
4459
+ ["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
4460
+ ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000",
4461
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0x0000000000000000000000000000000000000000",
4462
+ ["EVM-8453" /* BASE_MAINNET */]: "0x0000000000000000000000000000000000000000"
4463
+ },
4464
+ UniswapV4Quoter: {
4465
+ ["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
4466
+ ["EVM-1" /* MAINNET */]: "0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203",
4467
+ ["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000",
4468
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "0x0000000000000000000000000000000000000000",
4469
+ ["EVM-8453" /* BASE_MAINNET */]: "0x0000000000000000000000000000000000000000"
4470
+ },
4471
+ Calldispatcher: {
4472
+ ["EVM-11155111" /* SEPOLIA */]: "0xC7f13b6D03A0A7F3239d38897503E90553ABe155"
4623
4473
  }
4624
- }
4474
+ };
4475
+ var createRpcUrls = (env2) => ({
4476
+ ["EVM-97" /* BSC_CHAPEL */]: env2.BSC_CHAPEL || "https://bnb-testnet.api.onfinality.io/public",
4477
+ ["EVM-10200" /* GNOSIS_CHIADO */]: env2.GNOSIS_CHIADO || "https://gnosis-chiado-rpc.publicnode.com",
4478
+ ["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: env2.HYPERBRIDGE_GARGANTUA || "",
4479
+ ["EVM-11155111" /* SEPOLIA */]: env2.SEPOLIA || "https://1rpc.io/sepolia",
4480
+ ["EVM-1" /* MAINNET */]: env2.ETH_MAINNET || "https://eth-mainnet.g.alchemy.com/v2/demo",
4481
+ ["EVM-56" /* BSC_MAINNET */]: env2.BSC_MAINNET || "https://binance.llamarpc.com",
4482
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: env2.ARBITRUM_MAINNET || "https://arbitrum-one.public.blastapi.io",
4483
+ ["EVM-8453" /* BASE_MAINNET */]: env2.BASE_MAINNET || "https://base-mainnet.public.blastapi.io"
4484
+ });
4485
+ var consensusStateIds = {
4486
+ ["EVM-97" /* BSC_CHAPEL */]: "BSC0",
4487
+ ["EVM-10200" /* GNOSIS_CHIADO */]: "GNO0",
4488
+ ["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: "PAS0",
4489
+ ["EVM-11155111" /* SEPOLIA */]: "ETH0",
4490
+ ["EVM-1" /* MAINNET */]: "ETH0",
4491
+ ["EVM-56" /* BSC_MAINNET */]: "BSC0",
4492
+ ["EVM-42161" /* ARBITRUM_MAINNET */]: "ETH0",
4493
+ ["EVM-8453" /* BASE_MAINNET */]: "ETH0"
4494
+ };
4625
4495
 
4626
- // src/chain.ts
4627
- async function getChain(chainConfig) {
4628
- if (isEvmChain(chainConfig.stateMachineId)) {
4629
- const config = chainConfig;
4630
- const chainId = Number.parseInt(chainConfig.stateMachineId.split("-")[1]);
4631
- const evmChain = new EvmChain({
4632
- chainId,
4633
- url: config.rpcUrl,
4634
- host: config.host
4635
- });
4636
- return evmChain;
4496
+ // src/configs/ChainConfigService.ts
4497
+ var ChainConfigService = class {
4498
+ rpcUrls;
4499
+ constructor(env2 = process.env) {
4500
+ this.rpcUrls = createRpcUrls(env2);
4637
4501
  }
4638
- if (isSubstrateChain(chainConfig.stateMachineId)) {
4639
- const config = chainConfig;
4640
- const substrateChain = new SubstrateChain({
4641
- ws: config.wsUrl,
4642
- hasher: config.hasher
4643
- });
4644
- await substrateChain.connect();
4645
- return substrateChain;
4502
+ getChainConfig(chain) {
4503
+ return {
4504
+ chainId: chainIds[chain],
4505
+ rpcUrl: this.rpcUrls[chain],
4506
+ intentGatewayAddress: addresses.IntentGateway[chain]
4507
+ };
4646
4508
  }
4647
- throw new Error(`Unsupported chain: ${chainConfig.stateMachineId}`);
4648
- }
4649
- function getPeakPosByHeight(height) {
4650
- return (1n << BigInt(height + 1)) - 2n;
4651
- }
4652
- function leftPeakHeightPos(mmrSize) {
4653
- let height = 1;
4654
- let prevPos = 0n;
4655
- let pos = getPeakPosByHeight(height);
4656
- while (pos < mmrSize) {
4657
- height += 1;
4658
- prevPos = pos;
4659
- pos = getPeakPosByHeight(height);
4509
+ getIntentGatewayAddress(chain) {
4510
+ return addresses.IntentGateway[chain];
4660
4511
  }
4661
- return [height - 1, prevPos];
4662
- }
4663
- function getRightPeak(initialHeight, initialPos, mmrSize) {
4664
- let height = initialHeight;
4665
- let pos = initialPos;
4666
- pos += siblingOffset(height);
4667
- while (pos > mmrSize - 1n) {
4668
- if (height === 0) {
4669
- return null;
4670
- }
4671
- pos -= parentOffset(height - 1);
4672
- height -= 1;
4512
+ getHostAddress(chain) {
4513
+ return addresses.Host[chain];
4673
4514
  }
4674
- return [height, pos];
4675
- }
4676
- function getPeaks(mmrSize) {
4677
- const positions = [];
4678
- let [height, pos] = leftPeakHeightPos(mmrSize);
4679
- positions.push(pos);
4680
- while (height > 0) {
4681
- const peak = getRightPeak(height, pos, mmrSize);
4682
- if (!peak) break;
4683
- [height, pos] = peak;
4684
- positions.push(pos);
4515
+ getWrappedNativeAssetWithDecimals(chain) {
4516
+ return {
4517
+ asset: assets[chain].WETH,
4518
+ decimals: WrappedNativeDecimals[chain]
4519
+ };
4685
4520
  }
4686
- return positions;
4687
- }
4688
- function allOnes(num) {
4689
- if (num === 0n) return false;
4690
- return num.toString(2).split("").every((bit) => bit === "1");
4691
- }
4692
- function jumpLeft(pos) {
4693
- const bitLength = pos.toString(2).length;
4694
- const mostSignificantBits = 1n << BigInt(bitLength - 1);
4695
- return pos - (mostSignificantBits - 1n);
4696
- }
4697
- function posHeightInTree(initialPos) {
4698
- let pos = initialPos + 1n;
4699
- while (!allOnes(pos)) {
4700
- pos = jumpLeft(pos);
4521
+ getDaiAsset(chain) {
4522
+ return assets[chain].DAI;
4701
4523
  }
4702
- return pos.toString(2).length - 1;
4703
- }
4704
- function parentOffset(height) {
4705
- return 2n << BigInt(height);
4706
- }
4707
- function siblingOffset(height) {
4708
- return (2n << BigInt(height)) - 1n;
4709
- }
4710
- function takeWhileVec(v, p) {
4711
- const index = v.findIndex((item) => !p(item));
4712
- if (index === -1) {
4713
- const result = [...v];
4714
- v.length = 0;
4715
- return result;
4524
+ getUsdtAsset(chain) {
4525
+ return assets[chain].USDT;
4716
4526
  }
4717
- return v.splice(0, index);
4718
- }
4719
- function mmrPositionToKIndex(initialLeaves, mmrSize) {
4720
- const leaves = [...initialLeaves];
4721
- const peaks = getPeaks(mmrSize);
4722
- const leavesWithKIndices = [];
4723
- for (const peak of peaks) {
4724
- const peakLeaves = takeWhileVec(leaves, (pos) => pos <= peak);
4725
- if (peakLeaves.length > 0) {
4726
- for (const pos of peakLeaves) {
4727
- const height = posHeightInTree(peak);
4728
- let index = 0n;
4729
- let parentPos = peak;
4730
- for (let h = height; h >= 1; h--) {
4731
- const leftChild = parentPos - parentOffset(h - 1);
4732
- const rightChild = leftChild + siblingOffset(h - 1);
4733
- index *= 2n;
4734
- if (leftChild >= pos) {
4735
- parentPos = leftChild;
4736
- } else {
4737
- parentPos = rightChild;
4738
- index += 1n;
4739
- }
4740
- }
4741
- leavesWithKIndices.push([pos, index]);
4742
- }
4743
- }
4527
+ getUsdcAsset(chain) {
4528
+ return assets[chain].USDC;
4744
4529
  }
4745
- return leavesWithKIndices;
4746
- }
4747
- function calculateMMRSize(numberOfLeaves) {
4748
- const numberOfPeaks = numberOfLeaves.toString(2).split("1").length - 1;
4749
- return 2n * numberOfLeaves - BigInt(numberOfPeaks);
4750
- }
4751
- async function generateRootWithProof(postRequest, treeSize) {
4752
- const { generate_root_with_proof: generate_root_with_proof2 } = await load_ckb_mmr();
4753
- const { commitment: hash, encodePacked: encodePacked3 } = postRequestCommitment(postRequest);
4754
- const result = JSON.parse(generate_root_with_proof2(hexToBytes(encodePacked3), treeSize));
4755
- const { root, proof, mmr_size, leaf_positions, keccak_hash_calldata } = result;
4756
- if (keccak_hash_calldata !== hash) {
4757
- console.log("keccak_hash", keccak_hash_calldata);
4758
- console.log("hash", hash);
4759
- throw new Error("Abi keccak hash mismatch");
4530
+ getChainId(chain) {
4531
+ return chainIds[chain];
4532
+ }
4533
+ getConsensusStateId(chain) {
4534
+ return toHex(consensusStateIds[chain]);
4535
+ }
4536
+ getHyperbridgeChainId() {
4537
+ return chainIds["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */];
4538
+ }
4539
+ getRpcUrl(chain) {
4540
+ return this.rpcUrls[chain];
4541
+ }
4542
+ getUniswapRouterV2Address(chain) {
4543
+ return addresses.UniswapRouter02[chain];
4544
+ }
4545
+ getUniswapV2FactoryAddress(chain) {
4546
+ return addresses.UniswapV2Factory[chain];
4547
+ }
4548
+ getBatchExecutorAddress(chain) {
4549
+ return addresses.BatchExecutor[chain];
4550
+ }
4551
+ getUniversalRouterAddress(chain) {
4552
+ return addresses.UniversalRouter[chain];
4553
+ }
4554
+ getUniswapV3RouterAddress(chain) {
4555
+ return addresses.UniswapV3Router[chain];
4556
+ }
4557
+ getUniswapV3FactoryAddress(chain) {
4558
+ return addresses.UniswapV3Factory[chain];
4559
+ }
4560
+ getUniswapV3QuoterAddress(chain) {
4561
+ return addresses.UniswapV3Quoter[chain];
4562
+ }
4563
+ getUniswapV4PoolManagerAddress(chain) {
4564
+ return addresses.UniswapV4PoolManager[chain];
4565
+ }
4566
+ getUniswapV4QuoterAddress(chain) {
4567
+ return addresses.UniswapV4Quoter[chain];
4568
+ }
4569
+ };
4570
+
4571
+ // src/chains/evm.ts
4572
+ var chains = {
4573
+ [mainnet.id]: mainnet,
4574
+ [arbitrum.id]: arbitrum,
4575
+ [arbitrumSepolia.id]: arbitrumSepolia,
4576
+ [optimism.id]: optimism,
4577
+ [optimismSepolia.id]: optimismSepolia,
4578
+ [base.id]: base,
4579
+ [baseSepolia.id]: baseSepolia,
4580
+ [soneium.id]: soneium,
4581
+ [bsc.id]: bsc,
4582
+ [bscTestnet.id]: bscTestnet,
4583
+ [gnosis.id]: gnosis,
4584
+ [gnosisChiado.id]: gnosisChiado
4585
+ };
4586
+ var DEFAULT_ADDRESS = "0x0000000000000000000000000000000000000000";
4587
+ var EvmChain = class {
4588
+ constructor(params) {
4589
+ this.params = params;
4590
+ this.publicClient = createPublicClient({
4591
+ // @ts-ignore
4592
+ chain: chains[params.chainId],
4593
+ transport: http(params.url)
4594
+ });
4595
+ this.chainConfigService = new ChainConfigService();
4760
4596
  }
4761
- const [[, kIndex]] = mmrPositionToKIndex(leaf_positions, BigInt(mmr_size));
4762
- return {
4763
- root,
4764
- proof,
4765
- index: treeSize - 1n,
4766
- kIndex,
4767
- treeSize,
4768
- mmrSize: mmr_size
4769
- };
4770
- }
4771
- async function load_ckb_mmr() {
4772
- if (hasWindow) {
4773
- const wasm2 = await Promise.resolve().then(() => (init_web(), web_exports));
4774
- await wasm2.default();
4775
- return wasm2;
4597
+ publicClient;
4598
+ chainConfigService;
4599
+ // Expose minimal getters for external helpers/classes
4600
+ get client() {
4601
+ return this.publicClient;
4776
4602
  }
4777
- if (isNode) {
4778
- const wasm2 = await Promise.resolve().then(() => (init_web(), web_exports));
4779
- return wasm2;
4603
+ get host() {
4604
+ return this.params.host;
4605
+ }
4606
+ get config() {
4607
+ return this.chainConfigService;
4780
4608
  }
4781
- throw new Error(`SDK not setup for ${env}`);
4782
- }
4783
- async function __test() {
4784
- const { generate_root_with_proof: generate_root_with_proof2 } = await load_ckb_mmr();
4785
- return generate_root_with_proof2(new Uint8Array(), 120n);
4786
- }
4787
- var H256 = Vector(u8, 32);
4788
- var EvmStateProof = Struct({
4789
- /**
4790
- * Proof of the contract state.
4791
- */
4792
- contractProof: Vector(Vector(u8)),
4793
- /**
4794
- * Proof of the storage state.
4795
- */
4796
- storageProof: Vector(Tuple(Vector(u8), Vector(Vector(u8))))
4797
- });
4798
- var SubstrateHashing = Enum({
4799
- /* For chains that use keccak as their hashing algo */
4800
- Keccak: _void,
4801
- /* For chains that use blake2b as their hashing algo */
4802
- Blake2: _void
4803
- });
4804
- var SubstrateStateMachineProof = Struct({
4805
4609
  /**
4806
- * The hasher used to hash the state machine state.
4610
+ * Derives the key for the request receipt.
4611
+ * @param {HexString} commitment - The commitment to derive the key from.
4612
+ * @returns {HexString} The derived key.
4807
4613
  */
4808
- hasher: SubstrateHashing,
4614
+ requestReceiptKey(commitment) {
4615
+ return deriveMapKey(hexToBytes(commitment), REQUEST_RECEIPTS_SLOT);
4616
+ }
4809
4617
  /**
4810
- * Proof of the state machine state.
4811
- */
4812
- storageProof: Vector(Vector(u8))
4813
- });
4814
- var SubstrateStateProof = Enum({
4815
- /*
4816
- * Uses overlay root for verification
4817
- */
4818
- OverlayProof: SubstrateStateMachineProof,
4819
- /*
4820
- * Uses state root for verification
4821
- */
4822
- StateProof: SubstrateStateMachineProof
4823
- });
4824
- var BasicProof = Vector(Vector(u8));
4825
- var LeafIndexAndPos = Struct({
4826
- /*
4827
- * Leaf index
4828
- */
4829
- leafIndex: u64,
4830
- /*
4831
- * Leaf position in the MMR
4832
- */
4833
- pos: u64
4834
- });
4835
- var MmrProof = Struct({
4836
- /*
4837
- * Proof of the leaf index and position.
4838
- */
4839
- leafIndexAndPos: Vector(LeafIndexAndPos),
4840
- /*
4841
- * Proof of the leaf data.
4842
- */
4843
- leafCount: u64,
4844
- /*
4845
- * Proof elements (hashes of siblings of inner nodes on the path to the leaf).
4846
- */
4847
- items: Vector(H256)
4848
- });
4849
- var ConsensusStateId = Vector(u8, 4);
4850
- var ConsensusMessage = Struct({
4851
- /*
4852
- * Consensus message data.
4853
- */
4854
- consensusProof: Vector(u8),
4855
- /*
4856
- * Consensus state Id
4857
- */
4858
- consensusStateId: ConsensusStateId,
4859
- /*
4860
- * Public key of the sender
4861
- */
4862
- signer: Vector(u8)
4863
- });
4864
- var FraudProofMessage = Struct({
4865
- /*
4866
- * The first valid consensus proof
4867
- */
4868
- proof1: Vector(u8),
4869
- /*
4870
- * The second valid consensus proof
4871
- */
4872
- proof2: Vector(u8),
4873
- /*
4874
- * Consensus state Id
4875
- */
4876
- consensusStateId: ConsensusStateId
4877
- });
4878
- var StateMachine = Enum({
4879
- /*
4880
- * Evm state machines
4881
- */
4882
- Evm: u32,
4883
- /*
4884
- * Polkadot parachains
4885
- */
4886
- Polkadot: u32,
4887
- /*
4888
- * Kusama parachains
4889
- */
4890
- Kusama: u32,
4891
- /*
4892
- * Substrate-based standalone chain
4893
- */
4894
- Substrate: ConsensusStateId,
4895
- /*
4896
- * Tendermint chains
4897
- */
4898
- Tendermint: ConsensusStateId
4899
- });
4900
- var StateMachineId = Struct({
4901
- /*
4902
- * The state machine id
4903
- */
4904
- id: StateMachine,
4905
- /*
4906
- * The consensus state id
4907
- */
4908
- consensusStateId: ConsensusStateId
4909
- });
4910
- var StateMachineHeight = Struct({
4911
- /*
4912
- * The state machine id
4913
- */
4914
- id: StateMachineId,
4915
- /*
4916
- * The height of the state machine
4917
- */
4918
- height: u64
4919
- });
4920
- var Proof = Struct({
4921
- /*
4922
- * The height of the state machine
4923
- */
4924
- height: StateMachineHeight,
4925
- /*
4926
- * The proof
4927
- */
4928
- proof: Vector(u8)
4929
- });
4930
- var PostRequest = Struct({
4931
- /*
4932
- * The source state machine of this request.
4933
- */
4934
- source: StateMachine,
4935
- /*
4936
- * The destination state machine of this request.
4937
- */
4938
- dest: StateMachine,
4939
- /*
4940
- * The nonce of this request on the source chain
4941
- */
4942
- nonce: u64,
4943
- /*
4944
- * Module identifier of the sending module
4945
- */
4946
- from: Vector(u8),
4947
- /*
4948
- * Module identifier of the receiving module
4949
- */
4950
- to: Vector(u8),
4951
- /*
4952
- * Timestamp which this request expires in seconds.
4953
- */
4954
- timeoutTimestamp: u64,
4955
- /*
4956
- * Encoded request body
4957
- */
4958
- body: Vector(u8)
4959
- });
4960
- var PostResponse = Struct({
4961
- /*
4962
- * The request that triggered this response.
4963
- */
4964
- post: PostRequest,
4965
- /*
4966
- * The response message.
4967
- */
4968
- response: Vector(u8),
4969
- /*
4970
- * Timestamp at which this response expires in seconds.
4971
- */
4972
- timeoutTimestamp: u64
4973
- });
4974
- var GetRequest = Struct({
4975
- /*
4976
- * The source state machine of this request.
4977
- */
4978
- source: StateMachine,
4979
- /*
4980
- * The destination state machine of this request.
4981
- */
4982
- dest: StateMachine,
4983
- /*
4984
- * The nonce of this request on the source chain
4985
- */
4986
- nonce: u64,
4987
- /*
4988
- * Module identifier of the sending module
4989
- */
4990
- from: Vector(u8),
4991
- /*
4992
- * Raw Storage keys that would be used to fetch the values from the counterparty
4993
- * For deriving storage keys for ink contract fields follow the guide in the link below
4994
- * `<https://use.ink/datastructures/storage-in-metadata#a-full-example>`
4995
- * Substrate Keys
4996
- */
4997
- keys: Vector(Vector(u8)),
4998
- /*
4999
- * Some application-specific metadata relating to this request
5000
- */
5001
- context: Vector(u8),
5002
- /*
5003
- * Host timestamp at which this request expires in seconds
4618
+ * Queries the request receipt.
4619
+ * @param {HexString} commitment - The commitment to query.
4620
+ * @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
5004
4621
  */
5005
- timeoutTimestamp: u64
5006
- });
5007
- var StorageValue = Struct({
5008
- /*
5009
- * The request storage keys
4622
+ async queryRequestReceipt(commitment) {
4623
+ const relayer = await this.publicClient.readContract({
4624
+ address: this.params.host,
4625
+ abi: evmHost_default.ABI,
4626
+ functionName: "requestReceipts",
4627
+ args: [commitment]
4628
+ });
4629
+ return relayer === DEFAULT_ADDRESS ? void 0 : relayer;
4630
+ }
4631
+ /**
4632
+ * Queries the proof of the commitments.
4633
+ * @param {IMessage} message - The message to query.
4634
+ * @param {string} counterparty - The counterparty address.
4635
+ * @param {bigint} [at] - The block number to query at.
4636
+ * @returns {Promise<HexString>} The proof.
5010
4637
  */
5011
- key: Vector(u8),
5012
- /*
5013
- * The verified value
4638
+ async queryProof(message, counterparty, at) {
4639
+ const commitmentKeys = "Requests" in message ? message.Requests.map((key) => requestCommitmentKey(key)) : message.Responses.map((key) => responseCommitmentKey(key));
4640
+ const config = {
4641
+ address: this.params.host,
4642
+ storageKeys: commitmentKeys
4643
+ };
4644
+ if (!at) {
4645
+ config.blockTag = "latest";
4646
+ } else {
4647
+ config.blockNumber = at;
4648
+ }
4649
+ const proof = await this.publicClient.getProof(config);
4650
+ const flattenedProof = Array.from(new Set(flatten(proof.storageProof.map((item) => item.proof))));
4651
+ const encoded = EvmStateProof.enc({
4652
+ contractProof: proof.accountProof.map((item) => Array.from(hexToBytes(item))),
4653
+ storageProof: [
4654
+ [Array.from(hexToBytes(this.params.host)), flattenedProof.map((item) => Array.from(hexToBytes(item)))]
4655
+ ]
4656
+ });
4657
+ return toHex(encoded);
4658
+ }
4659
+ /**
4660
+ * Query and return the encoded storage proof for the provided keys at the given height.
4661
+ * @param {bigint} at - The block height at which to query the storage proof.
4662
+ * @param {HexString[]} keys - The keys for which to query the storage proof.
4663
+ * @returns {Promise<HexString>} The encoded storage proof.
5014
4664
  */
5015
- value: Option(Vector(u8))
5016
- });
5017
- var GetResponse = Struct({
5018
- /*
5019
- * The Get request that triggered this response.
4665
+ async queryStateProof(at, keys) {
4666
+ const config = {
4667
+ address: this.params.host,
4668
+ storageKeys: keys
4669
+ };
4670
+ if (!at) {
4671
+ config.blockTag = "latest";
4672
+ } else {
4673
+ config.blockNumber = at;
4674
+ }
4675
+ const proof = await this.publicClient.getProof(config);
4676
+ const flattenedProof = Array.from(new Set(flatten(proof.storageProof.map((item) => item.proof))));
4677
+ const encoded = EvmStateProof.enc({
4678
+ contractProof: proof.accountProof.map((item) => Array.from(hexToBytes(item))),
4679
+ storageProof: [
4680
+ [Array.from(hexToBytes(this.params.host)), flattenedProof.map((item) => Array.from(hexToBytes(item)))]
4681
+ ]
4682
+ });
4683
+ return toHex(encoded);
4684
+ }
4685
+ /**
4686
+ * Returns the current timestamp of the chain.
4687
+ * @returns {Promise<bigint>} The current timestamp.
5020
4688
  */
5021
- get: GetRequest,
5022
- /*
5023
- * Values derived from the state proof
4689
+ async timestamp() {
4690
+ const data = await this.publicClient.readContract({
4691
+ address: this.params.host,
4692
+ abi: evmHost_default.ABI,
4693
+ functionName: "timestamp"
4694
+ });
4695
+ return BigInt(data);
4696
+ }
4697
+ /**
4698
+ * Get the latest state machine height for a given state machine ID.
4699
+ * @param {StateMachineIdParams} stateMachineId - The state machine ID.
4700
+ * @returns {Promise<bigint>} The latest state machine height.
5024
4701
  */
5025
- values: Vector(StorageValue)
5026
- });
5027
- var Request2 = Enum({
5028
- /*
5029
- * A post request allows a module on a state machine to send arbitrary bytes to another module
5030
- * living in another state machine.
4702
+ async latestStateMachineHeight(stateMachineId) {
4703
+ if (!this.publicClient) throw new Error("API not initialized");
4704
+ const id = stateMachineId.stateId.Polkadot || stateMachineId.stateId.Kusama;
4705
+ if (!id)
4706
+ throw new Error(
4707
+ "Expected Polakdot or Kusama State machine id when reading latest state machine height on evm"
4708
+ );
4709
+ const data = await this.publicClient.readContract({
4710
+ address: this.params.host,
4711
+ abi: evmHost_default.ABI,
4712
+ functionName: "latestStateMachineHeight",
4713
+ args: [BigInt(id)]
4714
+ });
4715
+ return data;
4716
+ }
4717
+ /**
4718
+ * Get the state machine update time for a given state machine height.
4719
+ * @param {StateMachineHeight} stateMachineHeight - The state machine height.
4720
+ * @returns {Promise<bigint>} The statemachine update time in seconds.
5031
4721
  */
5032
- Post: PostRequest,
5033
- /*
5034
- * A get request allows a module on a state machine to read the storage of another module
5035
- * living in another state machine.
4722
+ async stateMachineUpdateTime(stateMachineHeight) {
4723
+ if (!this.publicClient) throw new Error("API not initialized");
4724
+ const id = stateMachineHeight.id.stateId.Polkadot || stateMachineHeight.id.stateId.Kusama;
4725
+ if (!id) throw new Error("Expected Polkadot or Kusama State machine id when reading state machine update time");
4726
+ const data = await this.publicClient.readContract({
4727
+ address: this.params.host,
4728
+ abi: evmHost_default.ABI,
4729
+ functionName: "stateMachineCommitmentUpdateTime",
4730
+ args: [{ stateMachineId: BigInt(id), height: stateMachineHeight.height }]
4731
+ });
4732
+ return data;
4733
+ }
4734
+ /**
4735
+ * Get the challenge period for a given state machine id.
4736
+ * @param {StateMachineIdParams} stateMachineId - The state machine ID.
4737
+ * @returns {Promise<bigint>} The challenge period in seconds.
5036
4738
  */
5037
- Get: GetRequest
5038
- });
5039
- var Response2 = Enum({
5040
- /*
5041
- * The response to a POST request
4739
+ async challengePeriod(stateMachineId) {
4740
+ if (!this.publicClient) throw new Error("API not initialized");
4741
+ const id = stateMachineId.stateId.Polkadot || stateMachineId.stateId.Kusama;
4742
+ if (!id)
4743
+ throw new Error(
4744
+ "Expected Polkadot or Kusama State machine id when reading latest state machine height on evm"
4745
+ );
4746
+ const data = await this.publicClient.readContract({
4747
+ address: this.params.host,
4748
+ abi: evmHost_default.ABI,
4749
+ functionName: "challengePeriod"
4750
+ });
4751
+ return data;
4752
+ }
4753
+ /**
4754
+ * Encodes an ISMP message for the EVM chain.
4755
+ * @param {IIsmpMessage} message The ISMP message to encode.
4756
+ * @returns {HexString} The encoded calldata.
4757
+ */
4758
+ encode(message) {
4759
+ const encoded = match(message).with({ kind: "PostRequest" }, (request) => {
4760
+ const mmrProof = MmrProof.dec(request.proof.proof);
4761
+ const requests = zip(request.requests, mmrProof.leafIndexAndPos).map(([req, leafIndexAndPos]) => {
4762
+ if (!req || !leafIndexAndPos) return;
4763
+ const [[, kIndex]] = mmrPositionToKIndex(
4764
+ [leafIndexAndPos?.pos],
4765
+ calculateMMRSize(mmrProof.leafCount)
4766
+ );
4767
+ return {
4768
+ request: {
4769
+ source: toHex(req.source),
4770
+ dest: toHex(req.dest),
4771
+ to: req.to,
4772
+ from: req.from,
4773
+ nonce: req.nonce,
4774
+ timeoutTimestamp: req.timeoutTimestamp,
4775
+ body: req.body
4776
+ },
4777
+ index: leafIndexAndPos?.leafIndex,
4778
+ kIndex
4779
+ };
4780
+ }).filter((item) => !!item);
4781
+ const proof = {
4782
+ height: {
4783
+ stateMachineId: BigInt(Number.parseInt(request.proof.stateMachine.split("-")[1])),
4784
+ height: request.proof.height
4785
+ },
4786
+ multiproof: mmrProof.items.map((item) => bytesToHex(new Uint8Array(item))),
4787
+ leafCount: mmrProof.leafCount
4788
+ };
4789
+ const encoded2 = encodeFunctionData({
4790
+ abi: handler_default.ABI,
4791
+ functionName: "handlePostRequests",
4792
+ args: [
4793
+ this.params.host,
4794
+ {
4795
+ proof,
4796
+ requests
4797
+ }
4798
+ ]
4799
+ });
4800
+ return encoded2;
4801
+ }).with({ kind: "TimeoutPostRequest" }, (timeout) => {
4802
+ const proof = SubstrateStateProof.dec(timeout.proof.proof).value.storageProof.map(
4803
+ (item) => toHex(new Uint8Array(item))
4804
+ );
4805
+ const encoded2 = encodeFunctionData({
4806
+ abi: handler_default.ABI,
4807
+ functionName: "handlePostRequestTimeouts",
4808
+ args: [
4809
+ this.params.host,
4810
+ {
4811
+ height: {
4812
+ stateMachineId: BigInt(Number.parseInt(timeout.proof.stateMachine.split("-")[1])),
4813
+ height: timeout.proof.height
4814
+ },
4815
+ timeouts: timeout.requests.map((req) => ({
4816
+ source: toHex(req.source),
4817
+ dest: toHex(req.dest),
4818
+ to: req.to,
4819
+ from: req.from,
4820
+ nonce: req.nonce,
4821
+ timeoutTimestamp: req.timeoutTimestamp,
4822
+ body: req.body
4823
+ })),
4824
+ proof
4825
+ }
4826
+ ]
4827
+ });
4828
+ return encoded2;
4829
+ }).with({ kind: "GetResponse" }, (request) => {
4830
+ const mmrProof = MmrProof.dec(request.proof.proof);
4831
+ const responses = zip(request.responses, mmrProof.leafIndexAndPos).map(([req, leafIndexAndPos]) => {
4832
+ if (!req || !leafIndexAndPos) return;
4833
+ const [[, kIndex]] = mmrPositionToKIndex(
4834
+ [leafIndexAndPos?.pos],
4835
+ calculateMMRSize(mmrProof.leafCount)
4836
+ );
4837
+ return {
4838
+ response: {
4839
+ request: {
4840
+ source: toHex(req.get.source),
4841
+ dest: toHex(req.get.dest),
4842
+ from: req.get.from,
4843
+ nonce: req.get.nonce,
4844
+ timeoutTimestamp: req.get.timeoutTimestamp,
4845
+ keys: req.get.keys,
4846
+ context: req.get.context,
4847
+ height: req.get.height
4848
+ },
4849
+ values: req.values
4850
+ },
4851
+ index: leafIndexAndPos?.leafIndex,
4852
+ kIndex
4853
+ };
4854
+ }).filter((item) => !!item);
4855
+ const proof = {
4856
+ height: {
4857
+ stateMachineId: BigInt(Number.parseInt(request.proof.stateMachine.split("-")[1])),
4858
+ height: request.proof.height
4859
+ },
4860
+ multiproof: mmrProof.items.map((item) => bytesToHex(new Uint8Array(item))),
4861
+ leafCount: mmrProof.leafCount
4862
+ };
4863
+ const encoded2 = encodeFunctionData({
4864
+ abi: handler_default.ABI,
4865
+ functionName: "handleGetResponses",
4866
+ args: [
4867
+ this.params.host,
4868
+ {
4869
+ proof,
4870
+ responses
4871
+ }
4872
+ ]
4873
+ });
4874
+ return encoded2;
4875
+ }).exhaustive();
4876
+ return encoded;
4877
+ }
4878
+ /**
4879
+ * Calculates the fee required to send a post request to the destination chain.
4880
+ * The fee is calculated based on the per-byte fee for the destination chain
4881
+ * multiplied by the size of the request body.
4882
+ *
4883
+ * @param request - The post request to calculate the fee for
4884
+ * @returns The total fee in wei required to send the post request
5042
4885
  */
5043
- Post: PostResponse,
5044
- /*
5045
- * The response to a GET request
4886
+ async quote(request) {
4887
+ const perByteFee = await this.publicClient.readContract({
4888
+ address: this.params.host,
4889
+ abi: evmHost_default.ABI,
4890
+ functionName: "perByteFee",
4891
+ args: [toHex(request.dest)]
4892
+ });
4893
+ const bodyByteLength = Math.floor((request.body.length - 2) / 2);
4894
+ const length = bodyByteLength < 32 ? 32 : bodyByteLength;
4895
+ return perByteFee * BigInt(length);
4896
+ }
4897
+ /**
4898
+ * Estimates the gas required for a post request execution on this chain.
4899
+ * This function generates mock proofs for the post request, creates a state override
4900
+ * with the necessary overlay root, and estimates the gas cost for executing the
4901
+ * handlePostRequests transaction on the handler contract.
4902
+ *
4903
+ * @param request - The post request to estimate gas for
4904
+ * @param paraId - The ID of the parachain (Hyperbridge) that will process the request
4905
+ * @returns The estimated gas amount in gas units and the generated calldata
5046
4906
  */
5047
- Get: GetResponse
5048
- });
5049
- var RequestMessage = Struct({
5050
- /*
5051
- * Requests from source chain
4907
+ async estimateGas(request) {
4908
+ const hostParams = await this.publicClient.readContract({
4909
+ address: this.params.host,
4910
+ abi: evmHost_default.ABI,
4911
+ functionName: "hostParams"
4912
+ });
4913
+ const { root, proof, index, kIndex, treeSize } = await generateRootWithProof(request, 2n ** 10n);
4914
+ const latestStateMachineHeight = 6291991n;
4915
+ const paraId = 4009n;
4916
+ const overlayRootSlot = getStateCommitmentFieldSlot(
4917
+ paraId,
4918
+ // Hyperbridge chain id
4919
+ latestStateMachineHeight,
4920
+ // Hyperbridge chain height
4921
+ 1
4922
+ // For overlayRoot
4923
+ );
4924
+ const postParams = {
4925
+ height: {
4926
+ stateMachineId: BigInt(paraId),
4927
+ height: latestStateMachineHeight
4928
+ },
4929
+ multiproof: proof,
4930
+ leafCount: treeSize
4931
+ };
4932
+ const formattedRequest = {
4933
+ ...request,
4934
+ source: toHex(request.source),
4935
+ dest: toHex(request.dest)
4936
+ };
4937
+ const contractArgs = [
4938
+ this.params.host,
4939
+ {
4940
+ proof: postParams,
4941
+ requests: [
4942
+ {
4943
+ request: formattedRequest,
4944
+ index,
4945
+ kIndex
4946
+ }
4947
+ ]
4948
+ }
4949
+ ];
4950
+ const postRequestCalldata = encodeFunctionData({
4951
+ abi: handler_default.ABI,
4952
+ functionName: "handlePostRequests",
4953
+ args: contractArgs
4954
+ });
4955
+ const gas = await this.publicClient.estimateContractGas({
4956
+ address: hostParams.handler,
4957
+ abi: handler_default.ABI,
4958
+ functionName: "handlePostRequests",
4959
+ args: contractArgs,
4960
+ stateOverride: [
4961
+ {
4962
+ address: this.params.host,
4963
+ stateDiff: [
4964
+ {
4965
+ slot: overlayRootSlot,
4966
+ value: root
4967
+ }
4968
+ ]
4969
+ }
4970
+ ]
4971
+ });
4972
+ return { gas, postRequestCalldata };
4973
+ }
4974
+ /**
4975
+ * Gets the fee token address and decimals for the chain.
4976
+ * This function gets the fee token address and decimals for the chain.
4977
+ *
4978
+ * @returns The fee token address and decimals
5052
4979
  */
5053
- requests: Vector(PostRequest),
5054
- /*
5055
- * Membership batch proof for these requests
4980
+ async getFeeTokenWithDecimals() {
4981
+ const hostParams = await this.publicClient.readContract({
4982
+ abi: evmHost_default.ABI,
4983
+ address: this.params.host,
4984
+ functionName: "hostParams"
4985
+ });
4986
+ const feeTokenAddress = hostParams.feeToken;
4987
+ const feeTokenDecimals = await this.publicClient.readContract({
4988
+ address: feeTokenAddress,
4989
+ abi: erc20Abi,
4990
+ functionName: "decimals"
4991
+ });
4992
+ return { address: feeTokenAddress, decimals: feeTokenDecimals };
4993
+ }
4994
+ /**
4995
+ * Gets the nonce of the host.
4996
+ * This function gets the nonce of the host.
4997
+ *
4998
+ * @returns The nonce of the host
5056
4999
  */
5057
- proof: Proof,
5000
+ async getHostNonce() {
5001
+ const nonce = await this.publicClient.readContract({
5002
+ abi: evmHost_default.ABI,
5003
+ address: this.params.host,
5004
+ functionName: "nonce"
5005
+ });
5006
+ return nonce;
5007
+ }
5008
+ };
5009
+ var REQUEST_COMMITMENTS_SLOT = 0n;
5010
+ var RESPONSE_COMMITMENTS_SLOT = 1n;
5011
+ var REQUEST_RECEIPTS_SLOT = 2n;
5012
+ var RESPONSE_RECEIPTS_SLOT = 3n;
5013
+ var STATE_COMMITMENTS_SLOT = 5n;
5014
+ function requestCommitmentKey(key) {
5015
+ const keyBytes = hexToBytes(key);
5016
+ const slot = REQUEST_COMMITMENTS_SLOT;
5017
+ const mappedKey = deriveMapKey(keyBytes, slot);
5018
+ const number = bytesToBigInt(hexToBytes(mappedKey)) + 1n;
5019
+ return pad(`0x${number.toString(16)}`, { size: 32 });
5020
+ }
5021
+ function responseCommitmentKey(key) {
5022
+ const keyBytes = hexToBytes(key);
5023
+ const slot = RESPONSE_COMMITMENTS_SLOT;
5024
+ const mappedKey = deriveMapKey(keyBytes, slot);
5025
+ const number = bytesToBigInt(hexToBytes(mappedKey)) + 1n;
5026
+ return pad(`0x${number.toString(16)}`, { size: 32 });
5027
+ }
5028
+ function deriveMapKey(key, slot) {
5029
+ const slotBytes = pad(`0x${slot.toString(16)}`, { size: 32 });
5030
+ const combined = new Uint8Array([...key, ...toBytes(slotBytes)]);
5031
+ return keccak256(combined);
5032
+ }
5033
+ function getStateCommitmentFieldSlot(stateMachineId, height, field) {
5034
+ const baseSlot = getStateCommitmentSlot(stateMachineId, height);
5035
+ const slotNumber = bytesToBigInt(toBytes(baseSlot)) + BigInt(field);
5036
+ return pad(`0x${slotNumber.toString(16)}`, { size: 32 });
5037
+ }
5038
+ function getStateCommitmentSlot(stateMachineId, height) {
5039
+ const firstLevelSlot = deriveFirstLevelSlot(stateMachineId, STATE_COMMITMENTS_SLOT);
5040
+ return deriveSecondLevelSlot(height, firstLevelSlot);
5041
+ }
5042
+ function deriveFirstLevelSlot(key, slot) {
5043
+ const keyHex = pad(`0x${key.toString(16)}`, { size: 32 });
5044
+ const keyBytes = toBytes(keyHex);
5045
+ const slotBytes = toBytes(pad(`0x${slot.toString(16)}`, { size: 32 }));
5046
+ const combined = new Uint8Array([...keyBytes, ...slotBytes]);
5047
+ return keccak256(combined);
5048
+ }
5049
+ function deriveSecondLevelSlot(key, firstLevelSlot) {
5050
+ const keyHex = pad(`0x${key.toString(16)}`, { size: 32 });
5051
+ const keyBytes = toBytes(keyHex);
5052
+ const slotBytes = toBytes(firstLevelSlot);
5053
+ const combined = new Uint8Array([...keyBytes, ...slotBytes]);
5054
+ return keccak256(combined);
5055
+ }
5056
+ var SubstrateChain = class {
5057
+ constructor(params) {
5058
+ this.params = params;
5059
+ }
5058
5060
  /*
5059
- * Signer information. Ideally should be their account identifier
5061
+ * api: The Polkadot API instance for the Substrate chain.
5060
5062
  */
5061
- signer: Vector(u8)
5062
- });
5063
- var RequestResponse = Enum({
5063
+ api;
5064
5064
  /*
5065
- * A set of requests
5065
+ * connect: Connects to the Substrate chain using the provided WebSocket URL.
5066
5066
  */
5067
- Request: Vector(Request2),
5068
- /*
5069
- * A set of responses
5067
+ async connect() {
5068
+ const wsProvider = new WsProvider(this.params.ws);
5069
+ const typesBundle = this.params.hasher === "Keccak" ? {
5070
+ spec: {
5071
+ nexus: {
5072
+ hasher: keccakAsU8a
5073
+ },
5074
+ gargantua: {
5075
+ hasher: keccakAsU8a
5076
+ }
5077
+ }
5078
+ } : {};
5079
+ this.api = await ApiPromise.create({
5080
+ provider: wsProvider,
5081
+ typesBundle
5082
+ });
5083
+ }
5084
+ /**
5085
+ * Disconnects the Substrate chain connection.
5070
5086
  */
5071
- Response: Vector(Response2)
5072
- });
5073
- var ResponseMessage = Struct({
5074
- /*
5075
- * A set of either POST requests or responses to be handled
5087
+ async disconnect() {
5088
+ if (this.api) {
5089
+ await this.api.disconnect();
5090
+ this.api = void 0;
5091
+ }
5092
+ }
5093
+ /**
5094
+ * Returns the storage key for a request receipt in the child trie
5095
+ * The request commitment is the key
5096
+ * @param key - The H256 hash key (as a 0x-prefixed hex string)
5097
+ * @returns The storage key as a hex string
5076
5098
  */
5077
- datagram: Vector(RequestResponse),
5078
- /*
5079
- * Membership batch proof for these requests/responses
5099
+ requestReceiptKey(key) {
5100
+ const prefix = new TextEncoder().encode("RequestReceipts");
5101
+ const keyBytes = hexToBytes(key);
5102
+ return bytesToHex(new Uint8Array([...prefix, ...keyBytes]));
5103
+ }
5104
+ /**
5105
+ * Returns the storage key for a request commitment in the child trie
5106
+ * The request commitment is the key
5107
+ * @param key - The H256 hash key (as a 0x-prefixed hex string)
5108
+ * @returns The storage key as a hex string
5080
5109
  */
5081
- proof: Proof,
5082
- /*
5083
- * Signer information. Ideally should be their account identifier
5110
+ requestCommitmentKey(key) {
5111
+ const prefix = new TextEncoder().encode("RequestCommitments");
5112
+ const keyBytes = hexToBytes(key);
5113
+ return bytesToHex(new Uint8Array([...prefix, ...keyBytes]));
5114
+ }
5115
+ /**
5116
+ * Queries a request commitment from the ISMP child trie storage.
5117
+ * @param {HexString} commitment - The commitment hash to look up.
5118
+ * @returns {Promise<HexString | undefined>} The commitment data if found, undefined otherwise.
5084
5119
  */
5085
- signer: Vector(u8)
5086
- });
5087
- var TimeoutMessage = Enum({
5088
- /*
5089
- * A non memership proof for POST requests
5120
+ async queryRequestCommitment(commitment) {
5121
+ const prefix = toHex(":child_storage:default:ISMP");
5122
+ const key = this.requestCommitmentKey(commitment);
5123
+ const rpc = new RpcWebSocketClient();
5124
+ await rpc.connect(this.params.ws);
5125
+ const item = await rpc.call("childstate_getStorage", [prefix, key]);
5126
+ return item;
5127
+ }
5128
+ /**
5129
+ * Queries the request receipt.
5130
+ * @param {HexString} commitment - The commitment to query.
5131
+ * @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
5090
5132
  */
5091
- Post: Struct({
5092
- /*
5093
- * Timed out requests
5094
- */
5095
- requests: Vector(Request2),
5096
- /*
5097
- * Membership batch proof for these requests
5098
- */
5099
- proof: Proof
5100
- }),
5101
- /*
5102
- * A non memership proof for POST responses
5133
+ async queryRequestReceipt(commitment) {
5134
+ const prefix = toHex(":child_storage:default:ISMP");
5135
+ const key = this.requestReceiptKey(commitment);
5136
+ const rpc = new RpcWebSocketClient();
5137
+ await rpc.connect(this.params.ws);
5138
+ const item = await rpc.call("childstate_getStorage", [prefix, key]);
5139
+ return item;
5140
+ }
5141
+ /**
5142
+ * Returns the current timestamp of the chain.
5143
+ * @returns {Promise<bigint>} The current timestamp.
5103
5144
  */
5104
- PostResponse: Struct({
5105
- /*
5106
- * Timed out responses
5107
- */
5108
- responses: Vector(Response2),
5109
- /*
5110
- * Membership batch proof for these responses
5111
- */
5112
- proof: Proof
5113
- }),
5114
- /*
5115
- * There are no proofs for Get timeouts
5145
+ async timestamp() {
5146
+ if (!this.api) throw new Error("API not initialized");
5147
+ const now = await this.api.query.timestamp.now();
5148
+ return BigInt(now.toJSON()) / BigInt(1e3);
5149
+ }
5150
+ /**
5151
+ * Queries the proof of the commitments.
5152
+ * @param {IMessage} message - The message to query.
5153
+ * @param {string} counterparty - The counterparty address.
5154
+ * @param {bigint} [at] - The block number to query at.
5155
+ * @returns {Promise<HexString>} The proof.
5116
5156
  */
5117
- Get: Struct({
5118
- /*
5119
- * Timed out requests
5120
- */
5121
- requests: Vector(Request2)
5122
- })
5123
- });
5124
- var Message = Enum({
5125
- /*
5126
- * A consensus update message
5157
+ async queryProof(message, counterparty, at) {
5158
+ const rpc = new RpcWebSocketClient();
5159
+ await rpc.connect(this.params.ws);
5160
+ if (isEvmChain(counterparty)) {
5161
+ const proof = await rpc.call("mmr_queryProof", [Number(at), message]);
5162
+ return toHex(proof.proof);
5163
+ }
5164
+ if (isSubstrateChain(counterparty)) {
5165
+ const childTrieKeys = "Requests" in message ? message.Requests.map(requestCommitmentStorageKey) : message.Responses.map(responseCommitmentStorageKey);
5166
+ const proof = await rpc.call("ismp_queryChildTrieProof", [Number(at), childTrieKeys]);
5167
+ const basicProof = BasicProof.dec(toHex(proof.proof));
5168
+ const encoded = SubstrateStateProof.enc({
5169
+ tag: "OverlayProof",
5170
+ value: {
5171
+ hasher: {
5172
+ tag: this.params.hasher,
5173
+ value: void 0
5174
+ },
5175
+ storageProof: basicProof
5176
+ }
5177
+ });
5178
+ return toHex(encoded);
5179
+ }
5180
+ throw new ExpectedError(`Unsupported chain type for counterparty: ${counterparty}`);
5181
+ }
5182
+ /**
5183
+ * Submit an unsigned ISMP transaction to the chain. Resolves when the transaction is finalized.
5184
+ * @param message - The message to be submitted.
5185
+ * @returns A promise that resolves to an object containing the transaction hash, block hash, and block number.
5127
5186
  */
5128
- ConsensusMessage,
5129
- /*
5130
- * A fraud proof message
5187
+ async submitUnsigned(message) {
5188
+ if (!this.api) throw new Error("API not initialized");
5189
+ const { api } = this;
5190
+ const args = hexToBytes(this.encode(message)).slice(2);
5191
+ const tx = api.tx.ismp.handleUnsigned(args);
5192
+ return new Promise((resolve, reject) => {
5193
+ let unsub = () => {
5194
+ };
5195
+ tx.send(async ({ isInBlock, isFinalized, isError, dispatchError, txHash, status }) => {
5196
+ if (isFinalized || isInBlock) {
5197
+ unsub();
5198
+ const blockHash = isInBlock ? status.asInBlock.toHex() : status.asFinalized.toHex();
5199
+ const header = await api.rpc.chain.getHeader(blockHash);
5200
+ const apiAt = await api.at(blockHash);
5201
+ const timestamp = await apiAt.query.timestamp.now();
5202
+ resolve({
5203
+ transactionHash: txHash.toHex(),
5204
+ blockHash,
5205
+ blockNumber: header.number.toNumber(),
5206
+ timestamp: Number(timestamp.toJSON()) / 1e3
5207
+ });
5208
+ } else if (isError) {
5209
+ unsub();
5210
+ console.error("Unsigned transaction failed: ", dispatchError);
5211
+ reject(dispatchError);
5212
+ }
5213
+ }).then((unsubscribe) => {
5214
+ unsub = unsubscribe;
5215
+ }).catch(reject);
5216
+ });
5217
+ }
5218
+ /**
5219
+ * Query the state proof for a given set of keys at a specific block height.
5220
+ * @param at The block height to query the state proof at.
5221
+ * @param keys The keys to query the state proof for.
5222
+ * @returns The state proof as a hexadecimal string.
5131
5223
  */
5132
- FraudProofMessage,
5133
- /*
5134
- * A request message
5224
+ async queryStateProof(at, keys) {
5225
+ const rpc = new RpcWebSocketClient();
5226
+ await rpc.connect(this.params.ws);
5227
+ const encodedKeys = keys.map((key) => Array.from(hexToBytes(key)));
5228
+ const proof = await rpc.call("ismp_queryChildTrieProof", [Number(at), encodedKeys]);
5229
+ const basicProof = BasicProof.dec(toHex(proof.proof));
5230
+ const encoded = SubstrateStateProof.enc({
5231
+ tag: "OverlayProof",
5232
+ value: {
5233
+ hasher: {
5234
+ tag: this.params.hasher,
5235
+ value: void 0
5236
+ },
5237
+ storageProof: basicProof
5238
+ }
5239
+ });
5240
+ return toHex(encoded);
5241
+ }
5242
+ /**
5243
+ * Get the latest state machine height for a given state machine ID.
5244
+ * @param {StateMachineIdParams} stateMachineId - The state machine ID.
5245
+ * @returns {Promise<bigint>} The latest state machine height.
5135
5246
  */
5136
- RequestMessage,
5137
- /*
5138
- * A response message
5247
+ async latestStateMachineHeight(stateMachineId) {
5248
+ if (!this.api) throw new Error("API not initialized");
5249
+ const latestHeight = await this.api.query.ismp.latestStateMachineHeight(stateMachineId);
5250
+ return BigInt(latestHeight.toString());
5251
+ }
5252
+ /**
5253
+ * Get the state machine update time for a given state machine height.
5254
+ * @param {StateMachineHeight} stateMachineHeight - The state machine height.
5255
+ * @returns {Promise<bigint>} The statemachine update time in seconds.
5139
5256
  */
5140
- ResponseMessage,
5141
- /*
5142
- * A request timeout message
5257
+ async stateMachineUpdateTime(stateMachineHeight) {
5258
+ if (!this.api) throw new Error("API not initialized");
5259
+ const updateTime = await this.api.query.ismp.stateMachineUpdateTime(stateMachineHeight);
5260
+ return BigInt(updateTime.toString());
5261
+ }
5262
+ /**
5263
+ * Get the challenge period for a given state machine id.
5264
+ * @param {StateMachineIdParams} stateMachineId - The state machine ID.
5265
+ * @returns {Promise<bigint>} The challenge period in seconds.
5143
5266
  */
5144
- TimeoutMessage
5145
- });
5146
-
5147
- // src/utils.ts
5148
- var DEFAULT_POLL_INTERVAL = 5e3;
5149
- var ADDRESS_ZERO2 = "0x0000000000000000000000000000000000000000";
5150
- var MOCK_ADDRESS2 = "0x1234567890123456789012345678901234567890";
5151
- var DUMMY_PRIVATE_KEY = "0x0000000000000000000000000000000000000000000000000000000000000000";
5152
- function sleep(ms) {
5153
- return new Promise((resolve) => setTimeout(resolve, ms || DEFAULT_POLL_INTERVAL));
5154
- }
5155
- async function waitForChallengePeriod(chain, stateMachineHeight) {
5156
- const challengePeriod = await chain.challengePeriod(stateMachineHeight.id);
5157
- if (challengePeriod === BigInt(0)) return;
5158
- const updateTime = await chain.stateMachineUpdateTime(stateMachineHeight);
5159
- let currentTimestamp = await chain.timestamp();
5160
- let timeElapsed = currentTimestamp - updateTime;
5161
- if (timeElapsed > challengePeriod) return;
5162
- await sleep(Number(challengePeriod) * 1e3);
5163
- while (timeElapsed <= challengePeriod) {
5164
- const remainingTime = challengePeriod - timeElapsed;
5165
- await sleep(Number(remainingTime) * 1e3);
5166
- currentTimestamp = await chain.timestamp();
5167
- timeElapsed = currentTimestamp - updateTime;
5267
+ async challengePeriod(stateMachineId) {
5268
+ if (!this.api) throw new Error("API not initialized");
5269
+ const challengePeriod = await this.api.query.ismp.challengePeriod(stateMachineId);
5270
+ return BigInt(challengePeriod.toString());
5168
5271
  }
5169
- }
5170
- function isEvmChain(stateMachineId) {
5171
- return stateMachineId.startsWith("EVM");
5172
- }
5173
- function isSubstrateChain(stateMachineId) {
5174
- return stateMachineId.startsWith("POLKADOT") || stateMachineId.startsWith("KUSAMA") || stateMachineId.startsWith("SUBSTRATE");
5175
- }
5176
- function parseStateMachineId(stateMachineId) {
5177
- const [type, value] = stateMachineId.split("-");
5178
- if (!type || !value) {
5179
- throw new Error(
5180
- `Invalid state machine ID format: ${stateMachineId}. Expected format like "EVM-97" or "SUBSTRATE-cere"`
5181
- );
5272
+ /**
5273
+ * Encode an ISMP calldata for a substrate chain.
5274
+ * @param message The ISMP message to encode.
5275
+ * @returns The encoded message as a hexadecimal string.
5276
+ */
5277
+ encode(message) {
5278
+ const palletIndex = this.getPalletIndex("Ismp");
5279
+ const args = encodeISMPMessage(message);
5280
+ const call = Vector(u8, 2).enc([palletIndex, 0]);
5281
+ return toHex(new Uint8Array([...call, ...args]));
5182
5282
  }
5183
- const stateId = {};
5184
- switch (type.toUpperCase()) {
5185
- case "EVM": {
5186
- const evmChainId = Number.parseInt(value, 10);
5187
- if (Number.isNaN(evmChainId)) {
5188
- throw new Error(`Invalid EVM chain ID: ${value}. Expected a number.`);
5189
- }
5190
- stateId.Evm = evmChainId;
5191
- break;
5192
- }
5193
- case "SUBSTRATE": {
5194
- const bytes = Buffer.from(value, "utf8");
5195
- stateId.Substrate = `0x${bytes.toString("hex")}`;
5196
- break;
5197
- }
5198
- case "POLKADOT": {
5199
- const polkadotChainId = Number.parseInt(value, 10);
5200
- if (Number.isNaN(polkadotChainId)) {
5201
- throw new Error(`Invalid Polkadot chain ID: ${value}. Expected a number.`);
5202
- }
5203
- stateId.Polkadot = polkadotChainId;
5204
- break;
5205
- }
5206
- case "KUSAMA": {
5207
- const kusamaChainId = Number.parseInt(value, 10);
5208
- if (Number.isNaN(kusamaChainId)) {
5209
- throw new Error(`Invalid Kusama chain ID: ${value}. Expected a number.`);
5283
+ /**
5284
+ * Returns the index of a pallet by its name, by looking up the pallets in the runtime metadata.
5285
+ * @param {string} name - The name of the pallet.
5286
+ * @returns {number} The index of the pallet.
5287
+ */
5288
+ getPalletIndex(name) {
5289
+ if (!this.api) throw new Error("API not initialized");
5290
+ const pallets = this.api.runtimeMetadata.asLatest.pallets.entries();
5291
+ for (const p of pallets) {
5292
+ if (p[1].name.toString() === name) {
5293
+ const index = p[1].index.toNumber();
5294
+ return index;
5210
5295
  }
5211
- stateId.Kusama = kusamaChainId;
5212
- break;
5213
5296
  }
5214
- default:
5215
- throw new Error(`Unsupported chain type: ${type}. Expected one of: EVM, SUBSTRATE, POLKADOT, KUSAMA.`);
5216
- }
5217
- return { stateId };
5218
- }
5219
- function postRequestCommitment(post) {
5220
- const data = encodePacked(
5221
- ["bytes", "bytes", "uint64", "uint64", "bytes", "bytes", "bytes"],
5222
- [toHex(post.source), toHex(post.dest), post.nonce, post.timeoutTimestamp, post.from, post.to, post.body]
5223
- );
5224
- return {
5225
- commitment: keccak256(data),
5226
- encodePacked: data
5227
- };
5228
- }
5229
- function orderCommitment2(order) {
5230
- const encodedOrder = encodeAbiParameters(
5231
- [
5232
- {
5233
- name: "order",
5234
- type: "tuple",
5235
- components: [
5236
- { name: "user", type: "bytes32" },
5237
- { name: "sourceChain", type: "bytes" },
5238
- { name: "destChain", type: "bytes" },
5239
- { name: "deadline", type: "uint256" },
5240
- { name: "nonce", type: "uint256" },
5241
- { name: "fees", type: "uint256" },
5242
- {
5243
- name: "outputs",
5244
- type: "tuple[]",
5245
- components: [
5246
- { name: "token", type: "bytes32" },
5247
- { name: "amount", type: "uint256" },
5248
- { name: "beneficiary", type: "bytes32" }
5249
- ]
5250
- },
5251
- {
5252
- name: "inputs",
5253
- type: "tuple[]",
5254
- components: [
5255
- { name: "token", type: "bytes32" },
5256
- { name: "amount", type: "uint256" }
5257
- ]
5258
- },
5259
- { name: "callData", type: "bytes" }
5260
- ]
5261
- }
5262
- ],
5263
- [
5264
- {
5265
- user: order.user,
5266
- sourceChain: order.sourceChain.startsWith("0x") ? order.sourceChain : toHex(order.sourceChain),
5267
- destChain: order.destChain.startsWith("0x") ? order.destChain : toHex(order.destChain),
5268
- deadline: order.deadline,
5269
- nonce: order.nonce,
5270
- fees: order.fees,
5271
- outputs: order.outputs,
5272
- inputs: order.inputs,
5273
- callData: order.callData
5274
- }
5275
- ]
5276
- );
5277
- return keccak256(encodedOrder);
5278
- }
5279
- function bytes32ToBytes202(bytes32Address) {
5280
- if (bytes32Address === ADDRESS_ZERO2) {
5281
- return ADDRESS_ZERO2;
5297
+ throw new Error(`${name} not found in runtime`);
5282
5298
  }
5283
- const bytes = hexToBytes(bytes32Address);
5284
- const addressBytes = bytes.slice(12);
5285
- return bytesToHex(addressBytes);
5299
+ };
5300
+ function requestCommitmentStorageKey(key) {
5301
+ const prefix = new TextEncoder().encode("RequestCommitments");
5302
+ const keyBytes = hexToBytes(key);
5303
+ return Array.from(new Uint8Array([...prefix, ...keyBytes]));
5286
5304
  }
5287
- function bytes20ToBytes32(bytes20Address) {
5288
- return `0x${bytes20Address.slice(2).padStart(64, "0")}`;
5305
+ function responseCommitmentStorageKey(key) {
5306
+ const prefix = new TextEncoder().encode("ResponseCommitments");
5307
+ const keyBytes = hexToBytes(key);
5308
+ return Array.from(new Uint8Array([...prefix, ...keyBytes]));
5289
5309
  }
5290
- function hexToString2(hex) {
5291
- const hexWithoutPrefix = hex.startsWith("0x") ? hex.slice(2) : hex;
5292
- const bytes = new Uint8Array(hexWithoutPrefix.length / 2);
5293
- for (let i = 0; i < hexWithoutPrefix.length; i += 2) {
5294
- bytes[i / 2] = Number.parseInt(hexWithoutPrefix.slice(i, i + 2), 16);
5310
+ function convertStateMachineIdToEnum(id) {
5311
+ let [tag, value] = id.split("-");
5312
+ tag = capitalize(tag);
5313
+ if (["Evm", "Polkadot", "Kusama"].includes(tag)) {
5314
+ value = Number.parseInt(value);
5315
+ } else {
5316
+ value = Array.from(toBytes(value));
5295
5317
  }
5296
- return new TextDecoder().decode(bytes);
5318
+ return { tag, value };
5297
5319
  }
5298
- var DEFAULT_LOGGER = createConsola({
5299
- level: LogLevels.silent
5300
- });
5301
- async function retryPromise(operation, retryConfig) {
5302
- const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed" } = retryConfig;
5303
- let lastError;
5304
- for (let i = 0; i < retryConfig.maxRetries; i++) {
5305
- try {
5306
- return await operation();
5307
- } catch (error) {
5308
- logger.trace(`Retrying(${i}) > ${logMessage}`);
5309
- lastError = error;
5310
- await new Promise((resolve) => setTimeout(resolve, retryConfig.backoffMs * 2 ** i));
5320
+ function convertIPostRequestToCodec(request) {
5321
+ return {
5322
+ tag: "Post",
5323
+ value: {
5324
+ source: convertStateMachineIdToEnum(request.source),
5325
+ dest: convertStateMachineIdToEnum(request.dest),
5326
+ from: Array.from(hexToBytes(request.from)),
5327
+ to: Array.from(hexToBytes(request.to)),
5328
+ nonce: request.nonce,
5329
+ body: Array.from(hexToBytes(request.body)),
5330
+ timeoutTimestamp: request.timeoutTimestamp
5311
5331
  }
5312
- }
5313
- throw lastError;
5314
- }
5315
- function getRequestCommitment(get) {
5316
- const keysEncoding = "0x".concat(get.keys.map((key) => key.slice(2)).join(""));
5317
- return keccak256(
5318
- encodePacked(
5319
- ["bytes", "bytes", "uint64", "uint64", "uint64", "bytes", "bytes", "bytes"],
5320
- [
5321
- toHex(get.source),
5322
- toHex(get.dest),
5323
- get.nonce,
5324
- get.height,
5325
- get.timeoutTimestamp,
5326
- get.from,
5327
- keysEncoding,
5328
- get.context
5329
- ]
5330
- )
5331
- );
5332
- }
5333
- var REQUEST_STATUS_WEIGHTS = {
5334
- [RequestStatus.SOURCE]: 0,
5335
- [RequestStatus.SOURCE_FINALIZED]: 1,
5336
- [RequestStatus.HYPERBRIDGE_DELIVERED]: 2,
5337
- [RequestStatus.HYPERBRIDGE_FINALIZED]: 3,
5338
- [RequestStatus.DESTINATION]: 4,
5339
- [RequestStatus.HYPERBRIDGE_TIMED_OUT]: 5,
5340
- [RequestStatus.TIMED_OUT]: 6
5341
- };
5342
- var TIMEOUT_STATUS_WEIGHTS = {
5343
- [TimeoutStatus.PENDING_TIMEOUT]: 1,
5344
- [TimeoutStatus.DESTINATION_FINALIZED_TIMEOUT]: 2,
5345
- [TimeoutStatus.HYPERBRIDGE_TIMED_OUT]: 3,
5346
- [TimeoutStatus.HYPERBRIDGE_FINALIZED_TIMEOUT]: 4,
5347
- [TimeoutStatus.TIMED_OUT]: 5
5348
- };
5349
- var COMBINED_STATUS_WEIGHTS = {
5350
- [RequestStatus.SOURCE]: 0,
5351
- [RequestStatus.SOURCE_FINALIZED]: 1,
5352
- [RequestStatus.HYPERBRIDGE_DELIVERED]: 2,
5353
- [RequestStatus.HYPERBRIDGE_FINALIZED]: 3,
5354
- [RequestStatus.DESTINATION]: 4,
5355
- [TimeoutStatus.PENDING_TIMEOUT]: 5,
5356
- [TimeoutStatus.DESTINATION_FINALIZED_TIMEOUT]: 6,
5357
- [TimeoutStatus.HYPERBRIDGE_TIMED_OUT]: 7,
5358
- [TimeoutStatus.HYPERBRIDGE_FINALIZED_TIMEOUT]: 8,
5359
- [TimeoutStatus.TIMED_OUT]: 9
5360
- };
5361
- async function estimateGasForPost(params) {
5362
- const hostParams = await params.sourceClient.readContract({
5363
- address: params.hostAddress,
5364
- abi: evmHost_default.ABI,
5365
- functionName: "hostParams"
5366
- });
5367
- const { root, proof, index, kIndex, treeSize } = await generateRootWithProof(params.postRequest, 2n ** 10n);
5368
- const latestStateMachineHeight = params.hostLatestStateMachineHeight;
5369
- const overlayRootSlot = getStateCommitmentFieldSlot(
5370
- BigInt(4009n),
5371
- // Hyperbridge chain id
5372
- latestStateMachineHeight,
5373
- // Hyperbridge chain height
5374
- 1
5375
- // For overlayRoot
5376
- );
5377
- const postParams = {
5378
- height: {
5379
- stateMachineId: BigInt(4009n),
5380
- height: latestStateMachineHeight
5381
- },
5382
- multiproof: proof,
5383
- leafCount: treeSize
5384
5332
  };
5385
- const gas = await params.sourceClient.estimateContractGas({
5386
- address: hostParams.handler,
5387
- abi: handler_default.ABI,
5388
- functionName: "handlePostRequests",
5389
- args: [
5390
- params.hostAddress,
5391
- {
5392
- proof: postParams,
5393
- requests: [
5394
- {
5395
- request: {
5396
- ...params.postRequest,
5397
- source: toHex(params.postRequest.source),
5398
- dest: toHex(params.postRequest.dest)
5333
+ }
5334
+ function encodeISMPMessage(message) {
5335
+ try {
5336
+ return match(message).with({ kind: "PostRequest" }, (message2) => {
5337
+ return Vector(Message).enc([
5338
+ {
5339
+ tag: "RequestMessage",
5340
+ value: {
5341
+ requests: message2.requests.map(
5342
+ (post_request) => convertIPostRequestToCodec(post_request).value
5343
+ ),
5344
+ proof: {
5345
+ height: {
5346
+ height: message2.proof.height,
5347
+ id: {
5348
+ consensusStateId: Array.from(toBytes(message2.proof.consensusStateId)),
5349
+ id: convertStateMachineIdToEnum(message2.proof.stateMachine)
5350
+ }
5351
+ },
5352
+ proof: Array.from(hexToBytes(message2.proof.proof))
5399
5353
  },
5400
- index,
5401
- kIndex
5402
- }
5403
- ]
5404
- }
5405
- ],
5406
- stateOverride: [
5407
- {
5408
- address: params.hostAddress,
5409
- stateDiff: [
5410
- {
5411
- slot: overlayRootSlot,
5412
- value: root
5354
+ signer: Array.from(hexToBytes(message2.signer))
5413
5355
  }
5414
- ]
5415
- }
5416
- ]
5417
- });
5418
- return gas;
5419
- }
5420
- function constructRedeemEscrowRequestBody2(order, beneficiary) {
5421
- const commitment = order.id;
5422
- const inputs = order.inputs;
5423
- const requestKind = encodePacked(["uint8"], [0 /* RedeemEscrow */]);
5424
- const requestBody = {
5425
- commitment,
5426
- beneficiary: bytes20ToBytes32(beneficiary),
5427
- tokens: inputs
5428
- };
5429
- const encodedRequestBody = encodeAbiParameters(
5430
- [
5431
- {
5432
- name: "requestBody",
5433
- type: "tuple",
5434
- components: [
5435
- { name: "commitment", type: "bytes32" },
5436
- { name: "beneficiary", type: "bytes32" },
5437
- {
5438
- name: "tokens",
5439
- type: "tuple[]",
5440
- components: [
5441
- { name: "token", type: "bytes32" },
5442
- { name: "amount", type: "uint256" }
5443
- ]
5356
+ }
5357
+ ]);
5358
+ }).with({ kind: "GetResponse" }, (message2) => {
5359
+ throw new Error("GetResponse is not yet supported on Substrate chains");
5360
+ }).with({ kind: "TimeoutPostRequest" }, (message2) => {
5361
+ return Vector(Message).enc([
5362
+ {
5363
+ tag: "TimeoutMessage",
5364
+ value: {
5365
+ tag: "Post",
5366
+ value: {
5367
+ requests: message2.requests.map((r) => convertIPostRequestToCodec(r)),
5368
+ proof: {
5369
+ height: {
5370
+ height: message2.proof.height,
5371
+ id: {
5372
+ consensusStateId: Array.from(toBytes(message2.proof.consensusStateId)),
5373
+ id: convertStateMachineIdToEnum(message2.proof.stateMachine)
5374
+ }
5375
+ },
5376
+ proof: Array.from(hexToBytes(message2.proof.proof))
5377
+ }
5378
+ }
5444
5379
  }
5445
- ]
5446
- }
5447
- ],
5448
- [requestBody]
5449
- );
5450
- return concatHex([requestKind, encodedRequestBody]);
5380
+ }
5381
+ ]);
5382
+ }).exhaustive();
5383
+ } catch (error) {
5384
+ throw new Error("Failed to encode ISMP message", { cause: error });
5385
+ }
5451
5386
  }
5452
- var dateStringtoTimestamp = (date) => {
5453
- if (!date.endsWith("Z")) {
5454
- date = `${date}Z`;
5387
+
5388
+ // src/chain.ts
5389
+ async function getChain(chainConfig) {
5390
+ if (isEvmChain(chainConfig.stateMachineId)) {
5391
+ const config = chainConfig;
5392
+ const chainId = Number.parseInt(chainConfig.stateMachineId.split("-")[1]);
5393
+ const evmChain = new EvmChain({
5394
+ chainId,
5395
+ url: config.rpcUrl,
5396
+ host: config.host
5397
+ });
5398
+ return evmChain;
5455
5399
  }
5456
- return new Date(date).getTime();
5457
- };
5458
- function mapTestnetToMainnet(identifier) {
5459
- identifier = identifier.toLowerCase();
5460
- switch (identifier) {
5461
- case "bnb":
5462
- return "wbnb";
5463
- case "eth":
5464
- return "weth";
5465
- case "tbnb":
5466
- return "wbnb";
5467
- case "0xc043f483373072f7f27420d6e7d7ad269c018e18".toLowerCase():
5468
- return "dai";
5469
- case "0xae13d989dac2f0debff460ac112a837c89baa7cd".toLowerCase():
5470
- return "wbnb";
5471
- case "0x1938165569A5463327fb206bE06d8D9253aa06b7".toLowerCase():
5472
- return "dai";
5473
- case "0xC625ec7D30A4b1AAEfb1304610CdAcD0d606aC92".toLowerCase():
5474
- return "dai";
5475
- case "0x50B1d3c7c073c9caa1Ef207365A2c9C976bD70b9".toLowerCase():
5476
- return "dai";
5477
- case "0xa801da100bf16d07f668f4a49e1f71fc54d05177".toLowerCase():
5478
- return "dai";
5479
- default:
5480
- return identifier;
5400
+ if (isSubstrateChain(chainConfig.stateMachineId)) {
5401
+ const config = chainConfig;
5402
+ const substrateChain = new SubstrateChain({
5403
+ ws: config.wsUrl,
5404
+ hasher: config.hasher
5405
+ });
5406
+ await substrateChain.connect();
5407
+ return substrateChain;
5481
5408
  }
5409
+ throw new ExpectedError(`Unsupported chain: ${chainConfig.stateMachineId}`);
5482
5410
  }
5483
- async function fetchTokenUsdPrice2(identifier) {
5484
- try {
5485
- const coinGeckoPrice = await fetchFromCoinGecko(identifier);
5486
- return coinGeckoPrice;
5487
- } catch (error) {
5488
- try {
5489
- const defillamaPrice = await fetchFromDefillama(identifier);
5490
- return defillamaPrice;
5491
- } catch (fallbackError) {
5492
- console.log(
5493
- `Both APIs failed for ${identifier}. CoinGecko: ${error}, Defillama: ${fallbackError}. Returning 1`
5494
- );
5495
- return 1;
5411
+
5412
+ // src/queries.ts
5413
+ var POST_REQUEST_STATUS = `
5414
+ query RequestStatusM($hash: String!) {
5415
+ requests(
5416
+ filter: { commitment: { equalTo: $hash } }
5417
+ ) {
5418
+ nodes {
5419
+ commitment
5420
+ timeoutTimestamp
5421
+ source
5422
+ dest
5423
+ to
5424
+ from
5425
+ nonce
5426
+ body
5427
+ statusMetadata {
5428
+ nodes {
5429
+ blockHash
5430
+ blockNumber
5431
+ timestamp
5432
+ chain
5433
+ status
5434
+ transactionHash
5435
+ }
5436
+ }
5496
5437
  }
5497
5438
  }
5498
5439
  }
5499
- async function fetchFromCoinGecko(identifier) {
5500
- const mappedIdentifier = mapTestnetToMainnet(identifier);
5501
- const url = mappedIdentifier.startsWith("0x") ? `https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=${mappedIdentifier}&vs_currencies=usd` : `https://api.coingecko.com/api/v3/simple/price?ids=${mappedIdentifier}&vs_currencies=usd`;
5502
- const response = await fetch(url);
5503
- if (!response.ok) {
5504
- throw new Error(`CoinGecko API error: ${response.status} ${response.statusText}`);
5440
+ `;
5441
+ var GET_REQUEST_STATUS = `
5442
+ query GetRequestDetails($commitment: String!) {
5443
+ getRequests(
5444
+ filter: { commitment: { equalTo: $commitment } }
5445
+ ) {
5446
+ nodes {
5447
+ id
5448
+ source
5449
+ dest
5450
+ from
5451
+ keys
5452
+ nonce
5453
+ height
5454
+ context
5455
+ timeoutTimestamp
5456
+ fee
5457
+ blockNumber
5458
+ blockHash
5459
+ transactionHash
5460
+ blockTimestamp
5461
+ status
5462
+ chain
5463
+ commitment
5464
+ statusMetadata {
5465
+ nodes {
5466
+ status
5467
+ chain
5468
+ timestamp
5469
+ blockNumber
5470
+ blockHash
5471
+ transactionHash
5472
+ }
5473
+ }
5474
+ }
5475
+ }
5476
+ }`;
5477
+ var STATE_MACHINE_UPDATES_BY_HEIGHT = `
5478
+ query StateMachineUpdatesByHeight($statemachineId: String!, $height: Int!, $chain: String!) {
5479
+ stateMachineUpdateEvents(
5480
+ filter: {
5481
+ and: [
5482
+ { stateMachineId: { equalTo: $statemachineId } }
5483
+ { height: { greaterThanOrEqualTo: $height } }
5484
+ { chain: { equalTo: $chain } }
5485
+ ]
5486
+ }
5487
+ orderBy: HEIGHT_ASC
5488
+ first: 1
5489
+ ) {
5490
+ nodes {
5491
+ height
5492
+ stateMachineId
5493
+ chain
5494
+ blockHash
5495
+ blockNumber
5496
+ transactionHash
5497
+ createdAt
5498
+ }
5499
+ }
5500
+ }
5501
+ `;
5502
+ var STATE_MACHINE_UPDATES_BY_TIMESTAMP = `
5503
+ query StateMachineUpdatesByTimestamp($statemachineId: String!, $commitmentTimestamp: BigFloat!, $chain: String!) {
5504
+ stateMachineUpdateEvents(
5505
+ filter: {
5506
+ and: [
5507
+ { stateMachineId: { equalTo: $statemachineId } }
5508
+ { commitmentTimestamp: { greaterThanOrEqualTo: $commitmentTimestamp } }
5509
+ { chain: { equalTo: $chain } }
5510
+ ]
5511
+ }
5512
+ orderBy: COMMITMENT_TIMESTAMP_DESC
5513
+ first: 1
5514
+ ) {
5515
+ nodes {
5516
+ height
5517
+ stateMachineId
5518
+ chain
5519
+ blockHash
5520
+ blockNumber
5521
+ transactionHash
5522
+ commitmentTimestamp
5523
+ createdAt
5524
+ }
5525
+ }
5505
5526
  }
5506
- const data = await response.json();
5507
- const key = mappedIdentifier.toLowerCase();
5508
- if (!data[key]?.usd) {
5509
- throw new Error(`Price not found for token: ${mappedIdentifier}`);
5527
+ `;
5528
+ var ASSET_TELEPORTED_BY_PARAMS = `
5529
+ query AssetTeleportedByParams($from: String!, $to: String!, $dest: String!, $blockNumber: Int!) {
5530
+ assetTeleporteds(
5531
+ filter: {
5532
+ and: [
5533
+ { from: { equalTo: $from } }
5534
+ { to: { equalTo: $to } }
5535
+ { dest: { includes: $dest } }
5536
+ { blockNumber: { greaterThanOrEqualTo: $blockNumber } }
5537
+ ]
5538
+ }
5539
+ orderBy: CREATED_AT_DESC
5540
+ first: 1
5541
+ ) {
5542
+ nodes {
5543
+ id
5544
+ from
5545
+ to
5546
+ amount
5547
+ dest
5548
+ commitment
5549
+ createdAt
5550
+ blockNumber
5551
+ }
5510
5552
  }
5511
- return data[key].usd;
5512
5553
  }
5513
- async function fetchFromDefillama(identifier) {
5514
- const mappedIdentifier = mapTestnetToMainnet(identifier);
5515
- const coinId = mappedIdentifier.startsWith("0x") ? `ethereum:${mappedIdentifier}` : `coingecko:${mappedIdentifier}`;
5516
- const url = `https://coins.llama.fi/prices/current/${coinId}`;
5517
- const response = await fetch(url);
5518
- if (!response.ok) {
5519
- throw new Error(`Defillama API error: ${response.status} ${response.statusText}`);
5520
- }
5521
- const data = await response.json();
5522
- const price = data.coins?.[coinId]?.price;
5523
- if (!price && price !== 0) {
5524
- throw new Error(`Price not found for token: ${mappedIdentifier}`);
5554
+ `;
5555
+ var GET_RESPONSE_BY_REQUEST_ID = `
5556
+ query GetResponseByRequestId($requestId: String!) {
5557
+ getResponses(filter: {requestId: {equalTo: $requestId}}) {
5558
+ nodes {
5559
+ id
5560
+ commitment
5561
+ responseMessage
5562
+ }
5525
5563
  }
5526
- return price;
5527
5564
  }
5528
- var ERC20Method = /* @__PURE__ */ ((ERC20Method2) => {
5529
- ERC20Method2["BALANCE_OF"] = "0x70a08231";
5530
- ERC20Method2["ALLOWANCE"] = "0xdd62ed3e";
5531
- return ERC20Method2;
5532
- })(ERC20Method || {});
5533
- async function getStorageSlot2(client, contractAddress, data) {
5534
- const traceCallClient = client.extend((client2) => ({
5535
- async traceCall(args) {
5536
- return client2.request({
5537
- // @ts-ignore
5538
- method: "debug_traceCall",
5539
- // @ts-ignore
5540
- params: [args, "latest", {}]
5541
- });
5542
- }
5543
- }));
5544
- const response = await traceCallClient.traceCall({
5545
- to: contractAddress,
5546
- data
5547
- });
5548
- const methodSignature = data.slice(0, 10);
5549
- const logs = response.structLogs;
5550
- for (let i = logs.length - 1; i >= 0; i--) {
5551
- const log = logs[i];
5552
- if (log.op === "SLOAD" && log.stack?.length >= 3) {
5553
- const sigHash = log.stack[0];
5554
- const slotHex = log.stack[log.stack.length - 1];
5555
- if (sigHash === methodSignature && slotHex.length === 66) {
5556
- return slotHex;
5565
+ `;
5566
+ var ORDER_STATUS = `
5567
+ query OrderStatus($commitment: String!) {
5568
+ orderPlaceds(
5569
+ filter: { commitment: { equalTo: $commitment } }
5570
+ ) {
5571
+ nodes {
5572
+ id
5573
+ user
5574
+ sourceChain
5575
+ destChain
5576
+ commitment
5577
+ deadline
5578
+ nonce
5579
+ fees
5580
+ inputTokens
5581
+ inputAmounts
5582
+ inputValuesUSD
5583
+ inputUSD
5584
+ outputTokens
5585
+ outputAmounts
5586
+ outputBeneficiaries
5587
+ calldata
5588
+ status
5589
+ createdAt
5590
+ blockNumber
5591
+ blockTimestamp
5592
+ transactionHash
5593
+ statusMetadata {
5594
+ nodes {
5595
+ status
5596
+ chain
5597
+ timestamp
5598
+ blockNumber
5599
+ transactionHash
5600
+ filler
5601
+ }
5557
5602
  }
5558
5603
  }
5559
5604
  }
5560
- throw new Error(`Storage slot not found for data: ${methodSignature}`);
5561
- }
5562
- function adjustFeeDecimals(feeInFeeToken, fromDecimals, toDecimals) {
5563
- if (fromDecimals === toDecimals) return feeInFeeToken;
5564
- if (fromDecimals < toDecimals) {
5565
- const scaleFactor = BigInt(10 ** (toDecimals - fromDecimals));
5566
- return feeInFeeToken * scaleFactor;
5567
- } else {
5568
- const scaleFactor = BigInt(10 ** (fromDecimals - toDecimals));
5569
- return (feeInFeeToken + scaleFactor - 1n) / scaleFactor;
5605
+ }`;
5606
+ var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
5607
+ query TokenGatewayAssetTeleportedStatus($commitment: String!) {
5608
+ tokenGatewayAssetTeleporteds(
5609
+ filter: { commitment: { equalTo: $commitment } }
5610
+ ) {
5611
+ nodes {
5612
+ id
5613
+ from
5614
+ to
5615
+ sourceChain
5616
+ destChain
5617
+ commitment
5618
+ amount
5619
+ usdValue
5620
+ assetId
5621
+ redeem
5622
+ status
5623
+ createdAt
5624
+ blockNumber
5625
+ blockTimestamp
5626
+ transactionHash
5627
+ statusMetadata {
5628
+ nodes {
5629
+ status
5630
+ chain
5631
+ timestamp
5632
+ blockNumber
5633
+ transactionHash
5634
+ }
5635
+ }
5636
+ }
5570
5637
  }
5571
- }
5638
+ }`;
5572
5639
  function createQueryClient(config) {
5573
5640
  return new GraphQLClient(config.url);
5574
5641
  }
@@ -6204,7 +6271,7 @@ var IndexerClient = class {
6204
6271
  switch (status) {
6205
6272
  // request has been dispatched from source chain
6206
6273
  case RequestStatus.SOURCE: {
6207
- let sourceUpdate = await this.waitOrAbort({
6274
+ const sourceUpdate = await this.waitOrAbort({
6208
6275
  signal,
6209
6276
  promise: () => this.queryStateMachineUpdateByHeight({
6210
6277
  statemachineId: request.source,
@@ -6246,7 +6313,7 @@ var IndexerClient = class {
6246
6313
  }
6247
6314
  // the request has been verified and aggregated on Hyperbridge
6248
6315
  case RequestStatus.HYPERBRIDGE_DELIVERED: {
6249
- let hyperbridgeFinalized = await this.waitOrAbort({
6316
+ const hyperbridgeFinalized = await this.waitOrAbort({
6250
6317
  signal,
6251
6318
  promise: () => {
6252
6319
  const stateMachineId = this.config.hyperbridge.stateMachineId;
@@ -6263,17 +6330,36 @@ var IndexerClient = class {
6263
6330
  ...this.config.hyperbridge,
6264
6331
  hasher: "Keccak"
6265
6332
  });
6266
- const proof = await hyperbridge.queryProof(
6267
- { Requests: [postRequestCommitment(request).commitment] },
6268
- request.dest,
6269
- BigInt(hyperbridgeFinalized.height)
6270
- );
6333
+ const safeFetchProof = async () => {
6334
+ try {
6335
+ const proof_hex = await hyperbridge.queryProof(
6336
+ { Requests: [postRequestCommitment(request).commitment] },
6337
+ request.dest,
6338
+ BigInt(hyperbridgeFinalized.height)
6339
+ );
6340
+ return { data: proof_hex, error: null };
6341
+ } catch (err) {
6342
+ return { error: err, data: null };
6343
+ }
6344
+ };
6345
+ const proof = await this.waitOrAbort({
6346
+ signal,
6347
+ promise: () => this.withRetry(safeFetchProof, {
6348
+ backoffMs: 2e3,
6349
+ maxRetries: 6
6350
+ // <-- should fail after 2mins
6351
+ })
6352
+ });
6353
+ if (proof.data === null) {
6354
+ this.logger.error("Failed to fetch proof:", proof.error);
6355
+ throw proof.error;
6356
+ }
6271
6357
  const calldata = destChain.encode({
6272
6358
  kind: "PostRequest",
6273
6359
  proof: {
6274
6360
  stateMachine: this.config.hyperbridge.stateMachineId,
6275
6361
  consensusStateId: this.config.hyperbridge.consensusStateId,
6276
- proof,
6362
+ proof: proof.data,
6277
6363
  height: BigInt(hyperbridgeFinalized.height)
6278
6364
  },
6279
6365
  requests: [request],
@@ -6362,7 +6448,7 @@ var IndexerClient = class {
6362
6448
  async *getRequestStatusStream(hash) {
6363
6449
  const controller = new AbortController();
6364
6450
  try {
6365
- let request = await this.waitOrAbort({
6451
+ const request = await this.waitOrAbort({
6366
6452
  signal: controller.signal,
6367
6453
  promise: () => this.queryGetRequest(hash)
6368
6454
  });
@@ -6398,7 +6484,7 @@ var IndexerClient = class {
6398
6484
  switch (status) {
6399
6485
  // request has been dispatched from source chain
6400
6486
  case RequestStatus.SOURCE: {
6401
- let sourceUpdate = await this.waitOrAbort({
6487
+ const sourceUpdate = await this.waitOrAbort({
6402
6488
  signal,
6403
6489
  promise: () => this.queryStateMachineUpdateByHeight({
6404
6490
  statemachineId: request.source,
@@ -6443,7 +6529,7 @@ var IndexerClient = class {
6443
6529
  if (request.source === this.config.hyperbridge.stateMachineId) {
6444
6530
  return;
6445
6531
  }
6446
- let hyperbridgeFinalized = await this.waitOrAbort({
6532
+ const hyperbridgeFinalized = await this.waitOrAbort({
6447
6533
  signal,
6448
6534
  promise: () => this.queryStateMachineUpdateByHeight({
6449
6535
  statemachineId: this.config.hyperbridge.stateMachineId,
@@ -6694,7 +6780,7 @@ var IndexerClient = class {
6694
6780
  })
6695
6781
  });
6696
6782
  } else {
6697
- let timeout = await this.waitOrAbort({
6783
+ const timeout = await this.waitOrAbort({
6698
6784
  signal,
6699
6785
  promise: async () => {
6700
6786
  const req = await this.queryPostRequest(hash);
@@ -8038,6 +8124,11 @@ var ABI3 = [
8038
8124
  internalType: "struct Order",
8039
8125
  name: "order",
8040
8126
  type: "tuple"
8127
+ },
8128
+ {
8129
+ internalType: "bytes32",
8130
+ name: "graffiti",
8131
+ type: "bytes32"
8041
8132
  }
8042
8133
  ],
8043
8134
  name: "placeOrder",
@@ -11364,21 +11455,21 @@ var IntentGateway = class {
11364
11455
  * protocol fees, and swap operations.
11365
11456
  *
11366
11457
  * @param order - The order to estimate fill costs for
11367
- * @returns The estimated total cost in the source chain's fee token
11458
+ * @returns An object containing the estimated cost in both fee token and native token, plus the post request calldata
11368
11459
  */
11369
11460
  async estimateFillOrder(order) {
11370
11461
  const postRequest = {
11371
11462
  source: order.destChain,
11372
11463
  dest: order.sourceChain,
11373
- body: constructRedeemEscrowRequestBody2(order, MOCK_ADDRESS2),
11464
+ body: constructRedeemEscrowRequestBody(order, MOCK_ADDRESS),
11374
11465
  timeoutTimestamp: 0n,
11375
11466
  nonce: await this.source.getHostNonce(),
11376
11467
  from: this.source.config.getIntentGatewayAddress(order.destChain),
11377
11468
  to: this.source.config.getIntentGatewayAddress(order.sourceChain)
11378
11469
  };
11379
- const { decimals: sourceChainFeeTokenDecimals } = await this.source.getFeeTokenWithDecimals();
11470
+ const { decimals: sourceChainFeeTokenDecimals, address: sourceChainFeeTokenAddress } = await this.source.getFeeTokenWithDecimals();
11380
11471
  const { address: destChainFeeTokenAddress, decimals: destChainFeeTokenDecimals } = await this.dest.getFeeTokenWithDecimals();
11381
- const postGasEstimate = await this.source.estimateGas(postRequest);
11472
+ const { gas: postGasEstimate, postRequestCalldata } = await this.source.estimateGas(postRequest);
11382
11473
  const postGasEstimateInSourceFeeToken = await this.convertGasToFeeToken(
11383
11474
  postGasEstimate,
11384
11475
  this.source.client,
@@ -11394,23 +11485,23 @@ var IntentGateway = class {
11394
11485
  const fillOptions = {
11395
11486
  relayerFee: relayerFeeInDestFeeToken
11396
11487
  };
11397
- const totalEthValue = order.outputs.filter((output) => bytes32ToBytes202(output.token) === ADDRESS_ZERO2).reduce((sum, output) => sum + output.amount, 0n);
11488
+ const totalEthValue = order.outputs.filter((output) => bytes32ToBytes20(output.token) === ADDRESS_ZERO).reduce((sum, output) => sum + output.amount, 0n);
11398
11489
  const intentGatewayAddress = this.source.config.getIntentGatewayAddress(order.destChain);
11399
11490
  const testValue = toHex(maxUint256 / 2n);
11400
11491
  const orderOverrides = await Promise.all(
11401
11492
  order.outputs.map(async (output) => {
11402
- const tokenAddress = bytes32ToBytes202(output.token);
11403
- if (tokenAddress === ADDRESS_ZERO2) {
11493
+ const tokenAddress = bytes32ToBytes20(output.token);
11494
+ if (tokenAddress === ADDRESS_ZERO) {
11404
11495
  return null;
11405
11496
  }
11406
11497
  try {
11407
11498
  const stateDiffs = [];
11408
- const balanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(MOCK_ADDRESS2).slice(2);
11409
- const balanceSlot = await getStorageSlot2(this.dest.client, tokenAddress, balanceData);
11499
+ const balanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2);
11500
+ const balanceSlot = await getStorageSlot(this.dest.client, tokenAddress, balanceData);
11410
11501
  stateDiffs.push({ slot: balanceSlot, value: testValue });
11411
11502
  try {
11412
- const allowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(MOCK_ADDRESS2).slice(2) + bytes20ToBytes32(intentGatewayAddress).slice(2);
11413
- const allowanceSlot = await getStorageSlot2(
11503
+ const allowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2) + bytes20ToBytes32(intentGatewayAddress).slice(2);
11504
+ const allowanceSlot = await getStorageSlot(
11414
11505
  this.dest.client,
11415
11506
  tokenAddress,
11416
11507
  allowanceData
@@ -11426,31 +11517,11 @@ var IntentGateway = class {
11426
11517
  }
11427
11518
  })
11428
11519
  ).then((results) => results.filter(Boolean));
11429
- const destFeeTokenBalanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(MOCK_ADDRESS2).slice(2);
11430
- const destFeeTokenBalanceSlot = await getStorageSlot2(
11431
- this.dest.client,
11432
- destChainFeeTokenAddress,
11433
- destFeeTokenBalanceData
11434
- );
11435
- const destFeeTokenAllowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(MOCK_ADDRESS2).slice(2) + bytes20ToBytes32(intentGatewayAddress).slice(2);
11436
- const destFeeTokenAllowanceSlot = await getStorageSlot2(
11437
- this.dest.client,
11438
- destChainFeeTokenAddress,
11439
- destFeeTokenAllowanceData
11440
- );
11441
- const feeTokenStateDiffs = [
11442
- { slot: destFeeTokenBalanceSlot, value: testValue },
11443
- { slot: destFeeTokenAllowanceSlot, value: testValue }
11444
- ];
11445
- orderOverrides.push({
11446
- address: destChainFeeTokenAddress,
11447
- stateDiff: feeTokenStateDiffs
11448
- });
11449
- const stateOverride = [
11520
+ let stateOverrides = [
11450
11521
  // Mock address with ETH balance so that any chain estimation runs
11451
11522
  // even when the address doesn't hold any native token in that chain
11452
11523
  {
11453
- address: MOCK_ADDRESS2,
11524
+ address: MOCK_ADDRESS,
11454
11525
  balance: maxUint256
11455
11526
  },
11456
11527
  ...orderOverrides.map((override) => ({
@@ -11458,15 +11529,52 @@ var IntentGateway = class {
11458
11529
  stateDiff: override.stateDiff
11459
11530
  }))
11460
11531
  ];
11461
- const destChainFillGas = await this.dest.client.estimateContractGas({
11462
- abi: IntentGateway_default.ABI,
11463
- address: intentGatewayAddress,
11464
- functionName: "fillOrder",
11465
- args: [transformOrderForContract(order), fillOptions],
11466
- account: MOCK_ADDRESS2,
11467
- value: totalEthValue,
11468
- stateOverride
11469
- });
11532
+ let destChainFillGas = 0n;
11533
+ try {
11534
+ const protocolFeeInNativeToken = await this.quoteNative(postRequest, relayerFeeInDestFeeToken);
11535
+ destChainFillGas = await this.dest.client.estimateContractGas({
11536
+ abi: IntentGateway_default.ABI,
11537
+ address: intentGatewayAddress,
11538
+ functionName: "fillOrder",
11539
+ args: [transformOrderForContract(order), fillOptions],
11540
+ account: MOCK_ADDRESS,
11541
+ value: totalEthValue + protocolFeeInNativeToken,
11542
+ stateOverride: stateOverrides
11543
+ });
11544
+ } catch {
11545
+ console.warn(
11546
+ `Could not estimate gas for fill order with native token as fees for chain ${order.destChain}, now trying with fee token as fees`
11547
+ );
11548
+ const destFeeTokenBalanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2);
11549
+ const destFeeTokenBalanceSlot = await getStorageSlot(
11550
+ this.dest.client,
11551
+ destChainFeeTokenAddress,
11552
+ destFeeTokenBalanceData
11553
+ );
11554
+ const destFeeTokenAllowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2) + bytes20ToBytes32(intentGatewayAddress).slice(2);
11555
+ const destFeeTokenAllowanceSlot = await getStorageSlot(
11556
+ this.dest.client,
11557
+ destChainFeeTokenAddress,
11558
+ destFeeTokenAllowanceData
11559
+ );
11560
+ const feeTokenStateDiffs = [
11561
+ { slot: destFeeTokenBalanceSlot, value: testValue },
11562
+ { slot: destFeeTokenAllowanceSlot, value: testValue }
11563
+ ];
11564
+ stateOverrides.push({
11565
+ address: destChainFeeTokenAddress,
11566
+ stateDiff: feeTokenStateDiffs
11567
+ });
11568
+ destChainFillGas = await this.dest.client.estimateContractGas({
11569
+ abi: IntentGateway_default.ABI,
11570
+ address: intentGatewayAddress,
11571
+ functionName: "fillOrder",
11572
+ args: [transformOrderForContract(order), fillOptions],
11573
+ account: MOCK_ADDRESS,
11574
+ value: totalEthValue,
11575
+ stateOverride: stateOverrides
11576
+ });
11577
+ }
11470
11578
  const fillGasInSourceFeeToken = await this.convertGasToFeeToken(
11471
11579
  destChainFillGas,
11472
11580
  this.dest.client,
@@ -11481,17 +11589,88 @@ var IntentGateway = class {
11481
11589
  const totalEstimate = fillGasInSourceFeeToken + protocolFeeInSourceFeeToken + relayerFeeInSourceFeeToken;
11482
11590
  const SWAP_OPERATIONS_BPS = 2500n;
11483
11591
  const swapOperationsInFeeToken = totalEstimate * SWAP_OPERATIONS_BPS / 10000n;
11484
- return totalEstimate + swapOperationsInFeeToken;
11592
+ const totalFeeTokenAmount = totalEstimate + swapOperationsInFeeToken;
11593
+ const totalNativeTokenAmount = await this.convertFeeTokenToNative(
11594
+ totalFeeTokenAmount,
11595
+ this.source.client,
11596
+ sourceChainFeeTokenDecimals
11597
+ );
11598
+ return {
11599
+ feeTokenAmount: totalFeeTokenAmount,
11600
+ nativeTokenAmount: totalNativeTokenAmount,
11601
+ postRequestCalldata
11602
+ };
11603
+ }
11604
+ /**
11605
+ * Converts fee token amounts back to the equivalent amount in native token.
11606
+ * Uses USD pricing to convert between fee token amounts and native token costs.
11607
+ *
11608
+ * @param feeTokenAmount - The amount in fee token (DAI)
11609
+ * @param publicClient - The client for the chain to get native token info
11610
+ * @param feeTokenDecimals - The decimal places of the fee token
11611
+ * @returns The fee token amount converted to native token amount
11612
+ * @private
11613
+ */
11614
+ async convertFeeTokenToNative(feeTokenAmount, publicClient, feeTokenDecimals) {
11615
+ const nativeToken = publicClient.chain?.nativeCurrency;
11616
+ if (!nativeToken?.symbol || !nativeToken?.decimals) {
11617
+ throw new Error("Chain native currency information not available");
11618
+ }
11619
+ const feeTokenAmountNumber = Number(feeTokenAmount) / Math.pow(10, feeTokenDecimals);
11620
+ const nativeTokenPriceUsd = await fetchTokenUsdPrice(nativeToken.symbol);
11621
+ const totalCostInNativeToken = feeTokenAmountNumber / nativeTokenPriceUsd;
11622
+ return BigInt(Math.floor(totalCostInNativeToken * Math.pow(10, nativeToken.decimals)));
11623
+ }
11624
+ /**
11625
+ * Converts gas costs to the equivalent amount in the fee token (DAI).
11626
+ * Uses USD pricing to convert between native token gas costs and fee token amounts.
11627
+ *
11628
+ * @param gasEstimate - The estimated gas units
11629
+ * @param publicClient - The client for the chain to get gas prices
11630
+ * @param targetDecimals - The decimal places of the target fee token
11631
+ * @returns The gas cost converted to fee token amount
11632
+ * @private
11633
+ */
11634
+ async convertGasToFeeToken(gasEstimate, publicClient, targetDecimals) {
11635
+ const gasPrice = await publicClient.getGasPrice();
11636
+ const gasCostInWei = gasEstimate * gasPrice;
11637
+ const nativeToken = publicClient.chain?.nativeCurrency;
11638
+ if (!nativeToken?.symbol || !nativeToken?.decimals) {
11639
+ throw new Error("Chain native currency information not available");
11640
+ }
11641
+ const gasCostInToken = Number(gasCostInWei) / Math.pow(10, nativeToken.decimals);
11642
+ const tokenPriceUsd = await fetchTokenUsdPrice(nativeToken.symbol);
11643
+ const gasCostUsd = gasCostInToken * tokenPriceUsd;
11644
+ const feeTokenPriceUsd = await fetchTokenUsdPrice("DAI");
11645
+ const gasCostInFeeToken = gasCostUsd / feeTokenPriceUsd;
11646
+ return BigInt(Math.floor(gasCostInFeeToken * Math.pow(10, targetDecimals)));
11647
+ }
11648
+ async quoteNative(postRequest, fee) {
11649
+ const dispatchPost = {
11650
+ dest: toHex(postRequest.dest),
11651
+ to: postRequest.to,
11652
+ body: postRequest.body,
11653
+ timeout: postRequest.timeoutTimestamp,
11654
+ fee,
11655
+ payer: postRequest.from
11656
+ };
11657
+ const quoteNative = await this.dest.client.readContract({
11658
+ address: this.dest.config.getIntentGatewayAddress(postRequest.dest),
11659
+ abi: IntentGateway_default.ABI,
11660
+ functionName: "quoteNative",
11661
+ args: [dispatchPost]
11662
+ });
11663
+ return quoteNative;
11485
11664
  }
11486
11665
  /**
11487
- * Finds the best Uniswap protocol (V2 or V3) for swapping tokens given a desired output amount.
11666
+ * Finds the best Uniswap protocol (V2, V3, or V4) for swapping tokens given a desired output amount.
11488
11667
  * Compares liquidity and pricing across different protocols and fee tiers.
11489
11668
  *
11490
11669
  * @param chain - The chain identifier where the swap will occur
11491
11670
  * @param tokenIn - The address of the input token
11492
11671
  * @param tokenOut - The address of the output token
11493
11672
  * @param amountOut - The desired output amount
11494
- * @returns Object containing the best protocol, required input amount, and fee tier (for V3)
11673
+ * @returns Object containing the best protocol, required input amount, and fee tier (for V3/V4)
11495
11674
  */
11496
11675
  async findBestProtocolWithAmountOut(chain, tokenIn, tokenOut, amountOut) {
11497
11676
  const destClient = this.dest.client;
@@ -11507,8 +11686,8 @@ var IntentGateway = class {
11507
11686
  const v3Quoter = this.source.config.getUniswapV3QuoterAddress(chain);
11508
11687
  const v4Quoter = this.source.config.getUniswapV4QuoterAddress(chain);
11509
11688
  const wethAsset = this.source.config.getWrappedNativeAssetWithDecimals(chain).asset;
11510
- const tokenInForQuote = tokenIn === ADDRESS_ZERO2 ? wethAsset : tokenIn;
11511
- const tokenOutForQuote = tokenOut === ADDRESS_ZERO2 ? wethAsset : tokenOut;
11689
+ const tokenInForQuote = tokenIn === ADDRESS_ZERO ? wethAsset : tokenIn;
11690
+ const tokenOutForQuote = tokenOut === ADDRESS_ZERO ? wethAsset : tokenOut;
11512
11691
  try {
11513
11692
  const v2PairExists = await destClient.readContract({
11514
11693
  address: v2Factory,
@@ -11516,7 +11695,7 @@ var IntentGateway = class {
11516
11695
  functionName: "getPair",
11517
11696
  args: [tokenInForQuote, tokenOutForQuote]
11518
11697
  });
11519
- if (v2PairExists !== ADDRESS_ZERO2) {
11698
+ if (v2PairExists !== ADDRESS_ZERO) {
11520
11699
  const v2AmountIn = await destClient.readContract({
11521
11700
  address: v2Router,
11522
11701
  abi: uniswapRouterV2_default.ABI,
@@ -11537,7 +11716,7 @@ var IntentGateway = class {
11537
11716
  functionName: "getPool",
11538
11717
  args: [tokenInForQuote, tokenOutForQuote, fee]
11539
11718
  });
11540
- if (pool !== ADDRESS_ZERO2) {
11719
+ if (pool !== ADDRESS_ZERO) {
11541
11720
  const liquidity = await destClient.readContract({
11542
11721
  address: pool,
11543
11722
  abi: uniswapV3Pool_default.ABI,
@@ -11581,7 +11760,7 @@ var IntentGateway = class {
11581
11760
  currency1,
11582
11761
  fee,
11583
11762
  tickSpacing: this.getTickSpacing(fee),
11584
- hooks: ADDRESS_ZERO2
11763
+ hooks: ADDRESS_ZERO
11585
11764
  // No hooks
11586
11765
  };
11587
11766
  const quoteResult = (await destClient.simulateContract({
@@ -11648,14 +11827,14 @@ var IntentGateway = class {
11648
11827
  }
11649
11828
  }
11650
11829
  /**
11651
- * Finds the best Uniswap protocol (V2 or V3) for swapping tokens given an input amount.
11830
+ * Finds the best Uniswap protocol (V2, V3, or V4) for swapping tokens given an input amount.
11652
11831
  * Compares liquidity and pricing across different protocols and fee tiers.
11653
11832
  *
11654
11833
  * @param chain - The chain identifier where the swap will occur
11655
11834
  * @param tokenIn - The address of the input token
11656
11835
  * @param tokenOut - The address of the output token
11657
11836
  * @param amountIn - The input amount to swap
11658
- * @returns Object containing the best protocol, expected output amount, and fee tier (for V3)
11837
+ * @returns Object containing the best protocol, expected output amount, and fee tier (for V3/V4)
11659
11838
  */
11660
11839
  async findBestProtocolWithAmountIn(chain, tokenIn, tokenOut, amountIn) {
11661
11840
  const destClient = this.dest.client;
@@ -11671,8 +11850,8 @@ var IntentGateway = class {
11671
11850
  const v3Quoter = this.source.config.getUniswapV3QuoterAddress(chain);
11672
11851
  const v4Quoter = this.source.config.getUniswapV4QuoterAddress(chain);
11673
11852
  const wethAsset = this.source.config.getWrappedNativeAssetWithDecimals(chain).asset;
11674
- const tokenInForQuote = tokenIn === ADDRESS_ZERO2 ? wethAsset : tokenIn;
11675
- const tokenOutForQuote = tokenOut === ADDRESS_ZERO2 ? wethAsset : tokenOut;
11853
+ const tokenInForQuote = tokenIn === ADDRESS_ZERO ? wethAsset : tokenIn;
11854
+ const tokenOutForQuote = tokenOut === ADDRESS_ZERO ? wethAsset : tokenOut;
11676
11855
  try {
11677
11856
  const v2PairExists = await destClient.readContract({
11678
11857
  address: v2Factory,
@@ -11680,7 +11859,7 @@ var IntentGateway = class {
11680
11859
  functionName: "getPair",
11681
11860
  args: [tokenInForQuote, tokenOutForQuote]
11682
11861
  });
11683
- if (v2PairExists !== ADDRESS_ZERO2) {
11862
+ if (v2PairExists !== ADDRESS_ZERO) {
11684
11863
  const v2AmountOut = await destClient.readContract({
11685
11864
  address: v2Router,
11686
11865
  abi: uniswapRouterV2_default.ABI,
@@ -11701,7 +11880,7 @@ var IntentGateway = class {
11701
11880
  functionName: "getPool",
11702
11881
  args: [tokenInForQuote, tokenOutForQuote, fee]
11703
11882
  });
11704
- if (pool !== ADDRESS_ZERO2) {
11883
+ if (pool !== ADDRESS_ZERO) {
11705
11884
  const liquidity = await destClient.readContract({
11706
11885
  address: pool,
11707
11886
  abi: uniswapV3Pool_default.ABI,
@@ -11745,7 +11924,7 @@ var IntentGateway = class {
11745
11924
  currency1,
11746
11925
  fee,
11747
11926
  tickSpacing: this.getTickSpacing(fee),
11748
- hooks: ADDRESS_ZERO2
11927
+ hooks: ADDRESS_ZERO
11749
11928
  // No hooks
11750
11929
  };
11751
11930
  const quoteResult = (await destClient.simulateContract({
@@ -11811,30 +11990,6 @@ var IntentGateway = class {
11811
11990
  };
11812
11991
  }
11813
11992
  }
11814
- /**
11815
- * Converts gas costs to the equivalent amount in the fee token (DAI).
11816
- * Uses USD pricing to convert between native token gas costs and fee token amounts.
11817
- *
11818
- * @param gasEstimate - The estimated gas units
11819
- * @param publicClient - The client for the chain to get gas prices
11820
- * @param targetDecimals - The decimal places of the target fee token
11821
- * @returns The gas cost converted to fee token amount
11822
- * @private
11823
- */
11824
- async convertGasToFeeToken(gasEstimate, publicClient, targetDecimals) {
11825
- const gasPrice = await publicClient.getGasPrice();
11826
- const gasCostInWei = gasEstimate * gasPrice;
11827
- const nativeToken = publicClient.chain?.nativeCurrency;
11828
- if (!nativeToken?.symbol || !nativeToken?.decimals) {
11829
- throw new Error("Chain native currency information not available");
11830
- }
11831
- const gasCostInToken = Number(gasCostInWei) / Math.pow(10, nativeToken.decimals);
11832
- const tokenPriceUsd = await fetchTokenUsdPrice2(nativeToken.symbol);
11833
- const gasCostUsd = gasCostInToken * tokenPriceUsd;
11834
- const feeTokenPriceUsd = await fetchTokenUsdPrice2("DAI");
11835
- const gasCostInFeeToken = gasCostUsd / feeTokenPriceUsd;
11836
- return BigInt(Math.floor(gasCostInFeeToken * Math.pow(10, targetDecimals)));
11837
- }
11838
11993
  /**
11839
11994
  * Checks if an order has been filled by verifying the commitment status on-chain.
11840
11995
  * Reads the storage slot corresponding to the order's commitment hash.
@@ -12199,6 +12354,6 @@ async function teleportDot(param_) {
12199
12354
  return stream;
12200
12355
  }
12201
12356
 
12202
- export { ADDRESS_ZERO2 as ADDRESS_ZERO, AbortSignalInternal, ChainConfigService, Chains, DEFAULT_ADDRESS, DUMMY_PRIVATE_KEY, ERC20Method, EvmChain, HyperClientStatus, IndexerClient, IntentGateway, OrderStatus, REQUEST_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, RESPONSE_COMMITMENTS_SLOT, RESPONSE_RECEIPTS_SLOT, RequestKind, RequestStatus, STATE_COMMITMENTS_SLOT, SubstrateChain, TeleportStatus, TimeoutStatus, WrappedNativeDecimals, __test, addresses, adjustFeeDecimals, assets, bytes20ToBytes32, bytes32ToBytes202 as bytes32ToBytes20, chainIds, consensusStateIds, constructRedeemEscrowRequestBody2 as constructRedeemEscrowRequestBody, convertStateMachineIdToEnum, createQueryClient, createRpcUrls, encodeISMPMessage, estimateGasForPost, fetchTokenUsdPrice2 as fetchTokenUsdPrice, generateRootWithProof, getChain, getRequestCommitment, getStateCommitmentFieldSlot, getStateCommitmentSlot, getStorageSlot2 as getStorageSlot, hexToString2 as hexToString, orderCommitment2 as orderCommitment, postRequestCommitment, queryGetRequest, queryPostRequest, teleport, teleportDot, viemChains };
12357
+ export { ADDRESS_ZERO, ChainConfigService, Chains, DEFAULT_ADDRESS, DEFAULT_GRAFFITI, DUMMY_PRIVATE_KEY, ERC20Method, EvmChain, HyperClientStatus, IndexerClient, IntentGateway, OrderStatus, REQUEST_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, RESPONSE_COMMITMENTS_SLOT, RESPONSE_RECEIPTS_SLOT, RequestKind, RequestStatus, STATE_COMMITMENTS_SLOT, SubstrateChain, TeleportStatus, TimeoutStatus, WrappedNativeDecimals, __test, addresses, adjustFeeDecimals, assets, bytes20ToBytes32, bytes32ToBytes20, chainIds, consensusStateIds, constructRedeemEscrowRequestBody, convertStateMachineIdToEnum, createQueryClient, createRpcUrls, encodeISMPMessage, estimateGasForPost, fetchTokenUsdPrice, generateRootWithProof, getChain, getRequestCommitment, getStateCommitmentFieldSlot, getStateCommitmentSlot, getStorageSlot, hexToString, orderCommitment, postRequestCommitment, queryGetRequest, queryPostRequest, teleport, teleportDot, viemChains };
12203
12358
  //# sourceMappingURL=index.js.map
12204
12359
  //# sourceMappingURL=index.js.map