@hyperbridge/sdk 1.8.6 → 1.9.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.
- package/dist/browser/index.d.ts +62 -13
- package/dist/browser/index.js +363 -189
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.d.ts +62 -13
- package/dist/node/index.js +363 -189
- package/dist/node/index.js.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.js
CHANGED
|
@@ -606,10 +606,9 @@ var IntentOrderStatus = Object.freeze({
|
|
|
606
606
|
AWAITING_BIDS: "AWAITING_BIDS",
|
|
607
607
|
BIDS_RECEIVED: "BIDS_RECEIVED",
|
|
608
608
|
BID_SELECTED: "BID_SELECTED",
|
|
609
|
-
USEROP_SUBMITTED: "USEROP_SUBMITTED",
|
|
610
609
|
FILLED: "FILLED",
|
|
611
610
|
PARTIAL_FILL: "PARTIAL_FILL",
|
|
612
|
-
|
|
611
|
+
EXPIRED: "EXPIRED",
|
|
613
612
|
FAILED: "FAILED"
|
|
614
613
|
});
|
|
615
614
|
|
|
@@ -3837,6 +3836,9 @@ var chainConfigs = {
|
|
|
3837
3836
|
UniversalRouter: "0x66a9893cc07d91d95644aedd05d03f95e1dba8af",
|
|
3838
3837
|
UniswapV3Quoter: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
|
|
3839
3838
|
UniswapV4Quoter: "0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203",
|
|
3839
|
+
UniswapV4PositionManager: "0xbd216513d74c8cf14cf4747e6aaa6420ff64ee9e",
|
|
3840
|
+
UniswapV4PoolManager: "0x000000000004444c5dc75cB358380D2e3dE08A90",
|
|
3841
|
+
UniswapV4StateView: "0x7ffe42c4a5deea5b0fec41c94c136cf115597227",
|
|
3840
3842
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
3841
3843
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
3842
3844
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
@@ -3889,6 +3891,9 @@ var chainConfigs = {
|
|
|
3889
3891
|
UniversalRouter: "0xd9C500DfF816a1Da21A48A732d3498Bf09dc9AEB",
|
|
3890
3892
|
UniswapV3Quoter: "0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997",
|
|
3891
3893
|
UniswapV4Quoter: "0xd0737C9762912dD34c3271197E362Aa736Df0926",
|
|
3894
|
+
UniswapV4PositionManager: "0x7a4a5c919ae2541aed11041a1aeee68f1287f95b",
|
|
3895
|
+
UniswapV4PoolManager: "0x28e2ea090877bf75740558f6bfb36a5ffee9e9df",
|
|
3896
|
+
UniswapV4StateView: "0xd13dd3d6e93f276fafc9db9e6bb47c1180aee0c4",
|
|
3892
3897
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
3893
3898
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
3894
3899
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
@@ -3943,6 +3948,9 @@ var chainConfigs = {
|
|
|
3943
3948
|
UniversalRouter: "0xa51afafe0263b40edaef0df8781ea9aa03e381a3",
|
|
3944
3949
|
UniswapV3Quoter: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
|
|
3945
3950
|
UniswapV4Quoter: "0x3972c00f7ed4885e145823eb7c655375d275a1c5",
|
|
3951
|
+
UniswapV4PositionManager: "0xd88f38f930b7952f2db2432cb002e7abbf3dd869",
|
|
3952
|
+
UniswapV4PoolManager: "0x360e68faccca8ca495c1b759fd9eee466db9fb32",
|
|
3953
|
+
UniswapV4StateView: "0x76fd297e2d437cd7f76d50f01afe6160f86e9990",
|
|
3946
3954
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
3947
3955
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
3948
3956
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
@@ -3999,7 +4007,11 @@ var chainConfigs = {
|
|
|
3999
4007
|
UniswapV4Quoter: "0x0d5e0f971ed27fbff6c2837bf31316121532048d",
|
|
4000
4008
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
4001
4009
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
4002
|
-
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
4010
|
+
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
4011
|
+
AerodromeRouter: "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43",
|
|
4012
|
+
UniswapV4PositionManager: "0x7c5f5a4bbd8fd63184577525326123b519429bdc",
|
|
4013
|
+
UniswapV4PoolManager: "0x498581ff718922c3f8e6a244956af099b2652b2b",
|
|
4014
|
+
UniswapV4StateView: "0xa3c0c9b65bad0b08107aa264b0f3db444b867a71"
|
|
4003
4015
|
// Usdt0Oft: Not available on Base
|
|
4004
4016
|
},
|
|
4005
4017
|
rpcEnvKey: "BASE_MAINNET",
|
|
@@ -4051,6 +4063,9 @@ var chainConfigs = {
|
|
|
4051
4063
|
UniversalRouter: "0x1095692a6237d83c6a72f3f5efedb9a670c49223",
|
|
4052
4064
|
UniswapV3Quoter: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
|
|
4053
4065
|
UniswapV4Quoter: "0xb3d5c3dfc3a7aebff71895a7191796bffc2c81b9",
|
|
4066
|
+
UniswapV4PositionManager: "0x1ec2ebf4f37e7363fdfe3551602425af0b3ceef9",
|
|
4067
|
+
UniswapV4PoolManager: "0x67366782805870060151383f4bbff9dab53e5cd6",
|
|
4068
|
+
UniswapV4StateView: "0x5ea1bd7974c8a611cbab0bdcafcb1d9cc9b3ba5a",
|
|
4054
4069
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
4055
4070
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
4056
4071
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
@@ -4095,6 +4110,9 @@ var chainConfigs = {
|
|
|
4095
4110
|
UniversalRouter: "0xef740bf23acae26f6492b10de645d6b98dc8eaf3",
|
|
4096
4111
|
UniswapV3Quoter: "0x385a5cf5f83e99f7bb2852b6a19c3538b9fa7658",
|
|
4097
4112
|
UniswapV4Quoter: "0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203",
|
|
4113
|
+
UniswapV4PositionManager: "0x4529a01c7a0410167c5740c487a8de60232617bf",
|
|
4114
|
+
UniswapV4PoolManager: "0x1f98400000000000000000000000000000000004",
|
|
4115
|
+
UniswapV4StateView: "0x86e8631a016f9068c3f085faf484ee3f5fdee8f2",
|
|
4098
4116
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
4099
4117
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
4100
4118
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
@@ -4200,7 +4218,9 @@ var chainConfigs = {
|
|
|
4200
4218
|
UniswapV3Factory: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
4201
4219
|
Calldispatcher: "0xC71251c8b3e7B02697A84363Eef6DcE8DfBdF333",
|
|
4202
4220
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
4203
|
-
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
4221
|
+
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
4222
|
+
UniswapV4PositionManager: "0x3c3ea4b57a46241e54610e5f022e5c45859a1017",
|
|
4223
|
+
UniswapV4PoolManager: "0x9a13f98cb987694c9f086b1f5eb990eea8264ec3"
|
|
4204
4224
|
},
|
|
4205
4225
|
defaultRpcUrl: "https://mainnet.optimism.io",
|
|
4206
4226
|
consensusStateId: "ETH0",
|
|
@@ -4256,7 +4276,9 @@ var chainConfigs = {
|
|
|
4256
4276
|
addresses: {
|
|
4257
4277
|
TokenGateway: "0xCe304770236f39F9911BfCC51afBdfF3b8635718",
|
|
4258
4278
|
Host: "0x7F0165140D0f3251c8f6465e94E9d12C7FD40711",
|
|
4259
|
-
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
4279
|
+
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
4280
|
+
UniswapV4PositionManager: "0x1b35d13a2e2528f192637f14b05f0dc0e7deb566",
|
|
4281
|
+
UniswapV4PoolManager: "0x360e68faccca8ca495c1b759fd9eee466db9fb32"
|
|
4260
4282
|
},
|
|
4261
4283
|
defaultRpcUrl: "https://rpc.soneium.org",
|
|
4262
4284
|
consensusStateId: "ETH0",
|
|
@@ -4450,6 +4472,9 @@ var ChainConfigService = class {
|
|
|
4450
4472
|
getUniswapRouterV2Address(chain) {
|
|
4451
4473
|
return this.getConfig(chain)?.addresses.UniswapRouter02 ?? "0x";
|
|
4452
4474
|
}
|
|
4475
|
+
getAerodromeRouterAddress(chain) {
|
|
4476
|
+
return this.getConfig(chain)?.addresses.AerodromeRouter ?? "0x";
|
|
4477
|
+
}
|
|
4453
4478
|
getUniswapV2FactoryAddress(chain) {
|
|
4454
4479
|
return this.getConfig(chain)?.addresses.UniswapV2Factory ?? "0x";
|
|
4455
4480
|
}
|
|
@@ -4465,6 +4490,15 @@ var ChainConfigService = class {
|
|
|
4465
4490
|
getUniswapV4QuoterAddress(chain) {
|
|
4466
4491
|
return this.getConfig(chain)?.addresses.UniswapV4Quoter ?? "0x";
|
|
4467
4492
|
}
|
|
4493
|
+
getUniswapV4PositionManagerAddress(chain) {
|
|
4494
|
+
return this.getConfig(chain)?.addresses.UniswapV4PositionManager ?? "0x";
|
|
4495
|
+
}
|
|
4496
|
+
getUniswapV4PoolManagerAddress(chain) {
|
|
4497
|
+
return this.getConfig(chain)?.addresses.UniswapV4PoolManager ?? "0x";
|
|
4498
|
+
}
|
|
4499
|
+
getUniswapV4StateViewAddress(chain) {
|
|
4500
|
+
return this.getConfig(chain)?.addresses.UniswapV4StateView ?? "0x";
|
|
4501
|
+
}
|
|
4468
4502
|
getPermit2Address(chain) {
|
|
4469
4503
|
return this.getConfig(chain)?.addresses.Permit2 ?? "0x";
|
|
4470
4504
|
}
|
|
@@ -5548,6 +5582,7 @@ var EvmChain = class _EvmChain {
|
|
|
5548
5582
|
});
|
|
5549
5583
|
this.chainConfigService = new ChainConfigService();
|
|
5550
5584
|
}
|
|
5585
|
+
params;
|
|
5551
5586
|
publicClient;
|
|
5552
5587
|
chainConfigService;
|
|
5553
5588
|
/**
|
|
@@ -6148,6 +6183,7 @@ var HttpRpcClient = class {
|
|
|
6148
6183
|
constructor(url) {
|
|
6149
6184
|
this.url = url;
|
|
6150
6185
|
}
|
|
6186
|
+
url;
|
|
6151
6187
|
/**
|
|
6152
6188
|
* Make an RPC call over HTTP
|
|
6153
6189
|
* @param method - The RPC method name
|
|
@@ -6185,6 +6221,7 @@ var SubstrateChain = class _SubstrateChain {
|
|
|
6185
6221
|
const httpUrl = replaceWebsocketWithHttp(url);
|
|
6186
6222
|
this.rpcClient = new HttpRpcClient(httpUrl);
|
|
6187
6223
|
}
|
|
6224
|
+
params;
|
|
6188
6225
|
/*
|
|
6189
6226
|
* api: The Polkadot API instance for the Substrate chain.
|
|
6190
6227
|
*/
|
|
@@ -6702,6 +6739,9 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
6702
6739
|
this.substratePrivateKey = substratePrivateKey;
|
|
6703
6740
|
this.ownsConnection = ownsConnection;
|
|
6704
6741
|
}
|
|
6742
|
+
api;
|
|
6743
|
+
substratePrivateKey;
|
|
6744
|
+
ownsConnection;
|
|
6705
6745
|
/** Cached result of whether the node exposes intents_* RPC methods */
|
|
6706
6746
|
hasIntentsRpc = null;
|
|
6707
6747
|
/**
|
|
@@ -6979,6 +7019,7 @@ var TronChain = class _TronChain {
|
|
|
6979
7019
|
this.evm = evm;
|
|
6980
7020
|
this.tronWebInstance = new TronWeb({ fullHost: params.rpcUrl });
|
|
6981
7021
|
}
|
|
7022
|
+
params;
|
|
6982
7023
|
evm;
|
|
6983
7024
|
tronWebInstance;
|
|
6984
7025
|
/**
|
|
@@ -7519,6 +7560,7 @@ var SubstrateHttpRpc = class {
|
|
|
7519
7560
|
constructor(url) {
|
|
7520
7561
|
this.url = url;
|
|
7521
7562
|
}
|
|
7563
|
+
url;
|
|
7522
7564
|
async call(method, params = []) {
|
|
7523
7565
|
const body = JSON.stringify({
|
|
7524
7566
|
jsonrpc: "2.0",
|
|
@@ -7563,6 +7605,7 @@ var PolkadotHubChain = class _PolkadotHubChain {
|
|
|
7563
7605
|
this.evm = evm;
|
|
7564
7606
|
this.substrateRpc = new SubstrateHttpRpc(replaceWebsocketWithHttp(params.substrateRpcUrl));
|
|
7565
7607
|
}
|
|
7608
|
+
params;
|
|
7566
7609
|
evm;
|
|
7567
7610
|
substrateRpc;
|
|
7568
7611
|
static fromParams(params) {
|
|
@@ -12631,7 +12674,9 @@ var BundlerMethod = {
|
|
|
12631
12674
|
/** Estimates gas limits for a UserOperation before submission. */
|
|
12632
12675
|
ETH_ESTIMATE_USER_OPERATION_GAS: "eth_estimateUserOperationGas",
|
|
12633
12676
|
/** Pimlico-specific method to fetch recommended EIP-1559 gas prices for UserOperations. */
|
|
12634
|
-
PIMLICO_GET_USER_OPERATION_GAS_PRICE: "pimlico_getUserOperationGasPrice"
|
|
12677
|
+
PIMLICO_GET_USER_OPERATION_GAS_PRICE: "pimlico_getUserOperationGasPrice",
|
|
12678
|
+
/** Alchemy (Rundler) method to fetch recommended priority fee for UserOperations. */
|
|
12679
|
+
RUNDLER_MAX_PRIORITY_FEE_PER_GAS: "rundler_maxPriorityFeePerGas"
|
|
12635
12680
|
};
|
|
12636
12681
|
|
|
12637
12682
|
// src/protocols/intents/CryptoUtils.ts
|
|
@@ -12652,6 +12697,7 @@ var CryptoUtils = class {
|
|
|
12652
12697
|
constructor(ctx) {
|
|
12653
12698
|
this.ctx = ctx;
|
|
12654
12699
|
}
|
|
12700
|
+
ctx;
|
|
12655
12701
|
/**
|
|
12656
12702
|
* Computes an EIP-712 domain separator for a given contract.
|
|
12657
12703
|
*
|
|
@@ -15187,6 +15233,7 @@ var OrderPlacer = class {
|
|
|
15187
15233
|
constructor(ctx) {
|
|
15188
15234
|
this.ctx = ctx;
|
|
15189
15235
|
}
|
|
15236
|
+
ctx;
|
|
15190
15237
|
/**
|
|
15191
15238
|
* Bidirectional async generator that orchestrates order placement.
|
|
15192
15239
|
*
|
|
@@ -15264,66 +15311,40 @@ var OrderPlacer = class {
|
|
|
15264
15311
|
return { order, receipt };
|
|
15265
15312
|
}
|
|
15266
15313
|
};
|
|
15267
|
-
|
|
15268
|
-
// src/protocols/intents/OrderExecutor.ts
|
|
15269
15314
|
var USED_USEROPS_STORAGE_KEY = (commitment) => `used-userops:${commitment.toLowerCase()}`;
|
|
15270
15315
|
var OrderExecutor = class {
|
|
15271
|
-
/**
|
|
15272
|
-
* @param ctx - Shared IntentsV2 context providing the destination chain
|
|
15273
|
-
* client, coprocessor, bundler URL, and storage adapters.
|
|
15274
|
-
* @param bidManager - Handles bid validation, sorting, simulation, and
|
|
15275
|
-
* UserOperation submission.
|
|
15276
|
-
* @param crypto - Crypto utilities used to compute UserOperation hashes for
|
|
15277
|
-
* deduplication.
|
|
15278
|
-
*/
|
|
15279
15316
|
constructor(ctx, bidManager, crypto) {
|
|
15280
15317
|
this.ctx = ctx;
|
|
15281
15318
|
this.bidManager = bidManager;
|
|
15282
15319
|
this.crypto = crypto;
|
|
15283
15320
|
}
|
|
15321
|
+
ctx;
|
|
15322
|
+
bidManager;
|
|
15323
|
+
crypto;
|
|
15284
15324
|
/**
|
|
15285
|
-
*
|
|
15286
|
-
*
|
|
15287
|
-
* or an unrecoverable error occurs.
|
|
15288
|
-
*
|
|
15289
|
-
* **Status progression (cross-chain orders):**
|
|
15290
|
-
* `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED` → `USEROP_SUBMITTED`
|
|
15291
|
-
* then terminates (settlement is confirmed off-chain via Hyperbridge).
|
|
15292
|
-
*
|
|
15293
|
-
* **Status progression (same-chain orders):**
|
|
15294
|
-
* `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED` → `USEROP_SUBMITTED`
|
|
15295
|
-
* → (`FILLED` | `PARTIAL_FILL`)* → (`FILLED` | `PARTIAL_FILL_EXHAUSTED`)
|
|
15296
|
-
*
|
|
15297
|
-
* **Error statuses:** `FAILED` (fatal, no fills) or `PARTIAL_FILL_EXHAUSTED`
|
|
15298
|
-
* (deadline reached or no new bids after at least one partial fill).
|
|
15299
|
-
*
|
|
15300
|
-
* @param options - Execution parameters including the placed order, its
|
|
15301
|
-
* session private key, bid collection settings, and poll interval.
|
|
15302
|
-
* @yields {@link IntentOrderStatusUpdate} objects describing each stage.
|
|
15303
|
-
* @throws Never throws directly; all errors are reported as `FAILED` yields.
|
|
15325
|
+
* Sleeps until the order's block deadline is reached, then yields EXPIRED.
|
|
15326
|
+
* Uses the chain's block time to calculate the sleep duration.
|
|
15304
15327
|
*/
|
|
15305
|
-
async *
|
|
15306
|
-
const
|
|
15307
|
-
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
const commitment = order.id;
|
|
15315
|
-
const isSameChain = order.source === order.destination;
|
|
15316
|
-
if (!this.ctx.intentsCoprocessor) {
|
|
15317
|
-
yield { status: "FAILED", error: "IntentsCoprocessor required for order execution" };
|
|
15318
|
-
return;
|
|
15319
|
-
}
|
|
15320
|
-
if (!this.ctx.bundlerUrl) {
|
|
15321
|
-
yield { status: "FAILED", error: "Bundler URL not configured" };
|
|
15322
|
-
return;
|
|
15328
|
+
async *deadlineStream(deadline, commitment) {
|
|
15329
|
+
const client = this.ctx.dest.client;
|
|
15330
|
+
const blockTimeSeconds = client.chain?.blockTime ?? 2;
|
|
15331
|
+
while (true) {
|
|
15332
|
+
const currentBlock = await client.getBlockNumber();
|
|
15333
|
+
if (currentBlock >= deadline) break;
|
|
15334
|
+
const blocksRemaining = Number(deadline - currentBlock);
|
|
15335
|
+
const sleepMs = blocksRemaining * blockTimeSeconds * 1e3;
|
|
15336
|
+
await sleep(sleepMs);
|
|
15323
15337
|
}
|
|
15338
|
+
yield {
|
|
15339
|
+
status: "EXPIRED",
|
|
15340
|
+
commitment,
|
|
15341
|
+
error: "Order deadline reached"
|
|
15342
|
+
};
|
|
15343
|
+
}
|
|
15344
|
+
/** Loads the persisted deduplication set of already-submitted UserOp hashes for a given order commitment. */
|
|
15345
|
+
async loadUsedUserOps(commitment) {
|
|
15324
15346
|
const usedUserOps = /* @__PURE__ */ new Set();
|
|
15325
|
-
const
|
|
15326
|
-
const persisted = await this.ctx.usedUserOpsStorage.getItem(storageKey);
|
|
15347
|
+
const persisted = await this.ctx.usedUserOpsStorage.getItem(USED_USEROPS_STORAGE_KEY(commitment));
|
|
15327
15348
|
if (persisted) {
|
|
15328
15349
|
try {
|
|
15329
15350
|
const parsed = JSON.parse(persisted);
|
|
@@ -15333,83 +15354,210 @@ var OrderExecutor = class {
|
|
|
15333
15354
|
} catch {
|
|
15334
15355
|
}
|
|
15335
15356
|
}
|
|
15336
|
-
|
|
15337
|
-
|
|
15338
|
-
|
|
15357
|
+
return usedUserOps;
|
|
15358
|
+
}
|
|
15359
|
+
/** Persists the deduplication set of UserOp hashes to storage. */
|
|
15360
|
+
async persistUsedUserOps(commitment, usedUserOps) {
|
|
15361
|
+
await this.ctx.usedUserOpsStorage.setItem(
|
|
15362
|
+
USED_USEROPS_STORAGE_KEY(commitment),
|
|
15363
|
+
JSON.stringify([...usedUserOps])
|
|
15364
|
+
);
|
|
15365
|
+
}
|
|
15366
|
+
/**
|
|
15367
|
+
* Creates a closure that computes the deduplication hash key for a
|
|
15368
|
+
* UserOperation, pre-bound to the order's destination chain and entry point.
|
|
15369
|
+
*/
|
|
15370
|
+
createUserOpHasher(order) {
|
|
15339
15371
|
const entryPointAddress = this.ctx.dest.configService.getEntryPointV08Address(hexToString(order.destination));
|
|
15340
15372
|
const chainId = BigInt(
|
|
15341
15373
|
this.ctx.dest.client.chain?.id ?? Number.parseInt(this.ctx.dest.config.stateMachineId.split("-")[1])
|
|
15342
15374
|
);
|
|
15343
|
-
|
|
15375
|
+
return (userOp) => this.crypto.computeUserOpHash(userOp, entryPointAddress, chainId);
|
|
15376
|
+
}
|
|
15377
|
+
/**
|
|
15378
|
+
* Fetches bids from the coprocessor for a given order commitment.
|
|
15379
|
+
* If a preferred solver is configured and the solver lock has not expired,
|
|
15380
|
+
* only bids from that solver are returned.
|
|
15381
|
+
*/
|
|
15382
|
+
async fetchBids(params) {
|
|
15383
|
+
const { commitment, solver, solverLockStartTime } = params;
|
|
15384
|
+
const fetchedBids = await this.ctx.intentsCoprocessor.getBidsForOrder(commitment);
|
|
15385
|
+
if (solver) {
|
|
15386
|
+
const { address, timeoutMs } = solver;
|
|
15387
|
+
const solverLockActive = Date.now() - solverLockStartTime < timeoutMs;
|
|
15388
|
+
return solverLockActive ? fetchedBids.filter((bid) => bid.userOp.sender.toLowerCase() === address.toLowerCase()) : fetchedBids;
|
|
15389
|
+
}
|
|
15390
|
+
return fetchedBids;
|
|
15391
|
+
}
|
|
15392
|
+
/**
|
|
15393
|
+
* Selects the best bid from the provided candidates, submits the
|
|
15394
|
+
* UserOperation, and persists the dedup entry to prevent resubmission.
|
|
15395
|
+
*/
|
|
15396
|
+
async submitBid(params) {
|
|
15397
|
+
const { order, freshBids, sessionPrivateKey, commitment, usedUserOps, userOpHashKey } = params;
|
|
15398
|
+
const result = await this.bidManager.selectBid(order, freshBids, sessionPrivateKey);
|
|
15399
|
+
usedUserOps.add(userOpHashKey(result.userOp));
|
|
15400
|
+
await this.persistUsedUserOps(commitment, usedUserOps);
|
|
15401
|
+
return result;
|
|
15402
|
+
}
|
|
15403
|
+
/**
|
|
15404
|
+
* Processes a fill result and returns updated fill accumulators,
|
|
15405
|
+
* the status update to yield (if any), and whether the order is
|
|
15406
|
+
* fully satisfied.
|
|
15407
|
+
*/
|
|
15408
|
+
processFillResult(result, commitment, targetAssets, totalFilledAssets, remainingAssets) {
|
|
15409
|
+
if (result.fillStatus === "full") {
|
|
15410
|
+
totalFilledAssets = targetAssets.map((a) => ({ token: a.token, amount: a.amount }));
|
|
15411
|
+
remainingAssets = targetAssets.map((a) => ({ token: a.token, amount: 0n }));
|
|
15412
|
+
return {
|
|
15413
|
+
update: {
|
|
15414
|
+
status: "FILLED",
|
|
15415
|
+
commitment,
|
|
15416
|
+
userOpHash: result.userOpHash,
|
|
15417
|
+
selectedSolver: result.solverAddress,
|
|
15418
|
+
transactionHash: result.txnHash,
|
|
15419
|
+
totalFilledAssets,
|
|
15420
|
+
remainingAssets
|
|
15421
|
+
},
|
|
15422
|
+
done: true,
|
|
15423
|
+
totalFilledAssets,
|
|
15424
|
+
remainingAssets
|
|
15425
|
+
};
|
|
15426
|
+
}
|
|
15427
|
+
if (result.fillStatus === "partial") {
|
|
15428
|
+
const filledAssets = result.filledAssets ?? [];
|
|
15429
|
+
totalFilledAssets = totalFilledAssets.map((a) => {
|
|
15430
|
+
const filled = filledAssets.find((f) => f.token === a.token);
|
|
15431
|
+
return filled ? { token: a.token, amount: a.amount + filled.amount } : { ...a };
|
|
15432
|
+
});
|
|
15433
|
+
remainingAssets = targetAssets.map((target) => {
|
|
15434
|
+
const filled = totalFilledAssets.find((a) => a.token === target.token);
|
|
15435
|
+
const filledAmt = filled?.amount ?? 0n;
|
|
15436
|
+
return {
|
|
15437
|
+
token: target.token,
|
|
15438
|
+
amount: filledAmt >= target.amount ? 0n : target.amount - filledAmt
|
|
15439
|
+
};
|
|
15440
|
+
});
|
|
15441
|
+
const fullyFilled = remainingAssets.every((a) => a.amount === 0n);
|
|
15442
|
+
return {
|
|
15443
|
+
update: fullyFilled ? {
|
|
15444
|
+
status: "FILLED",
|
|
15445
|
+
commitment,
|
|
15446
|
+
userOpHash: result.userOpHash,
|
|
15447
|
+
selectedSolver: result.solverAddress,
|
|
15448
|
+
transactionHash: result.txnHash,
|
|
15449
|
+
totalFilledAssets,
|
|
15450
|
+
remainingAssets
|
|
15451
|
+
} : {
|
|
15452
|
+
status: "PARTIAL_FILL",
|
|
15453
|
+
commitment,
|
|
15454
|
+
userOpHash: result.userOpHash,
|
|
15455
|
+
selectedSolver: result.solverAddress,
|
|
15456
|
+
transactionHash: result.txnHash,
|
|
15457
|
+
filledAssets,
|
|
15458
|
+
totalFilledAssets,
|
|
15459
|
+
remainingAssets
|
|
15460
|
+
},
|
|
15461
|
+
done: fullyFilled,
|
|
15462
|
+
totalFilledAssets,
|
|
15463
|
+
remainingAssets
|
|
15464
|
+
};
|
|
15465
|
+
}
|
|
15466
|
+
return { update: null, done: false, totalFilledAssets, remainingAssets };
|
|
15467
|
+
}
|
|
15468
|
+
/**
|
|
15469
|
+
* Executes an intent order by racing bid polling against the order's
|
|
15470
|
+
* block deadline. Yields status updates at each lifecycle stage.
|
|
15471
|
+
*
|
|
15472
|
+
* **Same-chain:** `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED`
|
|
15473
|
+
* → (`FILLED` | `PARTIAL_FILL`)* → (`FILLED` | `EXPIRED`)
|
|
15474
|
+
*
|
|
15475
|
+
* **Cross-chain:** `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED`
|
|
15476
|
+
* (terminates — settlement is confirmed async via Hyperbridge)
|
|
15477
|
+
*/
|
|
15478
|
+
async *executeOrder(options) {
|
|
15479
|
+
const { order, sessionPrivateKey, minBids = 1, pollIntervalMs = DEFAULT_POLL_INTERVAL, solver } = options;
|
|
15480
|
+
const commitment = order.id;
|
|
15481
|
+
const isSameChain = order.source === order.destination;
|
|
15482
|
+
if (!this.ctx.intentsCoprocessor) {
|
|
15483
|
+
yield { status: "FAILED", error: "IntentsCoprocessor required for order execution" };
|
|
15484
|
+
return;
|
|
15485
|
+
}
|
|
15486
|
+
if (!this.ctx.bundlerUrl) {
|
|
15487
|
+
yield { status: "FAILED", error: "Bundler URL not configured" };
|
|
15488
|
+
return;
|
|
15489
|
+
}
|
|
15490
|
+
const usedUserOps = await this.loadUsedUserOps(commitment);
|
|
15491
|
+
const userOpHashKey = this.createUserOpHasher(order);
|
|
15344
15492
|
const targetAssets = order.output.assets.map((a) => ({ token: a.token, amount: a.amount }));
|
|
15345
15493
|
let totalFilledAssets = order.output.assets.map((a) => ({ token: a.token, amount: 0n }));
|
|
15346
15494
|
let remainingAssets = order.output.assets.map((a) => ({ token: a.token, amount: a.amount }));
|
|
15495
|
+
const executionStream = this.executionStream({
|
|
15496
|
+
order,
|
|
15497
|
+
sessionPrivateKey,
|
|
15498
|
+
commitment,
|
|
15499
|
+
minBids,
|
|
15500
|
+
pollIntervalMs,
|
|
15501
|
+
solver,
|
|
15502
|
+
usedUserOps,
|
|
15503
|
+
userOpHashKey,
|
|
15504
|
+
targetAssets,
|
|
15505
|
+
totalFilledAssets,
|
|
15506
|
+
remainingAssets
|
|
15507
|
+
});
|
|
15508
|
+
const deadlineTimeout = this.deadlineStream(order.deadline, commitment);
|
|
15509
|
+
const combined = mergeRace(deadlineTimeout, executionStream);
|
|
15510
|
+
for await (const update of combined) {
|
|
15511
|
+
yield update;
|
|
15512
|
+
if (update.status === "EXPIRED" || update.status === "FILLED") return;
|
|
15513
|
+
if (update.status === "BID_SELECTED" && !isSameChain) return;
|
|
15514
|
+
}
|
|
15515
|
+
}
|
|
15516
|
+
/**
|
|
15517
|
+
* Core execution loop that polls for bids, submits UserOperations,
|
|
15518
|
+
* and tracks fill progress. Yields between each poll iteration so
|
|
15519
|
+
* that `mergeRace` can interleave the deadline stream.
|
|
15520
|
+
*/
|
|
15521
|
+
async *executionStream(params) {
|
|
15522
|
+
const {
|
|
15523
|
+
order,
|
|
15524
|
+
sessionPrivateKey,
|
|
15525
|
+
commitment,
|
|
15526
|
+
minBids,
|
|
15527
|
+
pollIntervalMs,
|
|
15528
|
+
solver,
|
|
15529
|
+
usedUserOps,
|
|
15530
|
+
userOpHashKey,
|
|
15531
|
+
targetAssets
|
|
15532
|
+
} = params;
|
|
15533
|
+
let { totalFilledAssets, remainingAssets } = params;
|
|
15534
|
+
const solverLockStartTime = Date.now();
|
|
15535
|
+
yield { status: "AWAITING_BIDS", commitment, totalFilledAssets, remainingAssets };
|
|
15347
15536
|
try {
|
|
15348
15537
|
while (true) {
|
|
15349
|
-
|
|
15350
|
-
|
|
15351
|
-
const
|
|
15352
|
-
|
|
15353
|
-
|
|
15354
|
-
yield {
|
|
15355
|
-
status: "PARTIAL_FILL_EXHAUSTED",
|
|
15356
|
-
commitment,
|
|
15357
|
-
totalFilledAssets,
|
|
15358
|
-
remainingAssets,
|
|
15359
|
-
error: deadlineError
|
|
15360
|
-
};
|
|
15361
|
-
} else {
|
|
15362
|
-
yield { status: "FAILED", commitment, error: deadlineError };
|
|
15363
|
-
}
|
|
15364
|
-
return;
|
|
15365
|
-
}
|
|
15366
|
-
yield { status: "AWAITING_BIDS", commitment, totalFilledAssets, remainingAssets };
|
|
15367
|
-
const startTime = Date.now();
|
|
15368
|
-
let bids = [];
|
|
15369
|
-
let solverLockExpired = false;
|
|
15370
|
-
while (Date.now() - startTime < bidTimeoutMs) {
|
|
15371
|
-
try {
|
|
15372
|
-
const fetchedBids = await this.ctx.intentsCoprocessor.getBidsForOrder(commitment);
|
|
15373
|
-
if (solver) {
|
|
15374
|
-
const { address, timeoutMs } = solver;
|
|
15375
|
-
const solverLockActive = Date.now() - startTime < timeoutMs;
|
|
15376
|
-
if (!solverLockActive) solverLockExpired = true;
|
|
15377
|
-
bids = solverLockActive ? fetchedBids.filter((bid) => bid.userOp.sender.toLowerCase() === address.toLowerCase()) : fetchedBids;
|
|
15378
|
-
} else {
|
|
15379
|
-
bids = fetchedBids;
|
|
15380
|
-
}
|
|
15381
|
-
if (bids.length >= minBids) {
|
|
15382
|
-
break;
|
|
15383
|
-
}
|
|
15384
|
-
} catch {
|
|
15385
|
-
}
|
|
15538
|
+
let freshBids;
|
|
15539
|
+
try {
|
|
15540
|
+
const bids = await this.fetchBids({ commitment, solver, solverLockStartTime });
|
|
15541
|
+
freshBids = bids.filter((bid) => !usedUserOps.has(userOpHashKey(bid.userOp)));
|
|
15542
|
+
} catch {
|
|
15386
15543
|
await sleep(pollIntervalMs);
|
|
15544
|
+
continue;
|
|
15387
15545
|
}
|
|
15388
|
-
|
|
15389
|
-
|
|
15390
|
-
|
|
15391
|
-
});
|
|
15392
|
-
if (freshBids.length === 0) {
|
|
15393
|
-
const isPartiallyFilled = totalFilledAssets.some((a) => a.amount > 0n);
|
|
15394
|
-
const solverClause = solver && !solverLockExpired ? ` for requested solver ${solver.address}` : "";
|
|
15395
|
-
const noBidsError = isPartiallyFilled ? `No new bids${solverClause} after partial fill` : `No new bids${solverClause} available within ${bidTimeoutMs}ms timeout`;
|
|
15396
|
-
if (isPartiallyFilled) {
|
|
15397
|
-
yield {
|
|
15398
|
-
status: "PARTIAL_FILL_EXHAUSTED",
|
|
15399
|
-
commitment,
|
|
15400
|
-
totalFilledAssets,
|
|
15401
|
-
remainingAssets,
|
|
15402
|
-
error: noBidsError
|
|
15403
|
-
};
|
|
15404
|
-
} else {
|
|
15405
|
-
yield { status: "FAILED", commitment, error: noBidsError };
|
|
15406
|
-
}
|
|
15407
|
-
return;
|
|
15546
|
+
if (freshBids.length < minBids) {
|
|
15547
|
+
await sleep(pollIntervalMs);
|
|
15548
|
+
continue;
|
|
15408
15549
|
}
|
|
15409
15550
|
yield { status: "BIDS_RECEIVED", commitment, bidCount: freshBids.length, bids: freshBids };
|
|
15410
|
-
let
|
|
15551
|
+
let submitResult;
|
|
15411
15552
|
try {
|
|
15412
|
-
|
|
15553
|
+
submitResult = await this.submitBid({
|
|
15554
|
+
order,
|
|
15555
|
+
freshBids,
|
|
15556
|
+
sessionPrivateKey,
|
|
15557
|
+
commitment,
|
|
15558
|
+
usedUserOps,
|
|
15559
|
+
userOpHashKey
|
|
15560
|
+
});
|
|
15413
15561
|
} catch (err) {
|
|
15414
15562
|
yield {
|
|
15415
15563
|
status: "FAILED",
|
|
@@ -15418,76 +15566,29 @@ var OrderExecutor = class {
|
|
|
15418
15566
|
remainingAssets,
|
|
15419
15567
|
error: `Failed to select bid and submit: ${err instanceof Error ? err.message : String(err)}`
|
|
15420
15568
|
};
|
|
15421
|
-
|
|
15569
|
+
await sleep(pollIntervalMs);
|
|
15570
|
+
continue;
|
|
15422
15571
|
}
|
|
15423
|
-
const usedKey = userOpHashKey(result.userOp);
|
|
15424
|
-
usedUserOps.add(usedKey);
|
|
15425
|
-
await persistUsedUserOps();
|
|
15426
15572
|
yield {
|
|
15427
15573
|
status: "BID_SELECTED",
|
|
15428
15574
|
commitment,
|
|
15429
|
-
selectedSolver:
|
|
15430
|
-
userOpHash:
|
|
15431
|
-
userOp:
|
|
15575
|
+
selectedSolver: submitResult.solverAddress,
|
|
15576
|
+
userOpHash: submitResult.userOpHash,
|
|
15577
|
+
userOp: submitResult.userOp,
|
|
15578
|
+
transactionHash: submitResult.txnHash
|
|
15432
15579
|
};
|
|
15433
|
-
|
|
15434
|
-
|
|
15580
|
+
const fill = this.processFillResult(
|
|
15581
|
+
submitResult,
|
|
15435
15582
|
commitment,
|
|
15436
|
-
|
|
15437
|
-
|
|
15438
|
-
|
|
15439
|
-
|
|
15440
|
-
|
|
15441
|
-
|
|
15442
|
-
|
|
15443
|
-
|
|
15444
|
-
|
|
15445
|
-
remainingAssets = targetAssets.map((a) => ({ token: a.token, amount: 0n }));
|
|
15446
|
-
yield {
|
|
15447
|
-
status: "FILLED",
|
|
15448
|
-
commitment,
|
|
15449
|
-
userOpHash: result.userOpHash,
|
|
15450
|
-
selectedSolver: result.solverAddress,
|
|
15451
|
-
transactionHash: result.txnHash,
|
|
15452
|
-
totalFilledAssets,
|
|
15453
|
-
remainingAssets
|
|
15454
|
-
};
|
|
15455
|
-
return;
|
|
15456
|
-
}
|
|
15457
|
-
if (result.fillStatus === "partial") {
|
|
15458
|
-
const filledAssets = result.filledAssets ?? [];
|
|
15459
|
-
for (const filled of filledAssets) {
|
|
15460
|
-
const entry = totalFilledAssets.find((a) => a.token === filled.token);
|
|
15461
|
-
if (entry) entry.amount += filled.amount;
|
|
15462
|
-
}
|
|
15463
|
-
remainingAssets = targetAssets.map((target) => {
|
|
15464
|
-
const filled = totalFilledAssets.find((a) => a.token === target.token);
|
|
15465
|
-
const filledAmt = filled?.amount ?? 0n;
|
|
15466
|
-
return { token: target.token, amount: filledAmt >= target.amount ? 0n : target.amount - filledAmt };
|
|
15467
|
-
});
|
|
15468
|
-
const fullyFilled = remainingAssets.every((a) => a.amount === 0n);
|
|
15469
|
-
if (fullyFilled) {
|
|
15470
|
-
yield {
|
|
15471
|
-
status: "FILLED",
|
|
15472
|
-
commitment,
|
|
15473
|
-
userOpHash: result.userOpHash,
|
|
15474
|
-
selectedSolver: result.solverAddress,
|
|
15475
|
-
transactionHash: result.txnHash,
|
|
15476
|
-
totalFilledAssets,
|
|
15477
|
-
remainingAssets
|
|
15478
|
-
};
|
|
15479
|
-
return;
|
|
15480
|
-
}
|
|
15481
|
-
yield {
|
|
15482
|
-
status: "PARTIAL_FILL",
|
|
15483
|
-
commitment,
|
|
15484
|
-
userOpHash: result.userOpHash,
|
|
15485
|
-
selectedSolver: result.solverAddress,
|
|
15486
|
-
transactionHash: result.txnHash,
|
|
15487
|
-
filledAssets,
|
|
15488
|
-
totalFilledAssets,
|
|
15489
|
-
remainingAssets
|
|
15490
|
-
};
|
|
15583
|
+
targetAssets,
|
|
15584
|
+
totalFilledAssets,
|
|
15585
|
+
remainingAssets
|
|
15586
|
+
);
|
|
15587
|
+
totalFilledAssets = fill.totalFilledAssets;
|
|
15588
|
+
remainingAssets = fill.remainingAssets;
|
|
15589
|
+
if (fill.update) {
|
|
15590
|
+
yield fill.update;
|
|
15591
|
+
if (fill.done) return;
|
|
15491
15592
|
}
|
|
15492
15593
|
}
|
|
15493
15594
|
} catch (err) {
|
|
@@ -15507,6 +15608,7 @@ var OrderCanceller = class {
|
|
|
15507
15608
|
constructor(ctx) {
|
|
15508
15609
|
this.ctx = ctx;
|
|
15509
15610
|
}
|
|
15611
|
+
ctx;
|
|
15510
15612
|
/**
|
|
15511
15613
|
* Returns both the native token cost and the relayer fee for cancelling an
|
|
15512
15614
|
* order. Frontends can use `relayerFee` to approve the ERC-20 spend before
|
|
@@ -15976,6 +16078,8 @@ var BidManager = class {
|
|
|
15976
16078
|
this.ctx = ctx;
|
|
15977
16079
|
this.crypto = crypto;
|
|
15978
16080
|
}
|
|
16081
|
+
ctx;
|
|
16082
|
+
crypto;
|
|
15979
16083
|
/**
|
|
15980
16084
|
* Constructs a signed `PackedUserOperation` that a solver can submit to the
|
|
15981
16085
|
* Hyperbridge coprocessor as a bid to fill an order.
|
|
@@ -18055,6 +18159,8 @@ var GasEstimator = class {
|
|
|
18055
18159
|
this.ctx = ctx;
|
|
18056
18160
|
this.crypto = crypto;
|
|
18057
18161
|
}
|
|
18162
|
+
ctx;
|
|
18163
|
+
crypto;
|
|
18058
18164
|
/**
|
|
18059
18165
|
* Estimates the gas cost for a solver to fill the given order and returns
|
|
18060
18166
|
* a structured estimate with individual gas components and total costs in
|
|
@@ -18089,11 +18195,13 @@ var GasEstimator = class {
|
|
|
18089
18195
|
const entryPointAddress = this.ctx.dest.configService.getEntryPointV08Address(destStateMachineId);
|
|
18090
18196
|
const chainId = BigInt(Number.parseInt(destStateMachineId.split("-")[1]));
|
|
18091
18197
|
const totalEthValue = order.output.assets.filter((output) => bytes32ToBytes20(output.token) === ADDRESS_ZERO2).reduce((sum, output) => sum + output.amount, 0n);
|
|
18092
|
-
const [sourceFeeToken, destFeeToken, gasPrice] = await Promise.all([
|
|
18198
|
+
const [sourceFeeToken, destFeeToken, gasPrice, latestBlock] = await Promise.all([
|
|
18093
18199
|
getFeeToken(this.ctx, this.ctx.source.config.stateMachineId, this.ctx.source),
|
|
18094
18200
|
getFeeToken(this.ctx, this.ctx.dest.config.stateMachineId, this.ctx.dest),
|
|
18095
|
-
this.ctx.dest.client.getGasPrice()
|
|
18201
|
+
this.ctx.dest.client.getGasPrice(),
|
|
18202
|
+
this.ctx.dest.client.getBlock({ blockTag: "latest" })
|
|
18096
18203
|
]);
|
|
18204
|
+
const baseFeePerGas = latestBlock.baseFeePerGas ?? gasPrice;
|
|
18097
18205
|
const feeTokenAsBytes32 = bytes20ToBytes32(destFeeToken.address);
|
|
18098
18206
|
const assetsForOverrides = [...order.output.assets];
|
|
18099
18207
|
if (!assetsForOverrides.some((asset) => asset.token.toLowerCase() === feeTokenAsBytes32.toLowerCase())) {
|
|
@@ -18141,6 +18249,7 @@ var GasEstimator = class {
|
|
|
18141
18249
|
if (this.ctx.bundlerUrl) {
|
|
18142
18250
|
try {
|
|
18143
18251
|
const callData = this.crypto.encodeERC7821Execute([
|
|
18252
|
+
...params.prependCalls ?? [],
|
|
18144
18253
|
{ target: intentGatewayV2Address, value: totalNativeValue, data: fillOrderCalldata }
|
|
18145
18254
|
]);
|
|
18146
18255
|
const accountGasLimits = this.crypto.packGasLimits(100000n, callGasLimit);
|
|
@@ -18182,7 +18291,9 @@ var GasEstimator = class {
|
|
|
18182
18291
|
sessionSignature
|
|
18183
18292
|
]);
|
|
18184
18293
|
const bundlerUserOp = this.crypto.prepareBundlerCall(preliminaryUserOp);
|
|
18185
|
-
const
|
|
18294
|
+
const bundlerUrlLower = this.ctx.bundlerUrl.toLowerCase();
|
|
18295
|
+
const isPimlico = bundlerUrlLower.includes("pimlico.io");
|
|
18296
|
+
const isAlchemy = bundlerUrlLower.includes("alchemy.com");
|
|
18186
18297
|
const bundlerRequests = [
|
|
18187
18298
|
{
|
|
18188
18299
|
method: BundlerMethod.ETH_ESTIMATE_USER_OPERATION_GAS,
|
|
@@ -18195,14 +18306,24 @@ var GasEstimator = class {
|
|
|
18195
18306
|
params: []
|
|
18196
18307
|
});
|
|
18197
18308
|
}
|
|
18309
|
+
if (isAlchemy) {
|
|
18310
|
+
bundlerRequests.push({
|
|
18311
|
+
method: BundlerMethod.RUNDLER_MAX_PRIORITY_FEE_PER_GAS,
|
|
18312
|
+
params: []
|
|
18313
|
+
});
|
|
18314
|
+
}
|
|
18198
18315
|
let gasEstimate;
|
|
18199
18316
|
let pimlicoGasPrices = null;
|
|
18317
|
+
let alchemyMaxPriorityFee = null;
|
|
18200
18318
|
try {
|
|
18201
18319
|
const batchResults = await this.crypto.sendBundlerBatch(bundlerRequests);
|
|
18202
18320
|
gasEstimate = batchResults[0];
|
|
18203
18321
|
if (isPimlico && batchResults.length > 1) {
|
|
18204
18322
|
pimlicoGasPrices = batchResults[1];
|
|
18205
18323
|
}
|
|
18324
|
+
if (isAlchemy && batchResults.length > 1) {
|
|
18325
|
+
alchemyMaxPriorityFee = batchResults[1];
|
|
18326
|
+
}
|
|
18206
18327
|
} catch {
|
|
18207
18328
|
gasEstimate = await this.crypto.sendBundler(
|
|
18208
18329
|
BundlerMethod.ETH_ESTIMATE_USER_OPERATION_GAS,
|
|
@@ -18221,6 +18342,14 @@ var GasEstimator = class {
|
|
|
18221
18342
|
maxPriorityFeePerGas = pimMaxPriorityFeePerGas + pimMaxPriorityFeePerGas * BigInt(priorityFeeBumpPercent) / 100n;
|
|
18222
18343
|
}
|
|
18223
18344
|
}
|
|
18345
|
+
if (alchemyMaxPriorityFee) {
|
|
18346
|
+
const rundlerPriorityFee = BigInt(alchemyMaxPriorityFee);
|
|
18347
|
+
const isArbitrum = chainId === 42161n;
|
|
18348
|
+
const alchemyPrioBump = isArbitrum ? 0n : 25n;
|
|
18349
|
+
maxPriorityFeePerGas = rundlerPriorityFee + rundlerPriorityFee * alchemyPrioBump / 100n;
|
|
18350
|
+
const bufferedBaseFee = baseFeePerGas + baseFeePerGas * 50n / 100n;
|
|
18351
|
+
maxFeePerGas = bufferedBaseFee + maxPriorityFeePerGas;
|
|
18352
|
+
}
|
|
18224
18353
|
} catch (e) {
|
|
18225
18354
|
console.warn("Bundler gas estimation failed, using fallback values:", e);
|
|
18226
18355
|
}
|
|
@@ -18453,6 +18582,7 @@ var OrderStatusChecker = class {
|
|
|
18453
18582
|
constructor(ctx) {
|
|
18454
18583
|
this.ctx = ctx;
|
|
18455
18584
|
}
|
|
18585
|
+
ctx;
|
|
18456
18586
|
/**
|
|
18457
18587
|
* Checks if a V2 order has been filled by reading the commitment storage slot on the destination chain.
|
|
18458
18588
|
*
|
|
@@ -18634,7 +18764,7 @@ var IntentGateway = class _IntentGateway {
|
|
|
18634
18764
|
* The caller must sign the transaction and pass it back via `gen.next(signedTx)`.
|
|
18635
18765
|
* 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
|
|
18636
18766
|
* the `OrderPlaced` event is confirmed.
|
|
18637
|
-
* 4. Delegates to {@link OrderExecutor.
|
|
18767
|
+
* 4. Delegates to {@link OrderExecutor.executeOrder} and forwards all
|
|
18638
18768
|
* subsequent status updates until the order is filled, exhausted, or fails.
|
|
18639
18769
|
*
|
|
18640
18770
|
* @param order - The order to place and execute. `order.fees` may be 0; it
|
|
@@ -18645,7 +18775,6 @@ var IntentGateway = class _IntentGateway {
|
|
|
18645
18775
|
* - `maxPriorityFeePerGasBumpPercent` — bump % for the priority fee estimate (default 8).
|
|
18646
18776
|
* - `maxFeePerGasBumpPercent` — bump % for the max fee estimate (default 10).
|
|
18647
18777
|
* - `minBids` — minimum bids to collect before selecting (default 1).
|
|
18648
|
-
* - `bidTimeoutMs` — how long to poll for bids before giving up (default 60 000 ms).
|
|
18649
18778
|
* - `pollIntervalMs` — interval between bid-polling attempts.
|
|
18650
18779
|
* @yields {@link IntentOrderStatusUpdate} at each lifecycle stage.
|
|
18651
18780
|
* @throws If the `placeOrder` generator behaves unexpectedly, or if gas
|
|
@@ -18678,11 +18807,10 @@ var IntentGateway = class _IntentGateway {
|
|
|
18678
18807
|
}
|
|
18679
18808
|
const { order: finalizedOrder, receipt: placementReceipt } = placeOrderSecond.value;
|
|
18680
18809
|
yield { status: "ORDER_PLACED", order: finalizedOrder, receipt: placementReceipt };
|
|
18681
|
-
for await (const status of this.orderExecutor.
|
|
18810
|
+
for await (const status of this.orderExecutor.executeOrder({
|
|
18682
18811
|
order: finalizedOrder,
|
|
18683
18812
|
sessionPrivateKey,
|
|
18684
18813
|
minBids: options?.minBids,
|
|
18685
|
-
bidTimeoutMs: options?.bidTimeoutMs,
|
|
18686
18814
|
pollIntervalMs: options?.pollIntervalMs,
|
|
18687
18815
|
solver: options?.solver
|
|
18688
18816
|
})) {
|
|
@@ -18690,6 +18818,52 @@ var IntentGateway = class _IntentGateway {
|
|
|
18690
18818
|
}
|
|
18691
18819
|
return;
|
|
18692
18820
|
}
|
|
18821
|
+
/**
|
|
18822
|
+
* Validates that an order has the minimum fields required for post-placement
|
|
18823
|
+
* resume (i.e. it was previously placed and has an on-chain identity).
|
|
18824
|
+
*
|
|
18825
|
+
* @throws If `order.id` or `order.session` is missing or zero-valued.
|
|
18826
|
+
*/
|
|
18827
|
+
assertOrderCanResume(order) {
|
|
18828
|
+
if (!order.id) {
|
|
18829
|
+
throw new Error("Cannot resume execution without order.id");
|
|
18830
|
+
}
|
|
18831
|
+
if (!order.session || order.session === ADDRESS_ZERO2) {
|
|
18832
|
+
throw new Error("Cannot resume execution without order.session");
|
|
18833
|
+
}
|
|
18834
|
+
}
|
|
18835
|
+
/**
|
|
18836
|
+
* Resumes execution of a previously placed order.
|
|
18837
|
+
*
|
|
18838
|
+
* Use this method after an app restart or crash to pick up where
|
|
18839
|
+
* {@link execute} left off. The order must already be placed on-chain
|
|
18840
|
+
* (i.e. it must have a valid `id` and `session`).
|
|
18841
|
+
*
|
|
18842
|
+
* Internally delegates to {@link OrderExecutor.executeOrder} and
|
|
18843
|
+
* yields the same status updates as the execution phase of {@link execute}:
|
|
18844
|
+
* `AWAITING_BIDS`, `BIDS_RECEIVED`, `BID_SELECTED`,
|
|
18845
|
+
* `FILLED`, `PARTIAL_FILL`, `EXPIRED`, or `FAILED`.
|
|
18846
|
+
*
|
|
18847
|
+
* Callers may check {@link isOrderFilled} or {@link isOrderRefunded} before
|
|
18848
|
+
* calling this method to avoid resuming an already-terminal order.
|
|
18849
|
+
*
|
|
18850
|
+
* @param order - A previously placed order with a valid `id` and `session`.
|
|
18851
|
+
* @param options - Optional tuning parameters for bid collection and execution.
|
|
18852
|
+
* @yields {@link IntentOrderStatusUpdate} at each execution stage.
|
|
18853
|
+
* @throws If the order is missing required fields for resumption.
|
|
18854
|
+
*/
|
|
18855
|
+
async *resume(order, options) {
|
|
18856
|
+
this.assertOrderCanResume(order);
|
|
18857
|
+
for await (const status of this.orderExecutor.executeOrder({
|
|
18858
|
+
order,
|
|
18859
|
+
sessionPrivateKey: options?.sessionPrivateKey,
|
|
18860
|
+
minBids: options?.minBids,
|
|
18861
|
+
pollIntervalMs: options?.pollIntervalMs,
|
|
18862
|
+
solver: options?.solver
|
|
18863
|
+
})) {
|
|
18864
|
+
yield status;
|
|
18865
|
+
}
|
|
18866
|
+
}
|
|
18693
18867
|
/**
|
|
18694
18868
|
* Returns both the native token cost and the relayer fee for cancelling an
|
|
18695
18869
|
* order. Use `relayerFee` to approve the ERC-20 spend before submitting.
|