@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.
@@ -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",
@@ -5177,6 +5200,19 @@ var ChainConfigService = class {
5177
5200
  getExtDecimals(chain) {
5178
5201
  return this.getConfig(chain)?.tokenDecimals?.EXT;
5179
5202
  }
5203
+ /** Configured exotic (non-USD) tokens on a chain, for selection UIs. EXT is a test asset and is not offered. */
5204
+ getKnownExoticTokens(chain) {
5205
+ const config = this.getConfig(chain);
5206
+ const tokens = [];
5207
+ if (config?.assets?.cNGN) {
5208
+ tokens.push({ symbol: "cNGN", address: config.assets.cNGN, decimals: config.tokenDecimals?.cNGN });
5209
+ }
5210
+ return tokens;
5211
+ }
5212
+ /** Known ERC-4626 treasury vaults on a chain, for selection UIs. */
5213
+ getKnownVaults(chain) {
5214
+ return this.getConfig(chain)?.erc4626Vaults ?? [];
5215
+ }
5180
5216
  getChainId(chain) {
5181
5217
  return this.getConfig(chain)?.chainId ?? 0;
5182
5218
  }
@@ -7466,17 +7502,30 @@ var SubstrateChain = class _SubstrateChain {
7466
7502
  rotationMap.set(BigInt(setId.toString()), BigInt(height.toString()));
7467
7503
  }
7468
7504
  const proofs = [];
7469
- let epoch = currentEpoch - 1n;
7505
+ let epoch = currentEpoch + 1n;
7470
7506
  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]);
7507
+ const key = rotationOffchainKey(epoch);
7508
+ let proof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", key]);
7509
+ if (!proof) {
7510
+ const legacyKey = messagingOffchainKey(rotationMap.get(epoch));
7511
+ proof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", legacyKey]);
7512
+ }
7474
7513
  if (!proof) return void 0;
7475
7514
  proofs.push(proof);
7476
7515
  epoch++;
7477
7516
  }
7478
- const messagingKey = beefyOffchainKey(lastProvenHeight);
7479
- const messagingProof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", messagingKey]);
7517
+ const messagingKey = messagingOffchainKey(lastProvenHeight);
7518
+ let messagingProof = await this.rpcClient.call("offchain_localStorageGet", ["PERSISTENT", messagingKey]);
7519
+ if (!messagingProof) {
7520
+ for (const [setId, height] of rotationMap) {
7521
+ if (height !== lastProvenHeight) continue;
7522
+ messagingProof = await this.rpcClient.call("offchain_localStorageGet", [
7523
+ "PERSISTENT",
7524
+ rotationOffchainKey(setId)
7525
+ ]);
7526
+ break;
7527
+ }
7528
+ }
7480
7529
  if (!messagingProof) return void 0;
7481
7530
  proofs.push(messagingProof);
7482
7531
  return { proofs, provenHeight: lastProvenHeight };
@@ -7493,11 +7542,17 @@ var SubstrateChain = class _SubstrateChain {
7493
7542
  throw new Error(`${name} not found in runtime`);
7494
7543
  }
7495
7544
  };
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]));
7545
+ function beefyOffchainKey(prefix, id) {
7546
+ const prefixBytes = new TextEncoder().encode(prefix);
7547
+ const idBytes = new Uint8Array(8);
7548
+ new DataView(idBytes.buffer).setBigUint64(0, id, false);
7549
+ return toHex(new Uint8Array([...prefixBytes, ...idBytes]));
7550
+ }
7551
+ function messagingOffchainKey(provenHeight) {
7552
+ return beefyOffchainKey("beefy_consensus_proofs::", provenHeight);
7553
+ }
7554
+ function rotationOffchainKey(setId) {
7555
+ return beefyOffchainKey("beefy_consensus_proofs::rotation::", setId);
7501
7556
  }
