@hyperbridge/sdk 2.5.0 → 2.6.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.
@@ -905,6 +905,10 @@ interface ChainConfigData {
905
905
  USDT: string;
906
906
  cNGN?: string;
907
907
  EXT?: string;
908
+ ZARP?: string;
909
+ EURC?: string;
910
+ XSGD?: string;
911
+ TRYB?: string;
908
912
  };
909
913
  tokenDecimals?: {
910
914
  USDC: number;
@@ -1005,6 +1009,13 @@ declare class ChainConfigService {
1005
1009
  getUsdcDecimals(chain: string): number;
1006
1010
  getUsdtDecimals(chain: string): number;
1007
1011
  getCNgnAsset(chain: string): HexString | undefined;
1012
+ /**
1013
+ * Address of `symbol` on `chain` from the per-chain asset table, matched
1014
+ * case-insensitively ("cNGN" ≡ "CNGN"). This table is the single source of
1015
+ * truth for token addresses — the simplex asset registry resolves through
1016
+ * it, so a new asset is added once in `chain.ts` and nowhere else.
1017
+ */
1018
+ getAssetBySymbol(chain: string, symbol: string): HexString | undefined;
1008
1019
  getCNgnDecimals(chain: string): number | undefined;
1009
1020
  getExtAsset(chain: string): HexString | undefined;
1010
1021
  getExtDecimals(chain: string): number | undefined;
@@ -2830,6 +2841,13 @@ interface FillOrderEstimate {
2830
2841
  maxPriorityFeePerGas: bigint;
2831
2842
  totalGasCostWei: bigint;
2832
2843
  totalGasInFeeToken: bigint;
2844
+ /**
2845
+ * Relayer fee for the cross-chain settlement message, denominated in the
2846
+ * SOURCE fee token (same unit as `Order.fees`). This is `RELAYER_MESSAGE_GAS`
2847
+ * priced on the source chain; it is 0 for same-chain fills. A filler's
2848
+ * `order.fees` must cover `totalGasInFeeToken + relayerFeeInSourceFeeToken`.
2849
+ */
2850
+ relayerFeeInSourceFeeToken: bigint;
2833
2851
  }
2834
2852
  /**
2835
2853
  * Result of submitting a bid to Hyperbridge
@@ -905,6 +905,10 @@ interface ChainConfigData {
905
905
  USDT: string;
906
906
  cNGN?: string;
907
907
  EXT?: string;
908
+ ZARP?: string;
909
+ EURC?: string;
910
+ XSGD?: string;
911
+ TRYB?: string;
908
912
  };
909
913
  tokenDecimals?: {
910
914
  USDC: number;
@@ -1005,6 +1009,13 @@ declare class ChainConfigService {
1005
1009
  getUsdcDecimals(chain: string): number;
1006
1010
  getUsdtDecimals(chain: string): number;
1007
1011
  getCNgnAsset(chain: string): HexString | undefined;
1012
+ /**
1013
+ * Address of `symbol` on `chain` from the per-chain asset table, matched
1014
+ * case-insensitively ("cNGN" ≡ "CNGN"). This table is the single source of
1015
+ * truth for token addresses — the simplex asset registry resolves through
1016
+ * it, so a new asset is added once in `chain.ts` and nowhere else.
1017
+ */
1018
+ getAssetBySymbol(chain: string, symbol: string): HexString | undefined;
1008
1019
  getCNgnDecimals(chain: string): number | undefined;
1009
1020
  getExtAsset(chain: string): HexString | undefined;
1010
1021
  getExtDecimals(chain: string): number | undefined;
@@ -2830,6 +2841,13 @@ interface FillOrderEstimate {
2830
2841
  maxPriorityFeePerGas: bigint;
2831
2842
  totalGasCostWei: bigint;
2832
2843
  totalGasInFeeToken: bigint;
2844
+ /**
2845
+ * Relayer fee for the cross-chain settlement message, denominated in the
2846
+ * SOURCE fee token (same unit as `Order.fees`). This is `RELAYER_MESSAGE_GAS`
2847
+ * priced on the source chain; it is 0 for same-chain fills. A filler's
2848
+ * `order.fees` must cover `totalGasInFeeToken + relayerFeeInSourceFeeToken`.
2849
+ */
2850
+ relayerFeeInSourceFeeToken: bigint;
2833
2851
  }
2834
2852
  /**
2835
2853
  * Result of submitting a bid to Hyperbridge
@@ -2689,7 +2689,11 @@ var chainConfigs = {
2689
2689
  DAI: "0x6b175474e89094c44da98b954eedeac495271d0f",
2690
2690
  USDC: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
2691
2691
  USDT: "0xdac17f958d2ee523a2206206994597c13d831ec7",
2692
- cNGN: "0x17CDB2a01e7a34CbB3DD4b83260B05d0274C8dab"
2692
+ cNGN: "0x17CDB2a01e7a34CbB3DD4b83260B05d0274C8dab",
2693
+ ZARP: "0xb755506531786C8aC63B756BaB1ac387bACB0C04",
2694
+ EURC: "0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c",
2695
+ XSGD: "0x70e8dE73cE538DA2bEEd35d14187F6959a8ecA96",
2696
+ TRYB: "0x2C537E5624e4af88A7ae4060C022609376C8D0EB"
2693
2697
  },
2694
2698
  tokenDecimals: {
2695
2699
  USDC: 6,
@@ -2859,7 +2863,9 @@ var chainConfigs = {
2859
2863
  USDC: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
2860
2864
  USDT: "0xfde4c96c8593536e31f229ea8f37b2ada2699bb2",
2861
2865
  EXT: "0x0e668E5127087e236578893a0e01E41837A28469",
2862
- cNGN: "0x46C85152bFe9f96829aA94755D9f915F9B10EF5F"
2866
+ cNGN: "0x46C85152bFe9f96829aA94755D9f915F9B10EF5F",
2867
+ ZARP: "0xb755506531786C8aC63B756BaB1ac387bACB0C04",
2868
+ EURC: "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"
2863
2869
  },
2864
2870
  tokenDecimals: {
2865
2871
  USDC: 6,
@@ -2919,7 +2925,9 @@ var chainConfigs = {
2919
2925
  USDC: "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
2920
2926
  USDT: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
2921
2927
  EXT: "0x7C8c11ADb8EF7cd3CFa718008Ea048445C6E7209",
2922
- cNGN: "0x52828daa48C1a9A06F37500882b42daf0bE04C3B"
2928
+ cNGN: "0x52828daa48C1a9A06F37500882b42daf0bE04C3B",
2929
+ ZARP: "0xb755506531786C8aC63B756BaB1ac387bACB0C04",
2930
+ XSGD: "0xDC3326e71D45186F113a2F448984CA0e8D201995"
2923
2931
  },
2924
2932
  tokenDecimals: {
2925
2933
  USDC: 6,
@@ -5156,6 +5164,21 @@ var ChainConfigService = class {
5156
5164
  getCNgnAsset(chain) {
5157
5165
  return this.getConfig(chain)?.assets?.cNGN;
5158
5166
  }
5167
+ /**
5168
+ * Address of `symbol` on `chain` from the per-chain asset table, matched
5169
+ * case-insensitively ("cNGN" ≡ "CNGN"). This table is the single source of
5170
+ * truth for token addresses — the simplex asset registry resolves through
5171
+ * it, so a new asset is added once in `chain.ts` and nowhere else.
5172
+ */
5173
+ getAssetBySymbol(chain, symbol) {
5174
+ const assets = this.getConfig(chain)?.assets;
5175
+ if (!assets) return void 0;
5176
+ const target = symbol.trim().toUpperCase();
5177
+ for (const [key, address] of Object.entries(assets)) {
5178
+ if (key.toUpperCase() === target) return address;
5179
+ }
5180
+ return void 0;
5181
+ }
5159
5182
  getCNgnDecimals(chain) {
5160
5183
  return this.getConfig(chain)?.tokenDecimals?.cNGN;
5161
5184
  }
@@ -17252,6 +17275,7 @@ var BidManager = class {
17252
17275
  }
17253
17276
  }
17254
17277
  };
