@hyperbridge/sdk 2.6.1 → 2.8.0

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.
@@ -10,7 +10,7 @@ import { match } from 'ts-pattern';
10
10
  import { WsProvider, ApiPromise, Keyring } from '@polkadot/api';
11
11
  import { Struct, Vector, u8, Bytes, Enum, Tuple, _void, u64, u32, Option, bool, u128 } from 'scale-ts';
12
12
  import { keccakAsU8a, decodeAddress, keccakAsHex, xxhashAsU8a, blake2AsU8a } from '@polkadot/util-crypto';
13
- import { hexToU8a, u8aToHex, u8aConcat } from '@polkadot/util';
13
+ import { hexToU8a, u8aToHex, u8aConcat, stringToU8a, isHex as isHex$1, u8aToString } from '@polkadot/util';
14
14
  import PQueue from 'p-queue';
15
15
  import { hasWindow, isNode, env } from 'std-env';
16
16
  import mergeRace from '@async-generator/merge-race';
@@ -2682,7 +2682,8 @@ var chainConfigs = {
2682
2682
  ZARP: "0xb755506531786C8aC63B756BaB1ac387bACB0C04",
2683
2683
  EURC: "0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c",
2684
2684
  XSGD: "0x70e8dE73cE538DA2bEEd35d14187F6959a8ecA96",
2685
- TRYB: "0x2C537E5624e4af88A7ae4060C022609376C8D0EB"
2685
+ TRYB: "0x2C537E5624e4af88A7ae4060C022609376C8D0EB",
2686
+ USDR: "0x9623DfB044D5612Ce0c0F1606973CCAEFd03CD05"
2686
2687
  },