7502
7557
  function requestCommitmentStorageKey(key) {
7503
7558
  const prefix = new TextEncoder().encode("RequestCommitments");
@@ -15385,14 +15440,21 @@ function orderCommitment(order) {
15385
15440
  const encoded = encodeAbiParameters([orderType], [transformOrderForContract(order)]);
15386
15441
  return keccak256(encoded);
15387
15442
  }
15388
- async function convertGasToFeeToken(ctx, gasEstimate, gasEstimateIn, evmChainID, gasPriceOverride) {
15443
+ function bumpGasPrice(gasPrice, bumpPercent) {
15444
+ if (bumpPercent < 0n) {
15445
+ throw new Error("Gas price bump percent cannot be negative");
15446
+ }
15447
+ return (gasPrice * (100n + bumpPercent) + 99n) / 100n;
15448
+ }
15449
+ async function convertGasToFeeToken(ctx, gasEstimate, gasEstimateIn, evmChainID, gasPriceOverride, gasPriceBumpPercent = 0n) {
15389
15450
  if (TESTNET_CHAINS.has(evmChainID)) return 1n;
15390
15451
  const chain = ctx[gasEstimateIn];
15391
15452
  const client = chain.client;
15392
- const gasPrice = gasPriceOverride ?? await retryPromise(() => client.getGasPrice(), {
15453
+ const baseGasPrice = gasPriceOverride ?? await retryPromise(() => client.getGasPrice(), {
15393
15454
  maxRetries: 3,
15394
15455
  backoffMs: 250
15395
15456
  });
15457
+ const gasPrice = bumpGasPrice(baseGasPrice, gasPriceBumpPercent);
15396
15458
  const gasCostInWei = gasEstimate * gasPrice;
15397
15459
  const wethAddr = chain.configService.getWrappedNativeAssetWithDecimals(evmChainID).asset;
15398
15460
  const feeToken = await getFeeToken(ctx, evmChainID, chain);
@@ -15893,6 +15955,12 @@ var OrderCanceller = class _OrderCanceller {
15893
15955
  static DEFAULT_MAX_RECOVERY_RESTARTS = 1;
15894
15956
  static PROOF_FRESHNESS_MAX_RETRIES = 3;
15895
15957
  static PROOF_FRESHNESS_BACKOFF_MS = 500;
15958
+ /**
15959
+ * Gas budget used to size the relayer fee for a cross-chain cancellation
15960
+ * message (the GET response or RefundEscrow POST executed on the source
15961
+ * chain), priced at the source chain's gas price.
15962
+ */
15963
+ static CANCEL_MESSAGE_GAS = 800000n;
15896
15964
  logger = createConsola({
15897
15965
  level: LogLevels.info,
15898
15966
  formatOptions: { columns: 80, colors: true, compact: true, date: false }
@@ -15951,9 +16019,14 @@ var OrderCanceller = class _OrderCanceller {
15951
16019
  timeoutTimestamp: 0n,
15952
16020
  context
15953
16021
  };
15954
- const feeInSourceFeeToken = await convertGasToFeeToken(this.ctx, 400000n, "source", sourceStateMachine);
16022
+ const feeInSourceFeeToken = await convertGasToFeeToken(
16023
+ this.ctx,
16024
+ _OrderCanceller.CANCEL_MESSAGE_GAS,
16025
+ "source",
16026
+ sourceStateMachine
16027
+ );
15955
16028
  const relayerFee = feeInSourceFeeToken * 1005n / 1000n;
15956
- const nativeValue = await this.ctx.source.quoteNative(getRequest, relayerFee);
16029
+ const nativeValue = await this.ctx.source.quoteNative(getRequest, relayerFee) * 101n / 100n;
15957
16030
  return { nativeValue, relayerFee };
15958
16031
  }
15959
16032
  /**
@@ -16212,7 +16285,7 @@ var OrderCanceller = class _OrderCanceller {
16212
16285
  body,
16213
16286
  timeoutTimestamp: 0n
16214
16287
  };
16215
- const nativeValue = await this.ctx.dest.quoteNative(postRequest, relayerFee);
16288
+ const nativeValue = await this.ctx.dest.quoteNative(postRequest, relayerFee) * 101n / 100n;
16216
16289
  return { nativeValue, relayerFee };
16217
16290
  }
16218
16291
  /**
@@ -16542,8 +16615,12 @@ var OrderCanceller = class _OrderCanceller {
16542
16615
  * Converts estimated gas on the source chain into the dest chain's fee token.
16543
16616
  */
16544
16617
  async estimateRelayerFee(sourceChainId, destChainId) {
16545
- const POST_REQUEST_GAS = 400000n;
16546
- const feeInSourceFeeToken = await convertGasToFeeToken(this.ctx, POST_REQUEST_GAS, "source", sourceChainId);
16618
+ const feeInSourceFeeToken = await convertGasToFeeToken(
16619
+ this.ctx,
16620
+ _OrderCanceller.CANCEL_MESSAGE_GAS,
16621
+ "source",
16622
+ sourceChainId
16623
+ );
16547
16624
  const sourceFeeToken = await getFeeToken(this.ctx, sourceChainId, this.ctx.source);
16548
16625
  const destFeeToken = await getFeeToken(this.ctx, destChainId, this.ctx.dest);
16549
16626
  const feeInDestFeeToken = adjustDecimals(feeInSourceFeeToken, sourceFeeToken.decimals, destFeeToken.decimals);
@@ -17302,12 +17379,15 @@ var GasEstimator = class {
17302
17379
  *
17303
17380
  * @param params - Parameters including the order to estimate and optional
17304
17381
  * percentage bumps for `maxPriorityFeePerGas` and `maxFeePerGas`.
17382
+ * @param pricingOptions - Internal fee-pricing policy. Direct estimates use
17383
+ * the default zero gas-price bump; SDK order-fee quotes opt into headroom.
17305
17384
  * @returns A {@link FillOrderEstimate} containing all gas components,
17306
17385
  * EIP-1559 fee values, total cost in wei, and total cost in the source
17307
17386
  * chain's fee token.
17308
17387
  */
17309
- async estimateFillOrder(params) {
17388
+ async estimateFillOrder(params, pricingOptions = {}) {
17310
17389
  const { order } = params;
17390
+ const orderFeeGasPriceBumpPercent = pricingOptions.orderFeeGasPriceBumpPercent ?? 0n;
17311
17391
  const solverPrivateKey = generatePrivateKey();
17312
17392
  const solverAccountAddress = privateKeyToAddress(solverPrivateKey);
17313
17393
  const souceStateMachineId = isHex(order.source) ? hexToString$1(order.source) : order.source;
@@ -17338,7 +17418,12 @@ var GasEstimator = class {
17338
17418
  intentGatewayV2Address,
17339
17419
  entryPointAddress
17340
17420
  }),
17341
- isSameChain ? Promise.resolve({ postRequestFee: 0n, relayerFeeInSourceFeeToken: 0n }) : this.estimateCrossChainFees(sourceFeeToken, destFeeToken, souceStateMachineId)
17421
+ isSameChain ? Promise.resolve({ postRequestFee: 0n, relayerFeeInSourceFeeToken: 0n }) : this.estimateCrossChainFees(
17422
+ sourceFeeToken,
17423
+ destFeeToken,
17424
+ souceStateMachineId,
17425
+ orderFeeGasPriceBumpPercent
17426
+ )
17342
17427
  ]);
17343
17428
  const { viem: stateOverrides, bundler: bundlerStateOverrides } = stateOverridesResult;
17344
17429
  const fillOptions = {
@@ -17503,7 +17588,8 @@ var GasEstimator = class {
17503
17588
  totalGas,
17504
17589
  "dest",
17505
17590
  destStateMachineId,
17506
- gasPrice
17591
+ gasPrice,
17592
+ orderFeeGasPriceBumpPercent
17507
17593
  );
17508
17594
  const totalGasInSourceFeeToken = isSameChain ? totalGasInDestFeeToken : adjustDecimals(totalGasInDestFeeToken, destFeeToken.decimals, sourceFeeToken.decimals);
17509
17595
  const totalGasCostWei = isSameChain ? rawTotalGasCostWei : await convertFeeTokenToWei(this.ctx, totalGasInSourceFeeToken, "source", souceStateMachineId);
@@ -17527,12 +17613,14 @@ var GasEstimator = class {
17527
17613
  * The dispatch is always paid in the fee token — the native rail was
17528
17614
  * removed because it silently drew on a native balance nothing guarantees.
17529
17615
  */
17530
- async estimateCrossChainFees(sourceFeeToken, destFeeToken, sourceChainId) {
17616
+ async estimateCrossChainFees(sourceFeeToken, destFeeToken, sourceChainId, orderFeeGasPriceBumpPercent) {
17531
17617
  const postRequestFeeInSourceFeeToken = await convertGasToFeeToken(
17532
17618
  this.ctx,
17533
17619
  RELAYER_MESSAGE_GAS,
17534
17620
  "source",
17535
- sourceChainId
17621
+ sourceChainId,
17622
+ void 0,
17623
+ orderFeeGasPriceBumpPercent
17536
17624
  );
17537
17625
  const postRequestFeeInDestFeeToken = adjustDecimals(
17538
17626
  postRequestFeeInSourceFeeToken,
@@ -18302,6 +18390,7 @@ function isConfiguredAddress(address) {
18302
18390
  }
18303
18391
 
18304
18392
  // src/protocols/intents/IntentGateway.ts
18393
+ var CROSS_CHAIN_ORDER_FEE_GAS_PRICE_BUMP_PERCENT = 10n;
18305
18394
  var IntentGateway = class _IntentGateway {
18306
18395
  /** EVM chain on which orders are placed and escrowed. */
18307
18396
  source;
@@ -18488,14 +18577,22 @@ var IntentGateway = class _IntentGateway {
18488
18577
  * placement, fee estimation, bid collection, and execution.
18489
18578
  *
18490
18579
  * **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)`.
18580
+ * 1. If `order.fees` is unset or zero, prices the fee on an internal copy
18581
+ * via {@link quoteOrderFees}: same-chain fees are twice the fill-gas
18582
+ * estimate without a gas-price bump; cross-chain gas is priced 10% above
18583
+ * the live price before attaching (fill gas + the settlement relayer fee)
18584
+ * with a further 5% buffer over the whole sum — strictly above the solver's
18585
+ * unpadded requirement. Direct solver estimates remain unbumped. The wei
18586
+ * cost used for the `value` field receives a 2% buffer.
18587
+ * 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, nativeFee,
18588
+ * feeTokenAmount, feeTokenAddress, sessionPrivateKey }`. `value` carries
18589
+ * only the order's native-token input amounts; `nativeFee` is the native
18590
+ * amount that funds `order.fees` (`0n` when the caller set `order.fees`);
18591
+ * `feeTokenAmount`/`feeTokenAddress` are the exact fee encoded in `data`
18592
+ * and the source-chain token it is charged in. To pay the fee in native
18593
+ * token, sign the transaction with `value + nativeFee`; with a fee-token
18594
+ * allowance, `value` alone. Pass the signed transaction back via
18595
+ * `gen.next(signedTx)`.
18499
18596
  * 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
18500
18597
  * the `OrderPlaced` event is confirmed.
18501
18598
  * 4. Delegates to {@link OrderExecutor.executeOrder} and forwards all
@@ -18516,33 +18613,33 @@ var IntentGateway = class _IntentGateway {
18516
18613
  */
18517
18614
  async *execute(order, graffiti = DEFAULT_GRAFFITI, options) {
18518
18615
  const executionOrder = { ...order };
18519
- let value;
18616
+ let nativeFee = 0n;
18520
18617
  if (!executionOrder.fees || executionOrder.fees === 0n) {
18521
- const estimate = await this.gasEstimator.estimateFillOrder({
18522
- order: executionOrder,
18618
+ const feesQuote = await this.quoteOrderFees(executionOrder, {
18523
18619
  maxPriorityFeePerGasBumpPercent: options?.maxPriorityFeePerGasBumpPercent,
18524
18620
  maxFeePerGasBumpPercent: options?.maxFeePerGasBumpPercent
18525
18621
  });
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;
18622
+ nativeFee = feesQuote.nativeValue;
18623
+ executionOrder.fees = feesQuote.fees;
18538
18624
  }
18625
+ const value = executionOrder.inputs.filter((input) => bytes32ToBytes20(input.token) === ADDRESS_ZERO2).reduce((sum, input) => sum + input.amount, 0n);
18539
18626
  const placeOrderGen = this.orderPlacer.placeOrder(executionOrder, graffiti);
18540
18627
  const placeOrderFirst = await placeOrderGen.next();
18541
18628
  if (placeOrderFirst.done) {
18542
18629
  throw new Error("placeOrder generator completed without yielding");
18543
18630
  }
18544
18631
  const { to, data, sessionPrivateKey } = placeOrderFirst.value;
18545
- const signedTransaction = yield { status: "AWAITING_PLACE_ORDER", to, data, value, sessionPrivateKey };
18632
+ const { address: feeTokenAddress } = await getFeeToken(this.ctx, this.source.config.stateMachineId, this.source);
18633
+ const signedTransaction = yield {
18634
+ status: "AWAITING_PLACE_ORDER",
18635
+ to,
18636
+ data,
18637
+ value,
18638
+ nativeFee,
18639
+ sessionPrivateKey,
18640
+ feeTokenAmount: executionOrder.fees,
18641
+ feeTokenAddress
18642
+ };
18546
18643
  const placeOrderSecond = await placeOrderGen.next(signedTransaction);
18547
18644
  if (placeOrderSecond.done === false) {
18548
18645
  throw new Error("placeOrder generator yielded unexpectedly after signing");
@@ -18842,6 +18939,50 @@ var IntentGateway = class _IntentGateway {
18842
18939
  async estimateFillOrder(params) {
18843
18940
  return this.gasEstimator.estimateFillOrder(params);
18844
18941
  }
18942
+ /**
18943
+ * Quotes the solver fee for an order using the same policy {@link execute} /
18944
+ * {@link executeBest} apply when `order.fees` is `0n`.
18945
+ *
18946
+ * Use this before placing to display the fee, or to check what the user can
18947
+ * afford: pay `fees` in the source-chain fee token (check balance and
18948
+ * allowance, then set `order.fees` and submit with `value: 0`), or leave
18949
+ * `order.fees` at `0n` and let the SDK attach `nativeValue` to the placement
18950
+ * transaction (check the native balance).
18951
+ *
18952
+ * @param order - The order to quote. `order.fees` is ignored and not mutated.
18953
+ * Gas prices used to derive cross-chain `fees` receive 10% SDK-only headroom.
18954
+ * Same-chain quotes and direct calls to {@link estimateFillOrder}, including
18955
+ * Simplex solver estimates, remain unbumped.
18956
+ *
18957
+ * @param options - Optional transaction gas-price bump percentages, as in {@link execute}.
18958
+ * @returns An {@link OrderFeesQuote} with the fee-token amount, the native
18959
+ * value for the native rail, and the underlying estimate.
18960
+ * @throws If gas estimation returns zero.
18961
+ */
18962
+ async quoteOrderFees(order, options) {
18963
+ const isSameChain = this.source.config.stateMachineId === this.dest.config.stateMachineId;
18964
+ const estimate = await this.gasEstimator.estimateFillOrder(
18965
+ {
18966
+ order,
18967
+ maxPriorityFeePerGasBumpPercent: options?.maxPriorityFeePerGasBumpPercent,
18968
+ maxFeePerGasBumpPercent: options?.maxFeePerGasBumpPercent
18969
+ },
18970
+ {
18971
+ orderFeeGasPriceBumpPercent: isSameChain ? 0n : CROSS_CHAIN_ORDER_FEE_GAS_PRICE_BUMP_PERCENT
18972
+ }
18973
+ );
18974
+ if (estimate.totalGasCostWei === 0n || estimate.totalGasInFeeToken === 0n) {
18975
+ throw new Error("Gas estimation failed");
18976
+ }
18977
+ const fees = isSameChain ? estimate.totalGasInFeeToken * 2n : (estimate.totalGasInFeeToken + estimate.relayerFeeInSourceFeeToken) * 105n / 100n;
18978
+ const { address: feeToken } = await this.source.getFeeTokenWithDecimals();
18979
+ return {
18980
+ fees,
18981
+ nativeValue: estimate.totalGasCostWei + estimate.totalGasCostWei * 2n / 100n,
18982
+ feeToken,
18983
+ estimate
18984
+ };
18985
+ }
18845
18986
  /**
18846
18987
  * Encodes a list of calls into ERC-7821 `execute` calldata using
18847
18988
  * single-batch mode.