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