17278
+ var RELAYER_MESSAGE_GAS = 1000000n;
17255
17279
  var GasEstimator = class {
17256
17280
  /**
17257
17281
  * @param ctx - Shared IntentsV2 context providing the source and destination
@@ -17272,7 +17296,12 @@ var GasEstimator = class {
17272
17296
  *
17273
17297
  * **Cross-chain orders:** also estimates the ISMP POST request fee required
17274
17298
  * for the solver to trigger source-chain escrow redemption after filling, and
17275
- * includes it in `fillOptions.relayerFee` and `fillOptions.nativeDispatchFee`.
17299
+ * includes it in `fillOptions.relayerFee`. The dispatch is always paid in the
17300
+ * fee token — `nativeDispatchFee` is fixed at 0. The native rail would draw
17301
+ * from the solver account's native balance, which nothing guarantees, and a
17302
+ * shortfall is invisible to estimation (the account balance is overridden
17303
+ * during simulation) — it would only surface as a reverted execution that
17304
+ * still bills the paymaster.
17276
17305
  *
17277
17306
  * **Bundler path:** constructs a mock `PackedUserOperation` signed by an
17278
17307
  * ephemeral keypair, applies state overrides, and calls
@@ -17321,24 +17350,19 @@ var GasEstimator = class {
17321
17350
  intentGatewayV2Address,
17322
17351
  entryPointAddress
17323
17352
  }),
17324
- isSameChain ? Promise.resolve({ postRequestFee: 0n, protocolFee: 0n }) : this.estimateCrossChainFees(
17325
- sourceFeeToken,
17326
- destFeeToken,
17327
- souceStateMachineId,
17328
- destStateMachineId,
17329
- order
17330
- )
17353
+ isSameChain ? Promise.resolve({ postRequestFee: 0n, relayerFeeInSourceFeeToken: 0n }) : this.estimateCrossChainFees(sourceFeeToken, destFeeToken, souceStateMachineId)
17331
17354
  ]);
17332
17355
  const { viem: stateOverrides, bundler: bundlerStateOverrides } = stateOverridesResult;
17333
17356
  const fillOptions = {
17334
17357
  relayerFee: crossChainFees.postRequestFee,
17335
- nativeDispatchFee: crossChainFees.protocolFee,
17358
+ // Always dispatch with the fee token (see the method docs).
17359
+ nativeDispatchFee: 0n,
17336
17360
  outputs: order.output.assets.map((asset) => ({
17337
17361
  ...asset,
17338
17362
  token: normalizeAddressForEvmBytes32(asset.token)
17339
17363
  }))
17340
17364
  };
17341
- const totalNativeValue = totalEthValue + fillOptions.nativeDispatchFee;
17365
+ const totalNativeValue = totalEthValue;
17342
17366
  const priorityFeeBumpPercent = params.maxPriorityFeePerGasBumpPercent ?? 8;
17343
17367
  const maxFeeBumpPercent = params.maxFeePerGasBumpPercent ?? 10;
17344
17368
  let maxPriorityFeePerGas = gasPrice + gasPrice * BigInt(priorityFeeBumpPercent) / 100n;
@@ -17505,37 +17529,32 @@ var GasEstimator = class {
17505
17529
  maxPriorityFeePerGas,
17506
17530
  totalGasCostWei,
17507
17531
  totalGasInFeeToken: totalGasInSourceFeeToken,
17532
+ relayerFeeInSourceFeeToken: crossChainFees.relayerFeeInSourceFeeToken,
17508
17533
  fillOptions
17509
17534
  };
17510
17535
  }
17511
17536
  /**
17512
- * Estimates cross-chain ISMP POST request fees by running the gas-to-fee-token
17513
- * conversion and host nonce fetch in parallel, then quoting the native dispatch cost.
17514
- */
17515
- async estimateCrossChainFees(sourceFeeToken, destFeeToken, sourceChainId, destChainId, order) {
17516
- const postRequestGas = 400000n;
17517
- const [postRequestFeeInSourceFeeToken, nonce] = await Promise.all([
17518
- convertGasToFeeToken(this.ctx, postRequestGas, "source", sourceChainId),
17519
- this.ctx.dest.getHostNonce()
17520
- ]);
17521
- let postRequestFeeInDestFeeToken = adjustDecimals(
17537
+ * Estimates the cross-chain ISMP POST request fee (the relayer fee for the
17538
+ * RedeemEscrow message), in both the source and destination fee tokens.
17539
+ * The dispatch is always paid in the fee token — the native rail was
17540
+ * removed because it silently drew on a native balance nothing guarantees.
17541
+ */
17542
+ async estimateCrossChainFees(sourceFeeToken, destFeeToken, sourceChainId) {
17543
+ const postRequestFeeInSourceFeeToken = await convertGasToFeeToken(
17544
+ this.ctx,
17545
+ RELAYER_MESSAGE_GAS,
17546
+ "source",
17547
+ sourceChainId
17548
+ );
17549
+ const postRequestFeeInDestFeeToken = adjustDecimals(
17522
17550
  postRequestFeeInSourceFeeToken,
17523
17551
  sourceFeeToken.decimals,
17524
17552
  destFeeToken.decimals
17525
17553
  );
17526
- const postRequest = {
17527
- source: destChainId,
17528
- dest: sourceChainId,
17529
- body: constructRedeemEscrowRequestBody({ ...order, id: orderCommitment(order) }, MOCK_ADDRESS),
17530
- timeoutTimestamp: 0n,
17531
- nonce,
17532
- from: this.ctx.source.configService.getIntentGatewayAddress(destChainId),
17533
- to: this.ctx.source.configService.getIntentGatewayAddress(sourceChainId)
17554
+ return {
17555
+ postRequestFee: postRequestFeeInDestFeeToken,
17556
+ relayerFeeInSourceFeeToken: postRequestFeeInSourceFeeToken
17534
17557
  };
17535
- postRequestFeeInDestFeeToken = postRequestFeeInDestFeeToken * 1005n / 1000n;
17536
- let protocolFeeInNativeToken = await this.ctx.dest.quoteNative(postRequest, postRequestFeeInDestFeeToken).catch(() => 0n);
17537
- protocolFeeInNativeToken = protocolFeeInNativeToken * 1005n / 1000n;
17538
- return { postRequestFee: postRequestFeeInDestFeeToken, protocolFee: protocolFeeInNativeToken };
17539
17558
  }
17540
17559
  /**
17541
17560
  * Builds EVM state override objects for gas estimation of the `fillOrder`
@@ -18295,7 +18314,6 @@ function isConfiguredAddress(address) {
18295
18314
  }
18296
18315
 
18297
18316
  // src/protocols/intents/IntentGateway.ts
18298
- var CROSS_CHAIN_ORDER_FEE_GAS_BUMP = 600000n;
18299
18317
  var IntentGateway = class _IntentGateway {
18300
18318
  /** EVM chain on which orders are placed and escrowed. */
18301
18319
  source;
@@ -18482,10 +18500,12 @@ var IntentGateway = class _IntentGateway {
18482
18500
  * placement, fee estimation, bid collection, and execution.
18483
18501
  *
18484
18502
  * **Yield/receive protocol:**
18485
- * 1. If `order.fees` is unset or zero, estimates gas on an internal copy and sets
18486
- * same-chain fees to twice the estimate. Cross-chain orders retain a 1% buffer
18487
- * and include an additional 600k-gas fee uplift, while the wei cost used for
18488
- * the `value` field receives a 2% buffer.
18503
+ * 1. If `order.fees` is unset or zero, estimates gas on an internal copy and
18504
+ * sets same-chain fees to twice the estimate. Cross-chain orders attach
18505
+ * (fill gas + a settlement-message uplift of `RELAYER_MESSAGE_GAS`, the
18506
+ * same gas budget the solver's relayer fee uses) with a 5% buffer over
18507
+ * the whole sum — strictly above the solver's unpadded requirement. The
18508
+ * wei cost used for the `value` field receives a 2% buffer.
18489
18509
  * 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, sessionPrivateKey }`.
18490
18510
  * The caller must sign the transaction and pass it back via `gen.next(signedTx)`.
18491
18511
  * 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
@@ -18522,11 +18542,11 @@ var IntentGateway = class _IntentGateway {
18522
18542
  value = estimate.totalGasCostWei + estimate.totalGasCostWei * 2n / 100n;
18523
18543
  const crossChainFeeBump = isSameChain ? 0n : await convertGasToFeeToken(
18524
18544
  this.ctx,
18525
- CROSS_CHAIN_ORDER_FEE_GAS_BUMP,
18545
+ RELAYER_MESSAGE_GAS,
18526
18546
  "source",
18527
18547
  this.source.config.stateMachineId
18528
18548
  );
18529
- executionOrder.fees = isSameChain ? estimate.totalGasInFeeToken * 2n : estimate.totalGasInFeeToken + (crossChainFeeBump + estimate.totalGasInFeeToken * 1n / 100n);
18549
+ executionOrder.fees = isSameChain ? estimate.totalGasInFeeToken * 2n : (estimate.totalGasInFeeToken + crossChainFeeBump) * 105n / 100n;
18530
18550
  }
18531
18551
  const placeOrderGen = this.orderPlacer.placeOrder(executionOrder, graffiti);
18532
18552
  const placeOrderFirst = await placeOrderGen.next();