2687
2688
  tokenDecimals: {
2688
2689
  USDC: 6,
@@ -2721,6 +2722,10 @@ var chainConfigs = {
2721
2722
  consensusStateId: "ETH0",
2722
2723
  coingeckoId: "ethereum",
2723
2724
  layerZeroEid: 30101,
2725
+ erc4626Vaults: [
2726
+ { label: "Aave stataUSDC", address: "0xD4fa2D31b7968E448877f69A96DE69f5de8cD23E", asset: "USDC" },
2727
+ { label: "Aave stataUSDT", address: "0x7Bc3485026Ac48b6cf9BaF0A377477Fff5703Af8", asset: "USDT" }
2728
+ ],
2724
2729
  popularTokens: [
2725
2730
  "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
2726
2731
  "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
@@ -2775,6 +2780,10 @@ var chainConfigs = {
2775
2780
  defaultRpcUrl: "https://binance.llamarpc.com",
2776
2781
  consensusStateId: "BSC0",
2777
2782
  coingeckoId: "binance-smart-chain",
2783
+ erc4626Vaults: [
2784
+ { label: "Aave stataUSDC", address: "0x3906cDdfb781f02B21f21BD81ed7Fd8DC37075E1", asset: "USDC" },
2785
+ { label: "Aave stataUSDT", address: "0x0471D185cc7Be61E154277cAB2396cD397663da6", asset: "USDT" }
2786
+ ],
2778
2787
  popularTokens: [
2779
2788
  "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82",
2780
2789
  "0x000Ae314E2A2172a039B26378814C252734f556A",
@@ -2834,6 +2843,10 @@ var chainConfigs = {
2834
2843
  consensusStateId: "ETH0",
2835
2844
  coingeckoId: "arbitrum-one",
2836
2845
  layerZeroEid: 30110,
2846
+ erc4626Vaults: [
2847
+ { label: "Aave stataUSDC", address: "0x7F6501d3B98eE91f9b9535E4b0ac710Fb0f9e0bc", asset: "USDC" },
2848
+ { label: "Aave stataUSDT", address: "0xa6D12574eFB239FC1D2099732bd8b5dC6306897F", asset: "USDT" }
2849
+ ],
2837
2850
  popularTokens: [
2838
2851
  "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
2839
2852
  "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
@@ -2854,7 +2867,8 @@ var chainConfigs = {
2854
2867
  EXT: "0x0e668E5127087e236578893a0e01E41837A28469",
2855
2868
  cNGN: "0x46C85152bFe9f96829aA94755D9f915F9B10EF5F",
2856
2869
  ZARP: "0xb755506531786C8aC63B756BaB1ac387bACB0C04",
2857
- EURC: "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"
2870
+ EURC: "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42",
2871
+ USDR: "0x3B5F2810fB2168FfA9C73160F97BF9f2461fFa5c"
2858
2872
  },
2859
2873
  tokenDecimals: {
2860
2874
  USDC: 6,
@@ -2896,6 +2910,10 @@ var chainConfigs = {
2896
2910
  coingeckoId: "base",
2897
2911
  layerZeroEid: 30184,
2898
2912
  uniswapV4Pools: [{ tokens: ["USDC", "cNGN"], fee: 1500, tickSpacing: 30 }],
2913
+ erc4626Vaults: [
2914
+ { label: "Aave stataUSDC", address: "0xC768c589647798a6EE01A91FdE98EF2ed046DBD6", asset: "USDC" },
2915
+ { label: "Yield Bearing cNGN", address: "0xa82A3531021317240Fb32E67f9c7bC091F737D3b", asset: "cNGN" }
2916
+ ],
2899
2917
  popularTokens: [
2900
2918
  "0x4200000000000000000000000000000000000006",
2901
2919
  "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
@@ -2916,7 +2934,8 @@ var chainConfigs = {
2916
2934
  EXT: "0x7C8c11ADb8EF7cd3CFa718008Ea048445C6E7209",
2917
2935
  cNGN: "0x52828daa48C1a9A06F37500882b42daf0bE04C3B",
2918
2936
  ZARP: "0xb755506531786C8aC63B756BaB1ac387bACB0C04",
2919
- XSGD: "0xDC3326e71D45186F113a2F448984CA0e8D201995"
2937
+ XSGD: "0xDC3326e71D45186F113a2F448984CA0e8D201995",
2938
+ USDR: "0x3B5F2810fB2168FfA9C73160F97BF9f2461fFa5c"
2920
2939
  },
2921
2940
  tokenDecimals: {
2922
2941
  USDC: 6,
@@ -2956,6 +2975,10 @@ var chainConfigs = {
2956
2975
  consensusStateId: "POLY",
2957
2976
  coingeckoId: "polygon-pos",
2958
2977
  layerZeroEid: 30109,
2978
+ erc4626Vaults: [
2979
+ { label: "Aave stataUSDC", address: "0x79261231698B26Ed9085b59ae89d59843Ae925a8", asset: "USDC" },
2980
+ { label: "Aave stataUSDT", address: "0x2eaD203C5C1C00612B1DdbBb20e4180dA822d6ff", asset: "USDT" }
2981
+ ],
2959
2982
  popularTokens: [
2960
2983
  "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",
2961
2984
  "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
@@ -3002,7 +3025,7 @@ var chainConfigs = {
3002
3025
  WETH: "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9",
3003
3026
  //wmatic, change it to wpol
3004
3027
  DAI: "0x0000000000000000000000000000000000000000",
3005
- USDC: "0x693b854d6965ffeaae21c74049dea644b56fcacb",
3028
+ USDC: "0xBE97E73126D66188d72fbF99029126D0340a7f18",
3006
3029
  USDT: "0x0000000000000000000000000000000000000000"
3007
3030
  },
3008
3031
  tokenDecimals: {
@@ -3011,7 +3034,7 @@ var chainConfigs = {
3011
3034
  },
3012
3035
  tokenStorageSlots: {
3013
3036
  USDT: { balanceSlot: 0, allowanceSlot: 1 },
3014
- USDC: { balanceSlot: 1, allowanceSlot: 2 }
3037
+ USDC: { balanceSlot: 0, allowanceSlot: 1 }
3015
3038
  },
3016
3039
  addresses: {
3017
3040
  IntentGateway: "0x6CF42FA9BecbC5b6a26884964956b113530f7cFA",
@@ -4818,6 +4841,24 @@ var ABI3 = [
4818
4841
  internalType: "uint256"
4819
4842
  }
4820
4843
  ]
4844
+ },
4845
+ {
4846
+ name: "predispatchCall",
4847
+ type: "bytes",
4848
+ indexed: false,
4849
+ internalType: "bytes"
4850
+ },
4851
+ {
4852
+ name: "outputCall",
4853
+ type: "bytes",
4854
+ indexed: false,
4855
+ internalType: "bytes"
4856
+ },
4857
+ {
4858
+ name: "graffiti",
4859
+ type: "bytes32",
4860
+ indexed: false,
4861
+ internalType: "bytes32"
4821
4862
  }
4822
4863
  ],
4823
4864
  anonymous: false
@@ -5177,6 +5218,19 @@ var ChainConfigService = class {
5177
5218
  getExtDecimals(chain) {
5178
5219
  return this.getConfig(chain)?.tokenDecimals?.EXT;
5179
5220
  }
5221
+ /** Configured exotic (non-USD) tokens on a chain, for selection UIs. EXT is a test asset and is not offered. */
5222
+ getKnownExoticTokens(chain) {
5223
+ const config = this.getConfig(chain);
5224
+ const tokens = [];
5225
+ if (config?.assets?.cNGN) {
5226
+ tokens.push({ symbol: "cNGN", address: config.assets.cNGN, decimals: config.tokenDecimals?.cNGN });
5227
+ }
5228
+ return tokens;
5229
+ }
5230
+ /** Known ERC-4626 treasury vaults on a chain, for selection UIs. */
5231
+ getKnownVaults(chain) {
5232
+ return this.getConfig(chain)?.erc4626Vaults ?? [];
5233
+ }
5180
5234
  getChainId(chain) {
5181
5235
  return this.getConfig(chain)?.chainId ?? 0;
5182
5236
  }
@@ -7466,17 +7520,30 @@ var SubstrateChain = class _SubstrateChain {
7466
7520
  rotationMap.set(BigInt(setId.toString()), BigInt(height.toString()));
7467
7521
  }
7468
7522
  const proofs = [];
7469
- let epoch = currentEpoch - 1n;
7523
+ let epoch = currentEpoch + 1n;
7470
7524
  while (rotationMap.has(epoch)) {
7471
- const height = rotationMap.get(epoch);
7472
- const key = beefyOffchainKey(height);
7473
- const proof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", key]);
7525
+ const key = rotationOffchainKey(epoch);
7526
+ let proof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", key]);
7527
+ if (!proof) {
7528
+ const legacyKey = messagingOffchainKey(rotationMap.get(epoch));
7529
+ proof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", legacyKey]);
7530
+ }
7474
7531
  if (!proof) return void 0;
7475
7532
  proofs.push(proof);
7476
7533
  epoch++;
7477
7534
  }
7478
- const messagingKey = beefyOffchainKey(lastProvenHeight);
7479
- const messagingProof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", messagingKey]);
7535
+ const messagingKey = messagingOffchainKey(lastProvenHeight);
7536
+ let messagingProof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", messagingKey]);
7537
+ if (!messagingProof) {
7538
+ for (const [setId, height] of rotationMap) {
7539
+ if (height !== lastProvenHeight) continue;
7540
+ messagingProof = await this.rpcClient.call("offchain_localStorageGet", [
7541
+ "PERSISTENT",
7542
+ rotationOffchainKey(setId)
7543
+ ]);
7544
+ break;
7545
+ }
7546
+ }
7480
7547
  if (!messagingProof) return void 0;
7481
7548
  proofs.push(messagingProof);
7482
7549
  return { proofs, provenHeight: lastProvenHeight };
@@ -7493,11 +7560,17 @@ var SubstrateChain = class _SubstrateChain {
7493
7560
  throw new Error(`${name} not found in runtime`);
7494
7561
  }
7495
7562
  };
7496
- function beefyOffchainKey(provenHeight) {
7497
- const prefix = new TextEncoder().encode("beefy_consensus_proofs::");
7498
- const heightBytes = new Uint8Array(8);
7499
- new DataView(heightBytes.buffer).setBigUint64(0, provenHeight, false);
7500
- return toHex(new Uint8Array([...prefix, ...heightBytes]));
7563
+ function beefyOffchainKey(prefix, id) {
7564
+ const prefixBytes = new TextEncoder().encode(prefix);
7565
+ const idBytes = new Uint8Array(8);
7566
+ new DataView(idBytes.buffer).setBigUint64(0, id, false);
7567
+ return toHex(new Uint8Array([...prefixBytes, ...idBytes]));
7568
+ }
7569
+ function messagingOffchainKey(provenHeight) {
7570
+ return beefyOffchainKey("beefy_consensus_proofs::", provenHeight);
7571
+ }
7572
+ function rotationOffchainKey(setId) {
7573
+ return beefyOffchainKey("beefy_consensus_proofs::rotation::", setId);
7501
7574
  }
7502
7575
  function requestCommitmentStorageKey(key) {
7503
7576
  const prefix = new TextEncoder().encode("RequestCommitments");
@@ -8167,14 +8240,17 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
8167
8240
  const orders = [];
8168
8241
  for (const { event } of records) {
8169
8242
  if (event.section !== "intentsCoprocessor" || event.method !== "PhantomOrderRegistered") continue;
8170
- const [commitment, chain, createdAt, tokenA, tokenB, standardAmount] = event.data;
8243
+ const [commitment, chain, createdAt, legs] = event.data;
8171
8244
  orders.push({
8172
8245
  commitment: commitment.toHex(),
8173
8246
  chain: new TextDecoder().decode(hexToU8a(chain.toHex())),
8174
8247
  createdAt: createdAt.toNumber(),
8175
- tokenA: tokenA.toHex(),
8176
- tokenB: tokenB.toHex(),
8177
- standardAmount: BigInt(standardAmount.toString())
8248
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8249
+ legs: legs.map((leg) => ({
8250
+ tokenA: leg.tokenA.toHex(),
8251
+ tokenB: leg.tokenB.toHex(),
8252
+ standardAmount: BigInt(leg.standardAmount.toString())
8253
+ }))
8178
8254
  });
8179
8255
  }
8180
8256
  return orders;
@@ -15385,14 +15461,21 @@ function orderCommitment(order) {
15385
15461
  const encoded = encodeAbiParameters([orderType], [transformOrderForContract(order)]);
15386
15462
  return keccak256(encoded);
15387
15463
  }
15388
- async function convertGasToFeeToken(ctx, gasEstimate, gasEstimateIn, evmChainID, gasPriceOverride) {
15464
+ function bumpGasPrice(gasPrice, bumpPercent) {
15465
+ if (bumpPercent < 0n) {
15466
+ throw new Error("Gas price bump percent cannot be negative");
15467
+ }
15468
+ return (gasPrice * (100n + bumpPercent) + 99n) / 100n;
15469
+ }
15470
+ async function convertGasToFeeToken(ctx, gasEstimate, gasEstimateIn, evmChainID, gasPriceOverride, gasPriceBumpPercent = 0n) {
15389
15471
  if (TESTNET_CHAINS.has(evmChainID)) return 1n;
15390
15472
  const chain = ctx[gasEstimateIn];
15391
15473
  const client = chain.client;
15392
- const gasPrice = gasPriceOverride ?? await retryPromise(() => client.getGasPrice(), {
15474
+ const baseGasPrice = gasPriceOverride ?? await retryPromise(() => client.getGasPrice(), {
15393
15475
  maxRetries: 3,
15394
15476
  backoffMs: 250
15395
15477
  });
15478
+ const gasPrice = bumpGasPrice(baseGasPrice, gasPriceBumpPercent);
15396
15479
  const gasCostInWei = gasEstimate * gasPrice;
15397
15480
  const wethAddr = chain.configService.getWrappedNativeAssetWithDecimals(evmChainID).asset;
15398
15481
  const feeToken = await getFeeToken(ctx, evmChainID, chain);
@@ -15463,13 +15546,13 @@ function deriveCanonicalPlacedOrder(order, args) {
15463
15546
  session: args.session,
15464
15547
  predispatch: {
15465
15548
  assets: args.predispatch.map((asset) => ({ ...asset })),
15466
- call: order.predispatch.call
15549
+ call: args.predispatchCall ?? order.predispatch.call
15467
15550
  },
15468
15551
  inputs: args.inputs.map((asset) => ({ ...asset })),
15469
15552
  output: {
15470
15553
  beneficiary: args.beneficiary,
15471
15554
  assets: args.outputs.map((asset) => ({ ...asset })),
15472
- call: order.output.call
15555
+ call: args.outputCall ?? order.output.call
15473
15556
  }
15474
15557
  };
15475
15558
  return { ...canonicalOrder, id: orderCommitment(canonicalOrder) };
@@ -15893,6 +15976,12 @@ var OrderCanceller = class _OrderCanceller {
15893
15976
  static DEFAULT_MAX_RECOVERY_RESTARTS = 1;
15894
15977
  static PROOF_FRESHNESS_MAX_RETRIES = 3;
15895
15978
  static PROOF_FRESHNESS_BACKOFF_MS = 500;
15979
+ /**
15980
+ * Gas budget used to size the relayer fee for a cross-chain cancellation
15981
+ * message (the GET response or RefundEscrow POST executed on the source
15982
+ * chain), priced at the source chain's gas price.
15983
+ */
15984
+ static CANCEL_MESSAGE_GAS = 800000n;
15896
15985
  logger = createConsola({
15897
15986
  level: LogLevels.info,
15898
15987
  formatOptions: { columns: 80, colors: true, compact: true, date: false }
@@ -15951,9 +16040,14 @@ var OrderCanceller = class _OrderCanceller {
15951
16040
  timeoutTimestamp: 0n,
15952
16041
  context
15953
16042
  };
15954
- const feeInSourceFeeToken = await convertGasToFeeToken(this.ctx, 400000n, "source", sourceStateMachine);
16043
+ const feeInSourceFeeToken = await convertGasToFeeToken(
16044
+ this.ctx,
16045
+ _OrderCanceller.CANCEL_MESSAGE_GAS,
16046
+ "source",
16047
+ sourceStateMachine
16048
+ );
15955
16049
  const relayerFee = feeInSourceFeeToken * 1005n / 1000n;
15956
- const nativeValue = await this.ctx.source.quoteNative(getRequest, relayerFee);
16050
+ const nativeValue = await this.ctx.source.quoteNative(getRequest, relayerFee) * 101n / 100n;
15957
16051
  return { nativeValue, relayerFee };
15958
16052
  }
15959
16053
  /**
@@ -16212,7 +16306,7 @@ var OrderCanceller = class _OrderCanceller {
16212
16306
  body,
16213
16307
  timeoutTimestamp: 0n
16214
16308
  };
16215
- const nativeValue = await this.ctx.dest.quoteNative(postRequest, relayerFee);
16309
+ const nativeValue = await this.ctx.dest.quoteNative(postRequest, relayerFee) * 101n / 100n;
16216
16310
  return { nativeValue, relayerFee };
16217
16311
  }
16218
16312
  /**
@@ -16542,8 +16636,12 @@ var OrderCanceller = class _OrderCanceller {
16542
16636
  * Converts estimated gas on the source chain into the dest chain's fee token.
16543
16637
  */
16544
16638
  async estimateRelayerFee(sourceChainId, destChainId) {
16545
- const POST_REQUEST_GAS = 400000n;
16546
- const feeInSourceFeeToken = await convertGasToFeeToken(this.ctx, POST_REQUEST_GAS, "source", sourceChainId);
16639
+ const feeInSourceFeeToken = await convertGasToFeeToken(
16640
+ this.ctx,
16641
+ _OrderCanceller.CANCEL_MESSAGE_GAS,
16642
+ "source",
16643
+ sourceChainId
16644
+ );
16547
16645
  const sourceFeeToken = await getFeeToken(this.ctx, sourceChainId, this.ctx.source);
16548
16646
  const destFeeToken = await getFeeToken(this.ctx, destChainId, this.ctx.dest);
16549
16647
  const feeInDestFeeToken = adjustDecimals(feeInSourceFeeToken, sourceFeeToken.decimals, destFeeToken.decimals);
@@ -17302,12 +17400,15 @@ var GasEstimator = class {
17302
17400
  *
17303
17401
  * @param params - Parameters including the order to estimate and optional
17304
17402
  * percentage bumps for `maxPriorityFeePerGas` and `maxFeePerGas`.
17403
+ * @param pricingOptions - Internal fee-pricing policy. Direct estimates use
17404
+ * the default zero gas-price bump; SDK order-fee quotes opt into headroom.
17305
17405
  * @returns A {@link FillOrderEstimate} containing all gas components,
17306
17406
  * EIP-1559 fee values, total cost in wei, and total cost in the source
17307
17407
  * chain's fee token.
17308
17408
  */
17309
- async estimateFillOrder(params) {
17409
+ async estimateFillOrder(params, pricingOptions = {}) {
17310
17410
  const { order } = params;
17411
+ const orderFeeGasPriceBumpPercent = pricingOptions.orderFeeGasPriceBumpPercent ?? 0n;
17311
17412
  const solverPrivateKey = generatePrivateKey();
17312
17413
  const solverAccountAddress = privateKeyToAddress(solverPrivateKey);
17313
17414
  const souceStateMachineId = isHex(order.source) ? hexToString$1(order.source) : order.source;
@@ -17338,7 +17439,12 @@ var GasEstimator = class {
17338
17439
  intentGatewayV2Address,
17339
17440
  entryPointAddress
17340
17441
  }),
17341
- isSameChain ? Promise.resolve({ postRequestFee: 0n, relayerFeeInSourceFeeToken: 0n }) : this.estimateCrossChainFees(sourceFeeToken, destFeeToken, souceStateMachineId)
17442
+ isSameChain ? Promise.resolve({ postRequestFee: 0n, relayerFeeInSourceFeeToken: 0n }) : this.estimateCrossChainFees(
17443
+ sourceFeeToken,
17444
+ destFeeToken,
17445
+ souceStateMachineId,
17446
+ orderFeeGasPriceBumpPercent
17447
+ )
17342
17448
  ]);
17343
17449
  const { viem: stateOverrides, bundler: bundlerStateOverrides } = stateOverridesResult;
17344
17450
  const fillOptions = {
@@ -17503,7 +17609,8 @@ var GasEstimator = class {
17503
17609
  totalGas,
17504
17610
  "dest",
17505
17611
  destStateMachineId,
17506
- gasPrice
17612
+ gasPrice,
17613
+ orderFeeGasPriceBumpPercent
17507
17614
  );
17508
17615
  const totalGasInSourceFeeToken = isSameChain ? totalGasInDestFeeToken : adjustDecimals(totalGasInDestFeeToken, destFeeToken.decimals, sourceFeeToken.decimals);
17509
17616
  const totalGasCostWei = isSameChain ? rawTotalGasCostWei : await convertFeeTokenToWei(this.ctx, totalGasInSourceFeeToken, "source", souceStateMachineId);
@@ -17527,12 +17634,14 @@ var GasEstimator = class {
17527
17634
  * The dispatch is always paid in the fee token — the native rail was
17528
17635
  * removed because it silently drew on a native balance nothing guarantees.
17529
17636
  */
17530
- async estimateCrossChainFees(sourceFeeToken, destFeeToken, sourceChainId) {
17637
+ async estimateCrossChainFees(sourceFeeToken, destFeeToken, sourceChainId, orderFeeGasPriceBumpPercent) {
17531
17638
  const postRequestFeeInSourceFeeToken = await convertGasToFeeToken(
17532
17639
  this.ctx,
17533
17640
  RELAYER_MESSAGE_GAS,
17534
17641
  "source",
17535
- sourceChainId
17642
+ sourceChainId,
17643
+ void 0,
17644
+ orderFeeGasPriceBumpPercent
17536
17645
  );
17537
17646
  const postRequestFeeInDestFeeToken = adjustDecimals(
17538
17647
  postRequestFeeInSourceFeeToken,
@@ -18302,6 +18411,7 @@ function isConfiguredAddress(address) {
18302
18411
  }
18303
18412
 
18304
18413
  // src/protocols/intents/IntentGateway.ts
18414
+ var CROSS_CHAIN_ORDER_FEE_GAS_PRICE_BUMP_PERCENT = 10n;
18305
18415
  var IntentGateway = class _IntentGateway {
18306
18416
  /** EVM chain on which orders are placed and escrowed. */
18307
18417
  source;
@@ -18488,14 +18598,22 @@ var IntentGateway = class _IntentGateway {
18488
18598
  * placement, fee estimation, bid collection, and execution.
18489
18599
  *
18490
18600
  * **Yield/receive protocol:**
18491
- * 1. If `order.fees` is unset or zero, estimates gas on an internal copy and
18492
- * sets same-chain fees to twice the estimate. Cross-chain orders attach
18493
- * (fill gas + a settlement-message uplift of `RELAYER_MESSAGE_GAS`, the
18494
- * same gas budget the solver's relayer fee uses) with a 5% buffer over
18495
- * the whole sum — strictly above the solver's unpadded requirement. The
18496
- * wei cost used for the `value` field receives a 2% buffer.
18497
- * 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, sessionPrivateKey }`.
18498
- * The caller must sign the transaction and pass it back via `gen.next(signedTx)`.
18601
+ * 1. If `order.fees` is unset or zero, prices the fee on an internal copy
18602
+ * via {@link quoteOrderFees}: same-chain fees are twice the fill-gas
18603
+ * estimate without a gas-price bump; cross-chain gas is priced 10% above
18604
+ * the live price before attaching (fill gas + the settlement relayer fee)
18605
+ * with a further 5% buffer over the whole sum — strictly above the solver's
18606
+ * unpadded requirement. Direct solver estimates remain unbumped. The wei
18607
+ * cost used for the `value` field receives a 2% buffer.
18608
+ * 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, nativeFee,
18609
+ * feeTokenAmount, feeTokenAddress, sessionPrivateKey }`. `value` carries
18610
+ * only the order's native-token input amounts; `nativeFee` is the native
18611
+ * amount that funds `order.fees` (`0n` when the caller set `order.fees`);
18612
+ * `feeTokenAmount`/`feeTokenAddress` are the exact fee encoded in `data`
18613
+ * and the source-chain token it is charged in. To pay the fee in native
18614
+ * token, sign the transaction with `value + nativeFee`; with a fee-token
18615
+ * allowance, `value` alone. Pass the signed transaction back via
18616
+ * `gen.next(signedTx)`.
18499
18617
  * 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
18500
18618
  * the `OrderPlaced` event is confirmed.
18501
18619
  * 4. Delegates to {@link OrderExecutor.executeOrder} and forwards all
@@ -18516,33 +18634,33 @@ var IntentGateway = class _IntentGateway {
18516
18634
  */
18517
18635
  async *execute(order, graffiti = DEFAULT_GRAFFITI, options) {
18518
18636
  const executionOrder = { ...order };
18519
- let value;
18637
+ let nativeFee = 0n;
18520
18638
  if (!executionOrder.fees || executionOrder.fees === 0n) {
18521
- const estimate = await this.gasEstimator.estimateFillOrder({
18522
- order: executionOrder,
18639
+ const feesQuote = await this.quoteOrderFees(executionOrder, {
18523
18640
  maxPriorityFeePerGasBumpPercent: options?.maxPriorityFeePerGasBumpPercent,
18524
18641
  maxFeePerGasBumpPercent: options?.maxFeePerGasBumpPercent
18525
18642
  });
18526
- if (estimate.totalGasCostWei === 0n || estimate.totalGasInFeeToken === 0n) {
18527
- throw new Error("Gas estimation failed");
18528
- }
18529
- const isSameChain = this.source.config.stateMachineId === this.dest.config.stateMachineId;
18530
- value = estimate.totalGasCostWei + estimate.totalGasCostWei * 2n / 100n;
18531
- const crossChainFeeBump = isSameChain ? 0n : await convertGasToFeeToken(
18532
- this.ctx,
18533
- RELAYER_MESSAGE_GAS,
18534
- "source",
18535
- this.source.config.stateMachineId
18536
- );
18537
- executionOrder.fees = isSameChain ? estimate.totalGasInFeeToken * 2n : (estimate.totalGasInFeeToken + crossChainFeeBump) * 105n / 100n;
18643
+ nativeFee = feesQuote.nativeValue;
18644
+ executionOrder.fees = feesQuote.fees;
18538
18645
  }
18646
+ const value = executionOrder.inputs.filter((input) => bytes32ToBytes20(input.token) === ADDRESS_ZERO2).reduce((sum, input) => sum + input.amount, 0n);
18539
18647
  const placeOrderGen = this.orderPlacer.placeOrder(executionOrder, graffiti);
18540
18648
  const placeOrderFirst = await placeOrderGen.next();
18541
18649
  if (placeOrderFirst.done) {
18542
18650
  throw new Error("placeOrder generator completed without yielding");
18543
18651
  }
18544
18652
  const { to, data, sessionPrivateKey } = placeOrderFirst.value;
18545
- const signedTransaction = yield { status: "AWAITING_PLACE_ORDER", to, data, value, sessionPrivateKey };
18653
+ const { address: feeTokenAddress } = await getFeeToken(this.ctx, this.source.config.stateMachineId, this.source);
18654
+ const signedTransaction = yield {
18655
+ status: "AWAITING_PLACE_ORDER",
18656
+ to,
18657
+ data,
18658
+ value,
18659
+ nativeFee,
18660
+ sessionPrivateKey,
18661
+ feeTokenAmount: executionOrder.fees,
18662
+ feeTokenAddress
18663
+ };
18546
18664
  const placeOrderSecond = await placeOrderGen.next(signedTransaction);
18547
18665
  if (placeOrderSecond.done === false) {
18548
18666
  throw new Error("placeOrder generator yielded unexpectedly after signing");
@@ -18842,6 +18960,50 @@ var IntentGateway = class _IntentGateway {
18842
18960
  async estimateFillOrder(params) {
18843
18961
  return this.gasEstimator.estimateFillOrder(params);
18844
18962
  }
18963
+ /**
18964
+ * Quotes the solver fee for an order using the same policy {@link execute} /
18965
+ * {@link executeBest} apply when `order.fees` is `0n`.
18966
+ *
18967
+ * Use this before placing to display the fee, or to check what the user can
18968
+ * afford: pay `fees` in the source-chain fee token (check balance and
18969
+ * allowance, then set `order.fees` and submit with `value: 0`), or leave
18970
+ * `order.fees` at `0n` and let the SDK attach `nativeValue` to the placement
18971
+ * transaction (check the native balance).
18972
+ *
18973
+ * @param order - The order to quote. `order.fees` is ignored and not mutated.
18974
+ * Gas prices used to derive cross-chain `fees` receive 10% SDK-only headroom.
18975
+ * Same-chain quotes and direct calls to {@link estimateFillOrder}, including
18976
+ * Simplex solver estimates, remain unbumped.
18977
+ *
18978
+ * @param options - Optional transaction gas-price bump percentages, as in {@link execute}.
18979
+ * @returns An {@link OrderFeesQuote} with the fee-token amount, the native
18980
+ * value for the native rail, and the underlying estimate.
18981
+ * @throws If gas estimation returns zero.
18982
+ */
18983
+ async quoteOrderFees(order, options) {
18984
+ const isSameChain = this.source.config.stateMachineId === this.dest.config.stateMachineId;
18985
+ const estimate = await this.gasEstimator.estimateFillOrder(
18986
+ {
18987
+ order,
18988
+ maxPriorityFeePerGasBumpPercent: options?.maxPriorityFeePerGasBumpPercent,
18989
+ maxFeePerGasBumpPercent: options?.maxFeePerGasBumpPercent
18990
+ },
18991
+ {
18992
+ orderFeeGasPriceBumpPercent: isSameChain ? 0n : CROSS_CHAIN_ORDER_FEE_GAS_PRICE_BUMP_PERCENT
18993
+ }
18994
+ );
18995
+ if (estimate.totalGasCostWei === 0n || estimate.totalGasInFeeToken === 0n) {
18996
+ throw new Error("Gas estimation failed");
18997
+ }
18998
+ const fees = isSameChain ? estimate.totalGasInFeeToken * 2n : (estimate.totalGasInFeeToken + estimate.relayerFeeInSourceFeeToken) * 105n / 100n;
18999
+ const { address: feeToken } = await this.source.getFeeTokenWithDecimals();
19000
+ return {
19001
+ fees,
19002
+ nativeValue: estimate.totalGasCostWei + estimate.totalGasCostWei * 2n / 100n,
19003
+ feeToken,
19004
+ estimate
19005
+ };
19006
+ }
18845
19007
  /**
18846
19008
  * Encodes a list of calls into ERC-7821 `execute` calldata using
18847
19009
  * single-batch mode.
@@ -18968,6 +19130,44 @@ var IntentGateway = class _IntentGateway {
18968
19130
  }
18969
19131
  }
18970
19132
  };
19133
+ var FILL_ORDER_ABI = IntentGatewayV2_default.ABI;
19134
+ var DECLARATION_VERSION = 1;
19135
+ var MAX_DECLARED_CHAINS = 255;
19136
+ function encodeAcceptedSourceChains(chains2) {
19137
+ if (chains2.length > MAX_DECLARED_CHAINS) {
19138
+ throw new Error(`Cannot declare more than ${MAX_DECLARED_CHAINS} source chains`);
19139
+ }
19140
+ const bytes = [DECLARATION_VERSION, chains2.length];
19141
+ for (const chain of chains2) {
19142
+ const encoded = stringToU8a(chain);
19143
+ if (encoded.length === 0 || encoded.length > 255) {
19144
+ throw new Error(`Invalid state machine id in source chain declaration: ${chain}`);
19145
+ }
19146
+ bytes.push(encoded.length, ...encoded);
19147
+ }
19148
+ return u8aToHex(new Uint8Array(bytes));
19149
+ }
19150
+ function decodeAcceptedSourceChains(paymasterAndData) {
19151
+ if (!paymasterAndData || !isHex$1(paymasterAndData)) return null;
19152
+ const bytes = hexToU8a(paymasterAndData);
19153
+ if (bytes.length < 2 || bytes[0] !== DECLARATION_VERSION) return null;
19154
+ const count = bytes[1];
19155
+ const chains2 = [];
19156
+ let offset = 2;
19157
+ for (let entry = 0; entry < count; entry++) {
19158
+ if (offset >= bytes.length) return null;
19159
+ const length = bytes[offset];
19160
+ offset += 1;
19161
+ if (length === 0 || offset + length > bytes.length) return null;
19162
+ chains2.push(u8aToString(bytes.subarray(offset, offset + length)));
19163
+ offset += length;
19164
+ }
19165
+ if (offset !== bytes.length) return null;
19166
+ return chains2;
19167
+ }
19168
+ FILL_ORDER_ABI.find(
19169
+ (item) => item?.type === "function" && item?.name === "fillOrder"
19170
+ )?.inputs?.[0];
18971
19171
  var TokenGateway = class {
18972
19172
  source;
18973
19173
  dest;
@@ -23438,6 +23638,6 @@ async function teleportDot(param_) {
23438
23638
  return stream;
23439
23639
  }
23440
23640
 
23441
- export { ADDRESS_ZERO2 as ADDRESS_ZERO, BundlerMethod, ChainConfigService, Chains, CryptoUtils, DEFAULT_ADDRESS, DEFAULT_GRAFFITI, DOMAIN_TYPEHASH, DUMMY_PRIVATE_KEY, ERC20Method, ERC7821_BATCH_MODE, EvmChain, ABI as EvmHostABI, EvmLanguage, HyperClientStatus, HyperFungibleToken, HyperFungibleTokenABI, IntentGateway, ABI3 as IntentGatewayABI, IntentOrderStatus, IntentsCoprocessor, InvalidPhantomSnapshotError, IsmpClient, MOCK_ADDRESS, ORDER_V2_PARAM_TYPE, OrderStatus, OrderStatusChecker, PACKED_USEROP_TYPEHASH, PLACE_ORDER_SELECTOR, PhantomSnapshotUnavailableError, PharosChain, PolkadotHubChain, REQUEST_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, RESPONSE_COMMITMENTS_SLOT, RESPONSE_RECEIPTS_SLOT, RequestKind, RequestStatus, SELECT_SOLVER_TYPEHASH, STATE_COMMITMENTS_SLOT, SubstrateChain, Swap, TESTNET_CHAINS, TeleportStatus, TimeoutStatus, TokenGateway, TronChain, USE_ETHERSCAN_CHAINS, UnsupportedIntentQuotePairError, UnsupportedIntentQuoteStrategyError, WrappedHyperFungibleTokenABI, __test, adjustDecimals, bytes20ToBytes32, bytes32ToBytes20, calculateAllowanceMappingLocation, calculateBalanceMappingLocation, chainConfigs, constructRedeemEscrowRequestBody, constructRefundEscrowRequestBody, convertCodecToIGetRequest, convertCodecToIProof, convertIGetRequestToCodec, convertIProofToCodec, convertStateIdToStateMachineId, convertStateMachineEnumToString, convertStateMachineIdToEnum, createEvmChain, createQueryClient, decodeERC7821ExecuteBatch, decodeUserOpScale, encodeERC7821ExecuteBatch, encodeISMPMessage, encodeStateMachineId, encodeUserOpScale, encodeWithdrawalRequest, estimateGasForPost, fetchPrice, fetchSourceProof, generateRootWithProof, getChainId, getConfigByStateMachineId, getContractCallInput, getContractCallInputs, getGasPriceFromEtherscan, getOrFetchStorageSlot, getOrderPlacedFromTx, getPostRequestEventFromTx, getPostResponseEventFromTx, getRequestCommitment, getStateCommitmentFieldSlot, getStateCommitmentSlot, getStorageSlot, getViemChain, hexToString, hyperbridgeAddress, maxBigInt, normalizeAddressForEvmBytes32, normalizeAddressForStateMachine, normalizeEvmAddress, normalizeEvmChainId, normalizeStateMachineId, orderCommitment, parseStateMachineId, pharosAtlantic, pharosMainnet, polkadotAssetHubPaseo, polkadotHubMainnet, postRequestCommitment, queryAssetTeleported, queryGetRequest, queryPostRequest, quoteUniswap, requestCommitmentKey, responseCommitmentKey, retryPromise, teleport, teleportDot, transformOrderForContract, tronChainIds, tronNile };
23641
+ export { ADDRESS_ZERO2 as ADDRESS_ZERO, BundlerMethod, ChainConfigService, Chains, CryptoUtils, DEFAULT_ADDRESS, DEFAULT_GRAFFITI, DOMAIN_TYPEHASH, DUMMY_PRIVATE_KEY, ERC20Method, ERC7821_BATCH_MODE, EvmChain, ABI as EvmHostABI, EvmLanguage, HyperClientStatus, HyperFungibleToken, HyperFungibleTokenABI, IntentGateway, ABI3 as IntentGatewayABI, IntentOrderStatus, IntentsCoprocessor, InvalidPhantomSnapshotError, IsmpClient, MOCK_ADDRESS, ORDER_V2_PARAM_TYPE, OrderStatus, OrderStatusChecker, PACKED_USEROP_TYPEHASH, PLACE_ORDER_SELECTOR, PhantomSnapshotUnavailableError, PharosChain, PolkadotHubChain, REQUEST_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, RESPONSE_COMMITMENTS_SLOT, RESPONSE_RECEIPTS_SLOT, RequestKind, RequestStatus, SELECT_SOLVER_TYPEHASH, STATE_COMMITMENTS_SLOT, SubstrateChain, Swap, TESTNET_CHAINS, TeleportStatus, TimeoutStatus, TokenGateway, TronChain, USE_ETHERSCAN_CHAINS, UnsupportedIntentQuotePairError, UnsupportedIntentQuoteStrategyError, WrappedHyperFungibleTokenABI, __test, adjustDecimals, bytes20ToBytes32, bytes32ToBytes20, calculateAllowanceMappingLocation, calculateBalanceMappingLocation, chainConfigs, constructRedeemEscrowRequestBody, constructRefundEscrowRequestBody, convertCodecToIGetRequest, convertCodecToIProof, convertIGetRequestToCodec, convertIProofToCodec, convertStateIdToStateMachineId, convertStateMachineEnumToString, convertStateMachineIdToEnum, createEvmChain, createQueryClient, decodeAcceptedSourceChains, decodeERC7821ExecuteBatch, decodeUserOpScale, encodeAcceptedSourceChains, encodeERC7821ExecuteBatch, encodeISMPMessage, encodeStateMachineId, encodeUserOpScale, encodeWithdrawalRequest, estimateGasForPost, fetchPrice, fetchSourceProof, generateRootWithProof, getChainId, getConfigByStateMachineId, getContractCallInput, getContractCallInputs, getGasPriceFromEtherscan, getOrFetchStorageSlot, getOrderPlacedFromTx, getPostRequestEventFromTx, getPostResponseEventFromTx, getRequestCommitment, getStateCommitmentFieldSlot, getStateCommitmentSlot, getStorageSlot, getViemChain, hexToString, hyperbridgeAddress, maxBigInt, normalizeAddressForEvmBytes32, normalizeAddressForStateMachine, normalizeEvmAddress, normalizeEvmChainId, normalizeStateMachineId, orderCommitment, parseStateMachineId, pharosAtlantic, pharosMainnet, polkadotAssetHubPaseo, polkadotHubMainnet, postRequestCommitment, queryAssetTeleported, queryGetRequest, queryPostRequest, quoteUniswap, requestCommitmentKey, responseCommitmentKey, retryPromise, teleport, teleportDot, transformOrderForContract, tronChainIds, tronNile };
23442
23642
  //# sourceMappingURL=index.js.map
23443
23643
  //# sourceMappingURL=index.js.map