@hyperbridge/sdk 2.6.1 → 2.7.2

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.
@@ -2693,7 +2693,8 @@ var chainConfigs = {
2693
2693
  ZARP: "0xb755506531786C8aC63B756BaB1ac387bACB0C04",
2694
2694
  EURC: "0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c",
2695
2695
  XSGD: "0x70e8dE73cE538DA2bEEd35d14187F6959a8ecA96",
2696
- TRYB: "0x2C537E5624e4af88A7ae4060C022609376C8D0EB"
2696
+ TRYB: "0x2C537E5624e4af88A7ae4060C022609376C8D0EB",
2697
+ USDR: "0x9623DfB044D5612Ce0c0F1606973CCAEFd03CD05"
2697
2698
  },
2698
2699
  tokenDecimals: {
2699
2700
  USDC: 6,
@@ -2732,6 +2733,10 @@ var chainConfigs = {
2732
2733
  consensusStateId: "ETH0",
2733
2734
  coingeckoId: "ethereum",
2734
2735
  layerZeroEid: 30101,
2736
+ erc4626Vaults: [
2737
+ { label: "Aave stataUSDC", address: "0xD4fa2D31b7968E448877f69A96DE69f5de8cD23E", asset: "USDC" },
2738
+ { label: "Aave stataUSDT", address: "0x7Bc3485026Ac48b6cf9BaF0A377477Fff5703Af8", asset: "USDT" }
2739
+ ],
2735
2740
  popularTokens: [
2736
2741
  "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
2737
2742
  "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
@@ -2786,6 +2791,10 @@ var chainConfigs = {
2786
2791
  defaultRpcUrl: "https://binance.llamarpc.com",
2787
2792
  consensusStateId: "BSC0",
2788
2793
  coingeckoId: "binance-smart-chain",
2794
+ erc4626Vaults: [
2795
+ { label: "Aave stataUSDC", address: "0x3906cDdfb781f02B21f21BD81ed7Fd8DC37075E1", asset: "USDC" },
2796
+ { label: "Aave stataUSDT", address: "0x0471D185cc7Be61E154277cAB2396cD397663da6", asset: "USDT" }
2797
+ ],
2789
2798
  popularTokens: [
2790
2799
  "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82",
2791
2800
  "0x000Ae314E2A2172a039B26378814C252734f556A",
@@ -2845,6 +2854,10 @@ var chainConfigs = {
2845
2854
  consensusStateId: "ETH0",
2846
2855
  coingeckoId: "arbitrum-one",
2847
2856
  layerZeroEid: 30110,
2857
+ erc4626Vaults: [
2858
+ { label: "Aave stataUSDC", address: "0x7F6501d3B98eE91f9b9535E4b0ac710Fb0f9e0bc", asset: "USDC" },
2859
+ { label: "Aave stataUSDT", address: "0xa6D12574eFB239FC1D2099732bd8b5dC6306897F", asset: "USDT" }
2860
+ ],
2848
2861
  popularTokens: [
2849
2862
  "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
2850
2863
  "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
@@ -2865,7 +2878,8 @@ var chainConfigs = {
2865
2878
  EXT: "0x0e668E5127087e236578893a0e01E41837A28469",
2866
2879
  cNGN: "0x46C85152bFe9f96829aA94755D9f915F9B10EF5F",
2867
2880
  ZARP: "0xb755506531786C8aC63B756BaB1ac387bACB0C04",
2868
- EURC: "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"
2881
+ EURC: "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42",
2882
+ USDR: "0x3B5F2810fB2168FfA9C73160F97BF9f2461fFa5c"
2869
2883
  },
2870
2884
  tokenDecimals: {
2871
2885
  USDC: 6,
@@ -2907,6 +2921,10 @@ var chainConfigs = {
2907
2921
  coingeckoId: "base",
2908
2922
  layerZeroEid: 30184,
2909
2923
  uniswapV4Pools: [{ tokens: ["USDC", "cNGN"], fee: 1500, tickSpacing: 30 }],
2924
+ erc4626Vaults: [
2925
+ { label: "Aave stataUSDC", address: "0xC768c589647798a6EE01A91FdE98EF2ed046DBD6", asset: "USDC" },
2926
+ { label: "Yield Bearing cNGN", address: "0xa82A3531021317240Fb32E67f9c7bC091F737D3b", asset: "cNGN" }
2927
+ ],
2910
2928
  popularTokens: [
2911
2929
  "0x4200000000000000000000000000000000000006",
2912
2930
  "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
@@ -2927,7 +2945,8 @@ var chainConfigs = {
2927
2945
  EXT: "0x7C8c11ADb8EF7cd3CFa718008Ea048445C6E7209",
2928
2946
  cNGN: "0x52828daa48C1a9A06F37500882b42daf0bE04C3B",
2929
2947
  ZARP: "0xb755506531786C8aC63B756BaB1ac387bACB0C04",
2930
- XSGD: "0xDC3326e71D45186F113a2F448984CA0e8D201995"
2948
+ XSGD: "0xDC3326e71D45186F113a2F448984CA0e8D201995",
2949
+ USDR: "0x3B5F2810fB2168FfA9C73160F97BF9f2461fFa5c"
2931
2950
  },
2932
2951
  tokenDecimals: {
2933
2952
  USDC: 6,
@@ -2967,6 +2986,10 @@ var chainConfigs = {
2967
2986
  consensusStateId: "POLY",
2968
2987
  coingeckoId: "polygon-pos",
2969
2988
  layerZeroEid: 30109,
2989
+ erc4626Vaults: [
2990
+ { label: "Aave stataUSDC", address: "0x79261231698B26Ed9085b59ae89d59843Ae925a8", asset: "USDC" },
2991
+ { label: "Aave stataUSDT", address: "0x2eaD203C5C1C00612B1DdbBb20e4180dA822d6ff", asset: "USDT" }
2992
+ ],
2970
2993
  popularTokens: [
2971
2994
  "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",
2972
2995
  "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
@@ -3013,7 +3036,7 @@ var chainConfigs = {
3013
3036
  WETH: "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9",
3014
3037
  //wmatic, change it to wpol
3015
3038
  DAI: "0x0000000000000000000000000000000000000000",
3016
- USDC: "0x693b854d6965ffeaae21c74049dea644b56fcacb",
3039
+ USDC: "0xBE97E73126D66188d72fbF99029126D0340a7f18",
3017
3040
  USDT: "0x0000000000000000000000000000000000000000"
3018
3041
  },
3019
3042
  tokenDecimals: {
@@ -3022,7 +3045,7 @@ var chainConfigs = {
3022
3045
  },
3023
3046
  tokenStorageSlots: {
3024
3047
  USDT: { balanceSlot: 0, allowanceSlot: 1 },
3025
- USDC: { balanceSlot: 1, allowanceSlot: 2 }
3048
+ USDC: { balanceSlot: 0, allowanceSlot: 1 }
3026
3049
  },
3027
3050
  addresses: {
3028
3051
  IntentGateway: "0x6CF42FA9BecbC5b6a26884964956b113530f7cFA",
@@ -5188,6 +5211,19 @@ var ChainConfigService = class {
5188
5211
  getExtDecimals(chain) {
5189
5212
  return this.getConfig(chain)?.tokenDecimals?.EXT;
5190
5213
  }
5214
+ /** Configured exotic (non-USD) tokens on a chain, for selection UIs. EXT is a test asset and is not offered. */
5215
+ getKnownExoticTokens(chain) {
5216
+ const config = this.getConfig(chain);
5217
+ const tokens = [];
5218
+ if (config?.assets?.cNGN) {
5219
+ tokens.push({ symbol: "cNGN", address: config.assets.cNGN, decimals: config.tokenDecimals?.cNGN });
5220
+ }
5221
+ return tokens;
5222
+ }
5223
+ /** Known ERC-4626 treasury vaults on a chain, for selection UIs. */
5224
+ getKnownVaults(chain) {
5225
+ return this.getConfig(chain)?.erc4626Vaults ?? [];
5226
+ }
5191
5227
  getChainId(chain) {
5192
5228
  return this.getConfig(chain)?.chainId ?? 0;
5193
5229
  }
@@ -7477,17 +7513,30 @@ var SubstrateChain = class _SubstrateChain {
7477
7513
  rotationMap.set(BigInt(setId.toString()), BigInt(height.toString()));
7478
7514
  }
7479
7515
  const proofs = [];
7480
- let epoch = currentEpoch - 1n;
7516
+ let epoch = currentEpoch + 1n;
7481
7517
  while (rotationMap.has(epoch)) {
7482
- const height = rotationMap.get(epoch);
7483
- const key = beefyOffchainKey(height);
7484
- const proof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", key]);
7518
+ const key = rotationOffchainKey(epoch);
7519
+ let proof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", key]);
7520
+ if (!proof) {
7521
+ const legacyKey = messagingOffchainKey(rotationMap.get(epoch));
7522
+ proof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", legacyKey]);
7523
+ }
7485
7524
  if (!proof) return void 0;
7486
7525
  proofs.push(proof);
7487
7526
  epoch++;
7488
7527
  }
7489
- const messagingKey = beefyOffchainKey(lastProvenHeight);
7490
- const messagingProof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", messagingKey]);
7528
+ const messagingKey = messagingOffchainKey(lastProvenHeight);
7529
+ let messagingProof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", messagingKey]);
7530
+ if (!messagingProof) {
7531
+ for (const [setId, height] of rotationMap) {
7532
+ if (height !== lastProvenHeight) continue;
7533
+ messagingProof = await this.rpcClient.call("offchain_localStorageGet", [
7534
+ "PERSISTENT",
7535
+ rotationOffchainKey(setId)
7536
+ ]);
7537
+ break;
7538
+ }
7539
+ }
7491
7540
  if (!messagingProof) return void 0;
7492
7541
  proofs.push(messagingProof);
7493
7542
  return { proofs, provenHeight: lastProvenHeight };
@@ -7504,11 +7553,17 @@ var SubstrateChain = class _SubstrateChain {
7504
7553
  throw new Error(`${name} not found in runtime`);
7505
7554
  }
7506
7555
  };
7507
- function beefyOffchainKey(provenHeight) {
7508
- const prefix = new TextEncoder().encode("beefy_consensus_proofs::");
7509
- const heightBytes = new Uint8Array(8);
7510
- new DataView(heightBytes.buffer).setBigUint64(0, provenHeight, false);
7511
- return viem.toHex(new Uint8Array([...prefix, ...heightBytes]));
7556
+ function beefyOffchainKey(prefix, id) {
7557
+ const prefixBytes = new TextEncoder().encode(prefix);
7558
+ const idBytes = new Uint8Array(8);
7559
+ new DataView(idBytes.buffer).setBigUint64(0, id, false);
7560
+ return viem.toHex(new Uint8Array([...prefixBytes, ...idBytes]));
7561
+ }
7562
+ function messagingOffchainKey(provenHeight) {
7563
+ return beefyOffchainKey("beefy_consensus_proofs::", provenHeight);
7564
+ }
7565
+ function rotationOffchainKey(setId) {
7566
+ return beefyOffchainKey("beefy_consensus_proofs::rotation::", setId);
7512
7567
  }
7513
7568
  function requestCommitmentStorageKey(key) {
7514
7569
  const prefix = new TextEncoder().encode("RequestCommitments");
@@ -15396,14 +15451,21 @@ function orderCommitment(order) {
15396
15451
  const encoded = viem.encodeAbiParameters([orderType], [transformOrderForContract(order)]);
15397
15452
  return viem.keccak256(encoded);
15398
15453
  }
15399
- async function convertGasToFeeToken(ctx, gasEstimate, gasEstimateIn, evmChainID, gasPriceOverride) {
15454
+ function bumpGasPrice(gasPrice, bumpPercent) {
15455
+ if (bumpPercent < 0n) {
15456
+ throw new Error("Gas price bump percent cannot be negative");
15457
+ }
15458
+ return (gasPrice * (100n + bumpPercent) + 99n) / 100n;
15459
+ }
15460
+ async function convertGasToFeeToken(ctx, gasEstimate, gasEstimateIn, evmChainID, gasPriceOverride, gasPriceBumpPercent = 0n) {
15400
15461
  if (TESTNET_CHAINS.has(evmChainID)) return 1n;
15401
15462
  const chain = ctx[gasEstimateIn];
15402
15463
  const client = chain.client;
15403
- const gasPrice = gasPriceOverride ?? await retryPromise(() => client.getGasPrice(), {
15464
+ const baseGasPrice = gasPriceOverride ?? await retryPromise(() => client.getGasPrice(), {
15404
15465
  maxRetries: 3,
15405
15466
  backoffMs: 250
15406
15467
  });
15468
+ const gasPrice = bumpGasPrice(baseGasPrice, gasPriceBumpPercent);
15407
15469
  const gasCostInWei = gasEstimate * gasPrice;
15408
15470
  const wethAddr = chain.configService.getWrappedNativeAssetWithDecimals(evmChainID).asset;
15409
15471
  const feeToken = await getFeeToken(ctx, evmChainID, chain);
@@ -15904,6 +15966,12 @@ var OrderCanceller = class _OrderCanceller {
15904
15966
  static DEFAULT_MAX_RECOVERY_RESTARTS = 1;
15905
15967
  static PROOF_FRESHNESS_MAX_RETRIES = 3;
15906
15968
  static PROOF_FRESHNESS_BACKOFF_MS = 500;
15969
+ /**
15970
+ * Gas budget used to size the relayer fee for a cross-chain cancellation
15971
+ * message (the GET response or RefundEscrow POST executed on the source
15972
+ * chain), priced at the source chain's gas price.
15973
+ */
15974
+ static CANCEL_MESSAGE_GAS = 800000n;
15907
15975
  logger = consola.createConsola({
15908
15976
  level: consola.LogLevels.info,
15909
15977
  formatOptions: { columns: 80, colors: true, compact: true, date: false }
@@ -15962,9 +16030,14 @@ var OrderCanceller = class _OrderCanceller {
15962
16030
  timeoutTimestamp: 0n,
15963
16031
  context
15964
16032
  };
15965
- const feeInSourceFeeToken = await convertGasToFeeToken(this.ctx, 400000n, "source", sourceStateMachine);
16033
+ const feeInSourceFeeToken = await convertGasToFeeToken(
16034
+ this.ctx,
16035
+ _OrderCanceller.CANCEL_MESSAGE_GAS,
16036
+ "source",
16037
+ sourceStateMachine
16038
+ );
15966
16039
  const relayerFee = feeInSourceFeeToken * 1005n / 1000n;
15967
- const nativeValue = await this.ctx.source.quoteNative(getRequest, relayerFee);
16040
+ const nativeValue = await this.ctx.source.quoteNative(getRequest, relayerFee) * 101n / 100n;
15968
16041
  return { nativeValue, relayerFee };
15969
16042
  }
15970
16043
  /**
@@ -16223,7 +16296,7 @@ var OrderCanceller = class _OrderCanceller {
16223
16296
  body,
16224
16297
  timeoutTimestamp: 0n
16225
16298
  };
16226
- const nativeValue = await this.ctx.dest.quoteNative(postRequest, relayerFee);
16299
+ const nativeValue = await this.ctx.dest.quoteNative(postRequest, relayerFee) * 101n / 100n;
16227
16300
  return { nativeValue, relayerFee };
16228
16301
  }
16229
16302
  /**
@@ -16553,8 +16626,12 @@ var OrderCanceller = class _OrderCanceller {
16553
16626
  * Converts estimated gas on the source chain into the dest chain's fee token.
16554
16627
  */
16555
16628
  async estimateRelayerFee(sourceChainId, destChainId) {
16556
- const POST_REQUEST_GAS = 400000n;
16557
- const feeInSourceFeeToken = await convertGasToFeeToken(this.ctx, POST_REQUEST_GAS, "source", sourceChainId);
16629
+ const feeInSourceFeeToken = await convertGasToFeeToken(
16630
+ this.ctx,
16631
+ _OrderCanceller.CANCEL_MESSAGE_GAS,
16632
+ "source",
16633
+ sourceChainId
16634
+ );
16558
16635
  const sourceFeeToken = await getFeeToken(this.ctx, sourceChainId, this.ctx.source);
16559
16636
  const destFeeToken = await getFeeToken(this.ctx, destChainId, this.ctx.dest);
16560
16637
  const feeInDestFeeToken = adjustDecimals(feeInSourceFeeToken, sourceFeeToken.decimals, destFeeToken.decimals);
@@ -17313,12 +17390,15 @@ var GasEstimator = class {
17313
17390
  *
17314
17391
  * @param params - Parameters including the order to estimate and optional
17315
17392
  * percentage bumps for `maxPriorityFeePerGas` and `maxFeePerGas`.
17393
+ * @param pricingOptions - Internal fee-pricing policy. Direct estimates use
17394
+ * the default zero gas-price bump; SDK order-fee quotes opt into headroom.
17316
17395
  * @returns A {@link FillOrderEstimate} containing all gas components,
17317
17396
  * EIP-1559 fee values, total cost in wei, and total cost in the source
17318
17397
  * chain's fee token.
17319
17398
  */
17320
- async estimateFillOrder(params) {
17399
+ async estimateFillOrder(params, pricingOptions = {}) {
17321
17400
  const { order } = params;
17401
+ const orderFeeGasPriceBumpPercent = pricingOptions.orderFeeGasPriceBumpPercent ?? 0n;
17322
17402
  const solverPrivateKey = accounts.generatePrivateKey();
17323
17403
  const solverAccountAddress = accounts.privateKeyToAddress(solverPrivateKey);
17324
17404
  const souceStateMachineId = viem.isHex(order.source) ? viem.hexToString(order.source) : order.source;
@@ -17349,7 +17429,12 @@ var GasEstimator = class {
17349
17429
  intentGatewayV2Address,
17350
17430
  entryPointAddress
17351
17431
  }),
17352
- isSameChain ? Promise.resolve({ postRequestFee: 0n, relayerFeeInSourceFeeToken: 0n }) : this.estimateCrossChainFees(sourceFeeToken, destFeeToken, souceStateMachineId)
17432
+ isSameChain ? Promise.resolve({ postRequestFee: 0n, relayerFeeInSourceFeeToken: 0n }) : this.estimateCrossChainFees(
17433
+ sourceFeeToken,
17434
+ destFeeToken,
17435
+ souceStateMachineId,
17436
+ orderFeeGasPriceBumpPercent
17437
+ )
17353
17438
  ]);
17354
17439
  const { viem: stateOverrides, bundler: bundlerStateOverrides } = stateOverridesResult;
17355
17440
  const fillOptions = {
@@ -17514,7 +17599,8 @@ var GasEstimator = class {
17514
17599
  totalGas,
17515
17600
  "dest",
17516
17601
  destStateMachineId,
17517
- gasPrice
17602
+ gasPrice,
17603
+ orderFeeGasPriceBumpPercent
17518
17604
  );
17519
17605
  const totalGasInSourceFeeToken = isSameChain ? totalGasInDestFeeToken : adjustDecimals(totalGasInDestFeeToken, destFeeToken.decimals, sourceFeeToken.decimals);
17520
17606
  const totalGasCostWei = isSameChain ? rawTotalGasCostWei : await convertFeeTokenToWei(this.ctx, totalGasInSourceFeeToken, "source", souceStateMachineId);
@@ -17538,12 +17624,14 @@ var GasEstimator = class {
17538
17624
  * The dispatch is always paid in the fee token — the native rail was
17539
17625
  * removed because it silently drew on a native balance nothing guarantees.
17540
17626
  */
17541
- async estimateCrossChainFees(sourceFeeToken, destFeeToken, sourceChainId) {
17627
+ async estimateCrossChainFees(sourceFeeToken, destFeeToken, sourceChainId, orderFeeGasPriceBumpPercent) {
17542
17628
  const postRequestFeeInSourceFeeToken = await convertGasToFeeToken(
17543
17629
  this.ctx,
17544
17630
  RELAYER_MESSAGE_GAS,
17545
17631
  "source",
17546
- sourceChainId
17632
+ sourceChainId,
17633
+ void 0,
17634
+ orderFeeGasPriceBumpPercent
17547
17635
  );
17548
17636
  const postRequestFeeInDestFeeToken = adjustDecimals(
17549
17637
  postRequestFeeInSourceFeeToken,
@@ -18313,6 +18401,7 @@ function isConfiguredAddress(address) {
18313
18401
  }
18314
18402
 
18315
18403
  // src/protocols/intents/IntentGateway.ts
18404
+ var CROSS_CHAIN_ORDER_FEE_GAS_PRICE_BUMP_PERCENT = 10n;
18316
18405
  var IntentGateway = class _IntentGateway {
18317
18406
  /** EVM chain on which orders are placed and escrowed. */
18318
18407
  source;
@@ -18499,14 +18588,22 @@ var IntentGateway = class _IntentGateway {
18499
18588
  * placement, fee estimation, bid collection, and execution.
18500
18589
  *
18501
18590
  * **Yield/receive protocol:**
18502
- * 1. If `order.fees` is unset or zero, estimates gas on an internal copy and
18503
- * sets same-chain fees to twice the estimate. Cross-chain orders attach
18504
- * (fill gas + a settlement-message uplift of `RELAYER_MESSAGE_GAS`, the
18505
- * same gas budget the solver's relayer fee uses) with a 5% buffer over
18506
- * the whole sum — strictly above the solver's unpadded requirement. The
18507
- * wei cost used for the `value` field receives a 2% buffer.
18508
- * 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, sessionPrivateKey }`.
18509
- * The caller must sign the transaction and pass it back via `gen.next(signedTx)`.
18591
+ * 1. If `order.fees` is unset or zero, prices the fee on an internal copy
18592
+ * via {@link quoteOrderFees}: same-chain fees are twice the fill-gas
18593
+ * estimate without a gas-price bump; cross-chain gas is priced 10% above
18594
+ * the live price before attaching (fill gas + the settlement relayer fee)
18595
+ * with a further 5% buffer over the whole sum — strictly above the solver's
18596
+ * unpadded requirement. Direct solver estimates remain unbumped. The wei
18597
+ * cost used for the `value` field receives a 2% buffer.
18598
+ * 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, nativeFee,
18599
+ * feeTokenAmount, feeTokenAddress, sessionPrivateKey }`. `value` carries
18600
+ * only the order's native-token input amounts; `nativeFee` is the native
18601
+ * amount that funds `order.fees` (`0n` when the caller set `order.fees`);
18602
+ * `feeTokenAmount`/`feeTokenAddress` are the exact fee encoded in `data`
18603
+ * and the source-chain token it is charged in. To pay the fee in native
18604
+ * token, sign the transaction with `value + nativeFee`; with a fee-token
18605
+ * allowance, `value` alone. Pass the signed transaction back via
18606
+ * `gen.next(signedTx)`.
18510
18607
  * 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
18511
18608
  * the `OrderPlaced` event is confirmed.
18512
18609
  * 4. Delegates to {@link OrderExecutor.executeOrder} and forwards all
@@ -18527,33 +18624,33 @@ var IntentGateway = class _IntentGateway {
18527
18624
  */
18528
18625
  async *execute(order, graffiti = DEFAULT_GRAFFITI, options) {
18529
18626
  const executionOrder = { ...order };
18530
- let value;
18627
+ let nativeFee = 0n;
18531
18628
  if (!executionOrder.fees || executionOrder.fees === 0n) {
18532
- const estimate = await this.gasEstimator.estimateFillOrder({
18533
- order: executionOrder,
18629
+ const feesQuote = await this.quoteOrderFees(executionOrder, {
18534
18630
  maxPriorityFeePerGasBumpPercent: options?.maxPriorityFeePerGasBumpPercent,
18535
18631
  maxFeePerGasBumpPercent: options?.maxFeePerGasBumpPercent
18536
18632
  });
18537
- if (estimate.totalGasCostWei === 0n || estimate.totalGasInFeeToken === 0n) {
18538
- throw new Error("Gas estimation failed");
18539
- }
18540
- const isSameChain = this.source.config.stateMachineId === this.dest.config.stateMachineId;
18541
- value = estimate.totalGasCostWei + estimate.totalGasCostWei * 2n / 100n;
18542
- const crossChainFeeBump = isSameChain ? 0n : await convertGasToFeeToken(
18543
- this.ctx,
18544
- RELAYER_MESSAGE_GAS,
18545
- "source",
18546
- this.source.config.stateMachineId
18547
- );
18548
- executionOrder.fees = isSameChain ? estimate.totalGasInFeeToken * 2n : (estimate.totalGasInFeeToken + crossChainFeeBump) * 105n / 100n;
18633
+ nativeFee = feesQuote.nativeValue;
18634
+ executionOrder.fees = feesQuote.fees;
18549
18635
  }
18636
+ const value = executionOrder.inputs.filter((input) => bytes32ToBytes20(input.token) === ADDRESS_ZERO2).reduce((sum, input) => sum + input.amount, 0n);
18550
18637
  const placeOrderGen = this.orderPlacer.placeOrder(executionOrder, graffiti);
18551
18638
  const placeOrderFirst = await placeOrderGen.next();
18552
18639
  if (placeOrderFirst.done) {
18553
18640
  throw new Error("placeOrder generator completed without yielding");
18554
18641
  }
18555
18642
  const { to, data, sessionPrivateKey } = placeOrderFirst.value;
18556
- const signedTransaction = yield { status: "AWAITING_PLACE_ORDER", to, data, value, sessionPrivateKey };
18643
+ const { address: feeTokenAddress } = await getFeeToken(this.ctx, this.source.config.stateMachineId, this.source);
18644
+ const signedTransaction = yield {
18645
+ status: "AWAITING_PLACE_ORDER",
18646
+ to,
18647
+ data,
18648
+ value,
18649
+ nativeFee,
18650
+ sessionPrivateKey,
18651
+ feeTokenAmount: executionOrder.fees,
18652
+ feeTokenAddress
18653
+ };
18557
18654
  const placeOrderSecond = await placeOrderGen.next(signedTransaction);
18558
18655
  if (placeOrderSecond.done === false) {
18559
18656
  throw new Error("placeOrder generator yielded unexpectedly after signing");
@@ -18853,6 +18950,50 @@ var IntentGateway = class _IntentGateway {
18853
18950
  async estimateFillOrder(params) {
18854
18951
  return this.gasEstimator.estimateFillOrder(params);
18855
18952
  }
18953
+ /**
18954
+ * Quotes the solver fee for an order using the same policy {@link execute} /
18955
+ * {@link executeBest} apply when `order.fees` is `0n`.
18956
+ *
18957
+ * Use this before placing to display the fee, or to check what the user can
18958
+ * afford: pay `fees` in the source-chain fee token (check balance and
18959
+ * allowance, then set `order.fees` and submit with `value: 0`), or leave
18960
+ * `order.fees` at `0n` and let the SDK attach `nativeValue` to the placement
18961
+ * transaction (check the native balance).
18962
+ *
18963
+ * @param order - The order to quote. `order.fees` is ignored and not mutated.
18964
+ * Gas prices used to derive cross-chain `fees` receive 10% SDK-only headroom.
18965
+ * Same-chain quotes and direct calls to {@link estimateFillOrder}, including
18966
+ * Simplex solver estimates, remain unbumped.
18967
+ *
18968
+ * @param options - Optional transaction gas-price bump percentages, as in {@link execute}.
18969
+ * @returns An {@link OrderFeesQuote} with the fee-token amount, the native
18970
+ * value for the native rail, and the underlying estimate.
18971
+ * @throws If gas estimation returns zero.
18972
+ */
18973
+ async quoteOrderFees(order, options) {
18974
+ const isSameChain = this.source.config.stateMachineId === this.dest.config.stateMachineId;
18975
+ const estimate = await this.gasEstimator.estimateFillOrder(
18976
+ {
18977
+ order,
18978
+ maxPriorityFeePerGasBumpPercent: options?.maxPriorityFeePerGasBumpPercent,
18979
+ maxFeePerGasBumpPercent: options?.maxFeePerGasBumpPercent
18980
+ },
18981
+ {
18982
+ orderFeeGasPriceBumpPercent: isSameChain ? 0n : CROSS_CHAIN_ORDER_FEE_GAS_PRICE_BUMP_PERCENT
18983
+ }
18984
+ );
18985
+ if (estimate.totalGasCostWei === 0n || estimate.totalGasInFeeToken === 0n) {
18986
+ throw new Error("Gas estimation failed");
18987
+ }
18988
+ const fees = isSameChain ? estimate.totalGasInFeeToken * 2n : (estimate.totalGasInFeeToken + estimate.relayerFeeInSourceFeeToken) * 105n / 100n;
18989
+ const { address: feeToken } = await this.source.getFeeTokenWithDecimals();
18990
+ return {
18991
+ fees,
18992
+ nativeValue: estimate.totalGasCostWei + estimate.totalGasCostWei * 2n / 100n,
18993
+ feeToken,
18994
+ estimate
18995
+ };
18996
+ }
18856
18997
  /**
18857
18998
  * Encodes a list of calls into ERC-7821 `execute` calldata using
18858
18999
  * single-batch mode.