@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/node/index.js
CHANGED
|
@@ -556,10 +556,9 @@ var IntentOrderStatus = Object.freeze({
|
|
|
556
556
|
AWAITING_BIDS: "AWAITING_BIDS",
|
|
557
557
|
BIDS_RECEIVED: "BIDS_RECEIVED",
|
|
558
558
|
BID_SELECTED: "BID_SELECTED",
|
|
559
|
-
USEROP_SUBMITTED: "USEROP_SUBMITTED",
|
|
560
559
|
FILLED: "FILLED",
|
|
561
560
|
PARTIAL_FILL: "PARTIAL_FILL",
|
|
562
|
-
|
|
561
|
+
EXPIRED: "EXPIRED",
|
|
563
562
|
FAILED: "FAILED"
|
|
564
563
|
});
|
|
565
564
|
|
|
@@ -3787,6 +3786,9 @@ var chainConfigs = {
|
|
|
3787
3786
|
UniversalRouter: "0x66a9893cc07d91d95644aedd05d03f95e1dba8af",
|
|
3788
3787
|
UniswapV3Quoter: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
|
|
3789
3788
|
UniswapV4Quoter: "0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203",
|
|
3789
|
+
UniswapV4PositionManager: "0xbd216513d74c8cf14cf4747e6aaa6420ff64ee9e",
|
|
3790
|
+
UniswapV4PoolManager: "0x000000000004444c5dc75cB358380D2e3dE08A90",
|
|
3791
|
+
UniswapV4StateView: "0x7ffe42c4a5deea5b0fec41c94c136cf115597227",
|
|
3790
3792
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
3791
3793
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
3792
3794
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
@@ -3839,6 +3841,9 @@ var chainConfigs = {
|
|
|
3839
3841
|
UniversalRouter: "0xd9C500DfF816a1Da21A48A732d3498Bf09dc9AEB",
|
|
3840
3842
|
UniswapV3Quoter: "0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997",
|
|
3841
3843
|
UniswapV4Quoter: "0xd0737C9762912dD34c3271197E362Aa736Df0926",
|
|
3844
|
+
UniswapV4PositionManager: "0x7a4a5c919ae2541aed11041a1aeee68f1287f95b",
|
|
3845
|
+
UniswapV4PoolManager: "0x28e2ea090877bf75740558f6bfb36a5ffee9e9df",
|
|
3846
|
+
UniswapV4StateView: "0xd13dd3d6e93f276fafc9db9e6bb47c1180aee0c4",
|
|
3842
3847
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
3843
3848
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
3844
3849
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
@@ -3893,6 +3898,9 @@ var chainConfigs = {
|
|
|
3893
3898
|
UniversalRouter: "0xa51afafe0263b40edaef0df8781ea9aa03e381a3",
|
|
3894
3899
|
UniswapV3Quoter: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
|
|
3895
3900
|
UniswapV4Quoter: "0x3972c00f7ed4885e145823eb7c655375d275a1c5",
|
|
3901
|
+
UniswapV4PositionManager: "0xd88f38f930b7952f2db2432cb002e7abbf3dd869",
|
|
3902
|
+
UniswapV4PoolManager: "0x360e68faccca8ca495c1b759fd9eee466db9fb32",
|
|
3903
|
+
UniswapV4StateView: "0x76fd297e2d437cd7f76d50f01afe6160f86e9990",
|
|
3896
3904
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
3897
3905
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
3898
3906
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
@@ -3949,7 +3957,11 @@ var chainConfigs = {
|
|
|
3949
3957
|
UniswapV4Quoter: "0x0d5e0f971ed27fbff6c2837bf31316121532048d",
|
|
3950
3958
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
3951
3959
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
3952
|
-
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
3960
|
+
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
3961
|
+
AerodromeRouter: "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43",
|
|
3962
|
+
UniswapV4PositionManager: "0x7c5f5a4bbd8fd63184577525326123b519429bdc",
|
|
3963
|
+
UniswapV4PoolManager: "0x498581ff718922c3f8e6a244956af099b2652b2b",
|
|
3964
|
+
UniswapV4StateView: "0xa3c0c9b65bad0b08107aa264b0f3db444b867a71"
|
|
3953
3965
|
// Usdt0Oft: Not available on Base
|
|
3954
3966
|
},
|
|
3955
3967
|
rpcEnvKey: "BASE_MAINNET",
|
|
@@ -4001,6 +4013,9 @@ var chainConfigs = {
|
|
|
4001
4013
|
UniversalRouter: "0x1095692a6237d83c6a72f3f5efedb9a670c49223",
|
|
4002
4014
|
UniswapV3Quoter: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
|
|
4003
4015
|
UniswapV4Quoter: "0xb3d5c3dfc3a7aebff71895a7191796bffc2c81b9",
|
|
4016
|
+
UniswapV4PositionManager: "0x1ec2ebf4f37e7363fdfe3551602425af0b3ceef9",
|
|
4017
|
+
UniswapV4PoolManager: "0x67366782805870060151383f4bbff9dab53e5cd6",
|
|
4018
|
+
UniswapV4StateView: "0x5ea1bd7974c8a611cbab0bdcafcb1d9cc9b3ba5a",
|
|
4004
4019
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
4005
4020
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
4006
4021
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
@@ -4045,6 +4060,9 @@ var chainConfigs = {
|
|
|
4045
4060
|
UniversalRouter: "0xef740bf23acae26f6492b10de645d6b98dc8eaf3",
|
|
4046
4061
|
UniswapV3Quoter: "0x385a5cf5f83e99f7bb2852b6a19c3538b9fa7658",
|
|
4047
4062
|
UniswapV4Quoter: "0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203",
|
|
4063
|
+
UniswapV4PositionManager: "0x4529a01c7a0410167c5740c487a8de60232617bf",
|
|
4064
|
+
UniswapV4PoolManager: "0x1f98400000000000000000000000000000000004",
|
|
4065
|
+
UniswapV4StateView: "0x86e8631a016f9068c3f085faf484ee3f5fdee8f2",
|
|
4048
4066
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
4049
4067
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
4050
4068
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
@@ -4150,7 +4168,9 @@ var chainConfigs = {
|
|
|
4150
4168
|
UniswapV3Factory: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
4151
4169
|
Calldispatcher: "0xC71251c8b3e7B02697A84363Eef6DcE8DfBdF333",
|
|
4152
4170
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
4153
|
-
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
4171
|
+
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
4172
|
+
UniswapV4PositionManager: "0x3c3ea4b57a46241e54610e5f022e5c45859a1017",
|
|
4173
|
+
UniswapV4PoolManager: "0x9a13f98cb987694c9f086b1f5eb990eea8264ec3"
|
|
4154
4174
|
},
|
|
4155
4175
|
defaultRpcUrl: "https://mainnet.optimism.io",
|
|
4156
4176
|
consensusStateId: "ETH0",
|
|
@@ -4206,7 +4226,9 @@ var chainConfigs = {
|
|
|
4206
4226
|
addresses: {
|
|
4207
4227
|
TokenGateway: "0xCe304770236f39F9911BfCC51afBdfF3b8635718",
|
|
4208
4228
|
Host: "0x7F0165140D0f3251c8f6465e94E9d12C7FD40711",
|
|
4209
|
-
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
4229
|
+
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
4230
|
+
UniswapV4PositionManager: "0x1b35d13a2e2528f192637f14b05f0dc0e7deb566",
|
|
4231
|
+
UniswapV4PoolManager: "0x360e68faccca8ca495c1b759fd9eee466db9fb32"
|
|
4210
4232
|
},
|
|
4211
4233
|
defaultRpcUrl: "https://rpc.soneium.org",
|
|
4212
4234
|
consensusStateId: "ETH0",
|
|
@@ -4400,6 +4422,9 @@ var ChainConfigService = class {
|
|
|
4400
4422
|
getUniswapRouterV2Address(chain) {
|
|
4401
4423
|
return this.getConfig(chain)?.addresses.UniswapRouter02 ?? "0x";
|
|
4402
4424
|
}
|
|
4425
|
+
getAerodromeRouterAddress(chain) {
|
|
4426
|
+
return this.getConfig(chain)?.addresses.AerodromeRouter ?? "0x";
|
|
4427
|
+
}
|
|
4403
4428
|
getUniswapV2FactoryAddress(chain) {
|
|
4404
4429
|
return this.getConfig(chain)?.addresses.UniswapV2Factory ?? "0x";
|
|
4405
4430
|
}
|
|
@@ -4415,6 +4440,15 @@ var ChainConfigService = class {
|
|
|
4415
4440
|
getUniswapV4QuoterAddress(chain) {
|
|
4416
4441
|
return this.getConfig(chain)?.addresses.UniswapV4Quoter ?? "0x";
|
|
4417
4442
|
}
|
|
4443
|
+
getUniswapV4PositionManagerAddress(chain) {
|
|
4444
|
+
return this.getConfig(chain)?.addresses.UniswapV4PositionManager ?? "0x";
|
|
4445
|
+
}
|
|
4446
|
+
getUniswapV4PoolManagerAddress(chain) {
|
|
4447
|
+
return this.getConfig(chain)?.addresses.UniswapV4PoolManager ?? "0x";
|
|
4448
|
+
}
|
|
4449
|
+
getUniswapV4StateViewAddress(chain) {
|
|
4450
|
+
return this.getConfig(chain)?.addresses.UniswapV4StateView ?? "0x";
|
|
4451
|
+
}
|
|
4418
4452
|
getPermit2Address(chain) {
|
|
4419
4453
|
return this.getConfig(chain)?.addresses.Permit2 ?? "0x";
|
|
4420
4454
|
}
|
|
@@ -5498,6 +5532,7 @@ var EvmChain = class _EvmChain {
|
|
|
5498
5532
|
});
|
|
5499
5533
|
this.chainConfigService = new ChainConfigService();
|
|
5500
5534
|
}
|
|
5535
|
+
params;
|
|
5501
5536
|
publicClient;
|
|
5502
5537
|
chainConfigService;
|
|
5503
5538
|
/**
|
|
@@ -6098,6 +6133,7 @@ var HttpRpcClient = class {
|
|
|
6098
6133
|
constructor(url) {
|
|
6099
6134
|
this.url = url;
|
|
6100
6135
|
}
|
|
6136
|
+
url;
|
|
6101
6137
|
/**
|
|
6102
6138
|
* Make an RPC call over HTTP
|
|
6103
6139
|
* @param method - The RPC method name
|
|
@@ -6135,6 +6171,7 @@ var SubstrateChain = class _SubstrateChain {
|
|
|
6135
6171
|
const httpUrl = replaceWebsocketWithHttp(url);
|
|
6136
6172
|
this.rpcClient = new HttpRpcClient(httpUrl);
|
|
6137
6173
|
}
|
|
6174
|
+
params;
|
|
6138
6175
|
/*
|
|
6139
6176
|
* api: The Polkadot API instance for the Substrate chain.
|
|
6140
6177
|
*/
|
|
@@ -6652,6 +6689,9 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
6652
6689
|
this.substratePrivateKey = substratePrivateKey;
|
|
6653
6690
|
this.ownsConnection = ownsConnection;
|
|
6654
6691
|
}
|
|
6692
|
+
api;
|
|
6693
|
+
substratePrivateKey;
|
|
6694
|
+
ownsConnection;
|
|
6655
6695
|
/** Cached result of whether the node exposes intents_* RPC methods */
|
|
6656
6696
|
hasIntentsRpc = null;
|
|
6657
6697
|
/**
|
|
@@ -6929,6 +6969,7 @@ var TronChain = class _TronChain {
|
|
|
6929
6969
|
this.evm = evm;
|
|
6930
6970
|
this.tronWebInstance = new TronWeb({ fullHost: params.rpcUrl });
|
|
6931
6971
|
}
|
|
6972
|
+
params;
|
|
6932
6973
|
evm;
|
|
6933
6974
|
tronWebInstance;
|
|
6934
6975
|
/**
|
|
@@ -7469,6 +7510,7 @@ var SubstrateHttpRpc = class {
|
|
|
7469
7510
|
constructor(url) {
|
|
7470
7511
|
this.url = url;
|
|
7471
7512
|
}
|
|
7513
|
+
url;
|
|
7472
7514
|
async call(method, params = []) {
|
|
7473
7515
|
const body = JSON.stringify({
|
|
7474
7516
|
jsonrpc: "2.0",
|
|
@@ -7513,6 +7555,7 @@ var PolkadotHubChain = class _PolkadotHubChain {
|
|
|
7513
7555
|
this.evm = evm;
|
|
7514
7556
|
this.substrateRpc = new SubstrateHttpRpc(replaceWebsocketWithHttp(params.substrateRpcUrl));
|
|
7515
7557
|
}
|
|
7558
|
+
params;
|
|
7516
7559
|
evm;
|
|
7517
7560
|
substrateRpc;
|
|
7518
7561
|
static fromParams(params) {
|
|
@@ -12571,7 +12614,9 @@ var BundlerMethod = {
|
|
|
12571
12614
|
/** Estimates gas limits for a UserOperation before submission. */
|
|
12572
12615
|
ETH_ESTIMATE_USER_OPERATION_GAS: "eth_estimateUserOperationGas",
|
|
12573
12616
|
/** Pimlico-specific method to fetch recommended EIP-1559 gas prices for UserOperations. */
|
|
12574
|
-
PIMLICO_GET_USER_OPERATION_GAS_PRICE: "pimlico_getUserOperationGasPrice"
|
|
12617
|
+
PIMLICO_GET_USER_OPERATION_GAS_PRICE: "pimlico_getUserOperationGasPrice",
|
|
12618
|
+
/** Alchemy (Rundler) method to fetch recommended priority fee for UserOperations. */
|
|
12619
|
+
RUNDLER_MAX_PRIORITY_FEE_PER_GAS: "rundler_maxPriorityFeePerGas"
|
|
12575
12620
|
};
|
|
12576
12621
|
|
|
12577
12622
|
// src/protocols/intents/CryptoUtils.ts
|
|
@@ -12592,6 +12637,7 @@ var CryptoUtils = class {
|
|
|
12592
12637
|
constructor(ctx) {
|
|
12593
12638
|
this.ctx = ctx;
|
|
12594
12639
|
}
|
|
12640
|
+
ctx;
|
|
12595
12641
|
/**
|
|
12596
12642
|
* Computes an EIP-712 domain separator for a given contract.
|
|
12597
12643
|
*
|
|
@@ -15127,6 +15173,7 @@ var OrderPlacer = class {
|
|
|
15127
15173
|
constructor(ctx) {
|
|
15128
15174
|
this.ctx = ctx;
|
|
15129
15175
|
}
|
|
15176
|
+
ctx;
|
|
15130
15177
|
/**
|
|
15131
15178
|
* Bidirectional async generator that orchestrates order placement.
|
|
15132
15179
|
*
|
|
@@ -15204,66 +15251,40 @@ var OrderPlacer = class {
|
|
|
15204
15251
|
return { order, receipt };
|
|
15205
15252
|
}
|
|
15206
15253
|
};
|
|
15207
|
-
|
|
15208
|
-
// src/protocols/intents/OrderExecutor.ts
|
|
15209
15254
|
var USED_USEROPS_STORAGE_KEY = (commitment) => `used-userops:${commitment.toLowerCase()}`;
|
|
15210
15255
|
var OrderExecutor = class {
|
|
15211
|
-
/**
|
|
15212
|
-
* @param ctx - Shared IntentsV2 context providing the destination chain
|
|
15213
|
-
* client, coprocessor, bundler URL, and storage adapters.
|
|
15214
|
-
* @param bidManager - Handles bid validation, sorting, simulation, and
|
|
15215
|
-
* UserOperation submission.
|
|
15216
|
-
* @param crypto - Crypto utilities used to compute UserOperation hashes for
|
|
15217
|
-
* deduplication.
|
|
15218
|
-
*/
|
|
15219
15256
|
constructor(ctx, bidManager, crypto) {
|
|
15220
15257
|
this.ctx = ctx;
|
|
15221
15258
|
this.bidManager = bidManager;
|
|
15222
15259
|
this.crypto = crypto;
|
|
15223
15260
|
}
|
|
15261
|
+
ctx;
|
|
15262
|
+
bidManager;
|
|
15263
|
+
crypto;
|
|
15224
15264
|
/**
|
|
15225
|
-
*
|
|
15226
|
-
*
|
|
15227
|
-
* or an unrecoverable error occurs.
|
|
15228
|
-
*
|
|
15229
|
-
* **Status progression (cross-chain orders):**
|
|
15230
|
-
* `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED` → `USEROP_SUBMITTED`
|
|
15231
|
-
* then terminates (settlement is confirmed off-chain via Hyperbridge).
|
|
15232
|
-
*
|
|
15233
|
-
* **Status progression (same-chain orders):**
|
|
15234
|
-
* `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED` → `USEROP_SUBMITTED`
|
|
15235
|
-
* → (`FILLED` | `PARTIAL_FILL`)* → (`FILLED` | `PARTIAL_FILL_EXHAUSTED`)
|
|
15236
|
-
*
|
|
15237
|
-
* **Error statuses:** `FAILED` (fatal, no fills) or `PARTIAL_FILL_EXHAUSTED`
|
|
15238
|
-
* (deadline reached or no new bids after at least one partial fill).
|
|
15239
|
-
*
|
|
15240
|
-
* @param options - Execution parameters including the placed order, its
|
|
15241
|
-
* session private key, bid collection settings, and poll interval.
|
|
15242
|
-
* @yields {@link IntentOrderStatusUpdate} objects describing each stage.
|
|
15243
|
-
* @throws Never throws directly; all errors are reported as `FAILED` yields.
|
|
15265
|
+
* Sleeps until the order's block deadline is reached, then yields EXPIRED.
|
|
15266
|
+
* Uses the chain's block time to calculate the sleep duration.
|
|
15244
15267
|
*/
|
|
15245
|
-
async *
|
|
15246
|
-
const
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
|
|
15250
|
-
|
|
15251
|
-
|
|
15252
|
-
|
|
15253
|
-
|
|
15254
|
-
const commitment = order.id;
|
|
15255
|
-
const isSameChain = order.source === order.destination;
|
|
15256
|
-
if (!this.ctx.intentsCoprocessor) {
|
|
15257
|
-
yield { status: "FAILED", error: "IntentsCoprocessor required for order execution" };
|
|
15258
|
-
return;
|
|
15259
|
-
}
|
|
15260
|
-
if (!this.ctx.bundlerUrl) {
|
|
15261
|
-
yield { status: "FAILED", error: "Bundler URL not configured" };
|
|
15262
|
-
return;
|
|
15268
|
+
async *deadlineStream(deadline, commitment) {
|
|
15269
|
+
const client = this.ctx.dest.client;
|
|
15270
|
+
const blockTimeSeconds = client.chain?.blockTime ?? 2;
|
|
15271
|
+
while (true) {
|
|
15272
|
+
const currentBlock = await client.getBlockNumber();
|
|
15273
|
+
if (currentBlock >= deadline) break;
|
|
15274
|
+
const blocksRemaining = Number(deadline - currentBlock);
|
|
15275
|
+
const sleepMs = blocksRemaining * blockTimeSeconds * 1e3;
|
|
15276
|
+
await sleep(sleepMs);
|
|
15263
15277
|
}
|
|
15278
|
+
yield {
|
|
15279
|
+
status: "EXPIRED",
|
|
15280
|
+
commitment,
|
|
15281
|
+
error: "Order deadline reached"
|
|
15282
|
+
};
|
|
15283
|
+
}
|
|
15284
|
+
/** Loads the persisted deduplication set of already-submitted UserOp hashes for a given order commitment. */
|
|
15285
|
+
async loadUsedUserOps(commitment) {
|
|
15264
15286
|
const usedUserOps = /* @__PURE__ */ new Set();
|
|
15265
|
-
const
|
|
15266
|
-
const persisted = await this.ctx.usedUserOpsStorage.getItem(storageKey);
|
|
15287
|
+
const persisted = await this.ctx.usedUserOpsStorage.getItem(USED_USEROPS_STORAGE_KEY(commitment));
|
|
15267
15288
|
if (persisted) {
|
|
15268
15289
|
try {
|
|
15269
15290
|
const parsed = JSON.parse(persisted);
|
|
@@ -15273,83 +15294,210 @@ var OrderExecutor = class {
|
|
|
15273
15294
|
} catch {
|
|
15274
15295
|
}
|
|
15275
15296
|
}
|
|
15276
|
-
|
|
15277
|
-
|
|
15278
|
-
|
|
15297
|
+
return usedUserOps;
|
|
15298
|
+
}
|
|
15299
|
+
/** Persists the deduplication set of UserOp hashes to storage. */
|
|
15300
|
+
async persistUsedUserOps(commitment, usedUserOps) {
|
|
15301
|
+
await this.ctx.usedUserOpsStorage.setItem(
|
|
15302
|
+
USED_USEROPS_STORAGE_KEY(commitment),
|
|
15303
|
+
JSON.stringify([...usedUserOps])
|
|
15304
|
+
);
|
|
15305
|
+
}
|
|
15306
|
+
/**
|
|
15307
|
+
* Creates a closure that computes the deduplication hash key for a
|
|
15308
|
+
* UserOperation, pre-bound to the order's destination chain and entry point.
|
|
15309
|
+
*/
|
|
15310
|
+
createUserOpHasher(order) {
|
|
15279
15311
|
const entryPointAddress = this.ctx.dest.configService.getEntryPointV08Address(hexToString(order.destination));
|
|
15280
15312
|
const chainId = BigInt(
|
|
15281
15313
|
this.ctx.dest.client.chain?.id ?? Number.parseInt(this.ctx.dest.config.stateMachineId.split("-")[1])
|
|
15282
15314
|
);
|
|
15283
|
-
|
|
15315
|
+
return (userOp) => this.crypto.computeUserOpHash(userOp, entryPointAddress, chainId);
|
|
15316
|
+
}
|
|
15317
|
+
/**
|
|
15318
|
+
* Fetches bids from the coprocessor for a given order commitment.
|
|
15319
|
+
* If a preferred solver is configured and the solver lock has not expired,
|
|
15320
|
+
* only bids from that solver are returned.
|
|
15321
|
+
*/
|
|
15322
|
+
async fetchBids(params) {
|
|
15323
|
+
const { commitment, solver, solverLockStartTime } = params;
|
|
15324
|
+
const fetchedBids = await this.ctx.intentsCoprocessor.getBidsForOrder(commitment);
|
|
15325
|
+
if (solver) {
|
|
15326
|
+
const { address, timeoutMs } = solver;
|
|
15327
|
+
const solverLockActive = Date.now() - solverLockStartTime < timeoutMs;
|
|
15328
|
+
return solverLockActive ? fetchedBids.filter((bid) => bid.userOp.sender.toLowerCase() === address.toLowerCase()) : fetchedBids;
|
|
15329
|
+
}
|
|
15330
|
+
return fetchedBids;
|
|
15331
|
+
}
|
|
15332
|
+
/**
|
|
15333
|
+
* Selects the best bid from the provided candidates, submits the
|
|
15334
|
+
* UserOperation, and persists the dedup entry to prevent resubmission.
|
|
15335
|
+
*/
|
|
15336
|
+
async submitBid(params) {
|
|
15337
|
+
const { order, freshBids, sessionPrivateKey, commitment, usedUserOps, userOpHashKey } = params;
|
|
15338
|
+
const result = await this.bidManager.selectBid(order, freshBids, sessionPrivateKey);
|
|
15339
|
+
usedUserOps.add(userOpHashKey(result.userOp));
|
|
15340
|
+
await this.persistUsedUserOps(commitment, usedUserOps);
|
|
15341
|
+
return result;
|
|
15342
|
+
}
|
|
15343
|
+
/**
|
|
15344
|
+
* Processes a fill result and returns updated fill accumulators,
|
|
15345
|
+
* the status update to yield (if any), and whether the order is
|
|
15346
|
+
* fully satisfied.
|
|
15347
|
+
*/
|
|
15348
|
+
processFillResult(result, commitment, targetAssets, totalFilledAssets, remainingAssets) {
|
|
15349
|
+
if (result.fillStatus === "full") {
|
|
15350
|
+
totalFilledAssets = targetAssets.map((a) => ({ token: a.token, amount: a.amount }));
|
|
15351
|
+
remainingAssets = targetAssets.map((a) => ({ token: a.token, amount: 0n }));
|
|
15352
|
+
return {
|
|
15353
|
+
update: {
|
|
15354
|
+
status: "FILLED",
|
|
15355
|
+
commitment,
|
|
15356
|
+
userOpHash: result.userOpHash,
|
|
15357
|
+
selectedSolver: result.solverAddress,
|
|
15358
|
+
transactionHash: result.txnHash,
|
|
15359
|
+
totalFilledAssets,
|
|
15360
|
+
remainingAssets
|
|
15361
|
+
},
|
|
15362
|
+
done: true,
|
|
15363
|
+
totalFilledAssets,
|
|
15364
|
+
remainingAssets
|
|
15365
|
+
};
|
|
15366
|
+
}
|
|
15367
|
+
if (result.fillStatus === "partial") {
|
|
15368
|
+
const filledAssets = result.filledAssets ?? [];
|
|
15369
|
+
totalFilledAssets = totalFilledAssets.map((a) => {
|
|
15370
|
+
const filled = filledAssets.find((f) => f.token === a.token);
|
|
15371
|
+
return filled ? { token: a.token, amount: a.amount + filled.amount } : { ...a };
|
|
15372
|
+
});
|
|
15373
|
+
remainingAssets = targetAssets.map((target) => {
|
|
15374
|
+
const filled = totalFilledAssets.find((a) => a.token === target.token);
|
|
15375
|
+
const filledAmt = filled?.amount ?? 0n;
|
|
15376
|
+
return {
|
|
15377
|
+
token: target.token,
|
|
15378
|
+
amount: filledAmt >= target.amount ? 0n : target.amount - filledAmt
|
|
15379
|
+
};
|
|
15380
|
+
});
|
|
15381
|
+
const fullyFilled = remainingAssets.every((a) => a.amount === 0n);
|
|
15382
|
+
return {
|
|
15383
|
+
update: fullyFilled ? {
|
|
15384
|
+
status: "FILLED",
|
|
15385
|
+
commitment,
|
|
15386
|
+
userOpHash: result.userOpHash,
|
|
15387
|
+
selectedSolver: result.solverAddress,
|
|
15388
|
+
transactionHash: result.txnHash,
|
|
15389
|
+
totalFilledAssets,
|
|
15390
|
+
remainingAssets
|
|
15391
|
+
} : {
|
|
15392
|
+
status: "PARTIAL_FILL",
|
|
15393
|
+
commitment,
|
|
15394
|
+
userOpHash: result.userOpHash,
|
|
15395
|
+
selectedSolver: result.solverAddress,
|
|
15396
|
+
transactionHash: result.txnHash,
|
|
15397
|
+
filledAssets,
|
|
15398
|
+
totalFilledAssets,
|
|
15399
|
+
remainingAssets
|
|
15400
|
+
},
|
|
15401
|
+
done: fullyFilled,
|
|
15402
|
+
totalFilledAssets,
|
|
15403
|
+
remainingAssets
|
|
15404
|
+
};
|
|
15405
|
+
}
|
|
15406
|
+
return { update: null, done: false, totalFilledAssets, remainingAssets };
|
|
15407
|
+
}
|
|
15408
|
+
/**
|
|
15409
|
+
* Executes an intent order by racing bid polling against the order's
|
|
15410
|
+
* block deadline. Yields status updates at each lifecycle stage.
|
|
15411
|
+
*
|
|
15412
|
+
* **Same-chain:** `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED`
|
|
15413
|
+
* → (`FILLED` | `PARTIAL_FILL`)* → (`FILLED` | `EXPIRED`)
|
|
15414
|
+
*
|
|
15415
|
+
* **Cross-chain:** `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED`
|
|
15416
|
+
* (terminates — settlement is confirmed async via Hyperbridge)
|
|
15417
|
+
*/
|
|
15418
|
+
async *executeOrder(options) {
|
|
15419
|
+
const { order, sessionPrivateKey, minBids = 1, pollIntervalMs = DEFAULT_POLL_INTERVAL, solver } = options;
|
|
15420
|
+
const commitment = order.id;
|
|
15421
|
+
const isSameChain = order.source === order.destination;
|
|
15422
|
+
if (!this.ctx.intentsCoprocessor) {
|
|
15423
|
+
yield { status: "FAILED", error: "IntentsCoprocessor required for order execution" };
|
|
15424
|
+
return;
|
|
15425
|
+
}
|
|
15426
|
+
if (!this.ctx.bundlerUrl) {
|
|
15427
|
+
yield { status: "FAILED", error: "Bundler URL not configured" };
|
|
15428
|
+
return;
|
|
15429
|
+
}
|
|
15430
|
+
const usedUserOps = await this.loadUsedUserOps(commitment);
|
|
15431
|
+
const userOpHashKey = this.createUserOpHasher(order);
|
|
15284
15432
|
const targetAssets = order.output.assets.map((a) => ({ token: a.token, amount: a.amount }));
|
|
15285
15433
|
let totalFilledAssets = order.output.assets.map((a) => ({ token: a.token, amount: 0n }));
|
|
15286
15434
|
let remainingAssets = order.output.assets.map((a) => ({ token: a.token, amount: a.amount }));
|
|
15435
|
+
const executionStream = this.executionStream({
|
|
15436
|
+
order,
|
|
15437
|
+
sessionPrivateKey,
|
|
15438
|
+
commitment,
|
|
15439
|
+
minBids,
|
|
15440
|
+
pollIntervalMs,
|
|
15441
|
+
solver,
|
|
15442
|
+
usedUserOps,
|
|
15443
|
+
userOpHashKey,
|
|
15444
|
+
targetAssets,
|
|
15445
|
+
totalFilledAssets,
|
|
15446
|
+
remainingAssets
|
|
15447
|
+
});
|
|
15448
|
+
const deadlineTimeout = this.deadlineStream(order.deadline, commitment);
|
|
15449
|
+
const combined = mergeRace(deadlineTimeout, executionStream);
|
|
15450
|
+
for await (const update of combined) {
|
|
15451
|
+
yield update;
|
|
15452
|
+
if (update.status === "EXPIRED" || update.status === "FILLED") return;
|
|
15453
|
+
if (update.status === "BID_SELECTED" && !isSameChain) return;
|
|
15454
|
+
}
|
|
15455
|
+
}
|
|
15456
|
+
/**
|
|
15457
|
+
* Core execution loop that polls for bids, submits UserOperations,
|
|
15458
|
+
* and tracks fill progress. Yields between each poll iteration so
|
|
15459
|
+
* that `mergeRace` can interleave the deadline stream.
|
|
15460
|
+
*/
|
|
15461
|
+
async *executionStream(params) {
|
|
15462
|
+
const {
|
|
15463
|
+
order,
|
|
15464
|
+
sessionPrivateKey,
|
|
15465
|
+
commitment,
|
|
15466
|
+
minBids,
|
|
15467
|
+
pollIntervalMs,
|
|
15468
|
+
solver,
|
|
15469
|
+
usedUserOps,
|
|
15470
|
+
userOpHashKey,
|
|
15471
|
+
targetAssets
|
|
15472
|
+
} = params;
|
|
15473
|
+
let { totalFilledAssets, remainingAssets } = params;
|
|
15474
|
+
const solverLockStartTime = Date.now();
|
|
15475
|
+
yield { status: "AWAITING_BIDS", commitment, totalFilledAssets, remainingAssets };
|
|
15287
15476
|
try {
|
|
15288
15477
|
while (true) {
|
|
15289
|
-
|
|
15290
|
-
|
|
15291
|
-
const
|
|
15292
|
-
|
|
15293
|
-
|
|
15294
|
-
yield {
|
|
15295
|
-
status: "PARTIAL_FILL_EXHAUSTED",
|
|
15296
|
-
commitment,
|
|
15297
|
-
totalFilledAssets,
|
|
15298
|
-
remainingAssets,
|
|
15299
|
-
error: deadlineError
|
|
15300
|
-
};
|
|
15301
|
-
} else {
|
|
15302
|
-
yield { status: "FAILED", commitment, error: deadlineError };
|
|
15303
|
-
}
|
|
15304
|
-
return;
|
|
15305
|
-
}
|
|
15306
|
-
yield { status: "AWAITING_BIDS", commitment, totalFilledAssets, remainingAssets };
|
|
15307
|
-
const startTime = Date.now();
|
|
15308
|
-
let bids = [];
|
|
15309
|
-
let solverLockExpired = false;
|
|
15310
|
-
while (Date.now() - startTime < bidTimeoutMs) {
|
|
15311
|
-
try {
|
|
15312
|
-
const fetchedBids = await this.ctx.intentsCoprocessor.getBidsForOrder(commitment);
|
|
15313
|
-
if (solver) {
|
|
15314
|
-
const { address, timeoutMs } = solver;
|
|
15315
|
-
const solverLockActive = Date.now() - startTime < timeoutMs;
|
|
15316
|
-
if (!solverLockActive) solverLockExpired = true;
|
|
15317
|
-
bids = solverLockActive ? fetchedBids.filter((bid) => bid.userOp.sender.toLowerCase() === address.toLowerCase()) : fetchedBids;
|
|
15318
|
-
} else {
|
|
15319
|
-
bids = fetchedBids;
|
|
15320
|
-
}
|
|
15321
|
-
if (bids.length >= minBids) {
|
|
15322
|
-
break;
|
|
15323
|
-
}
|
|
15324
|
-
} catch {
|
|
15325
|
-
}
|
|
15478
|
+
let freshBids;
|
|
15479
|
+
try {
|
|
15480
|
+
const bids = await this.fetchBids({ commitment, solver, solverLockStartTime });
|
|
15481
|
+
freshBids = bids.filter((bid) => !usedUserOps.has(userOpHashKey(bid.userOp)));
|
|
15482
|
+
} catch {
|
|
15326
15483
|
await sleep(pollIntervalMs);
|
|
15484
|
+
continue;
|
|
15327
15485
|
}
|
|
15328
|
-
|
|
15329
|
-
|
|
15330
|
-
|
|
15331
|
-
});
|
|
15332
|
-
if (freshBids.length === 0) {
|
|
15333
|
-
const isPartiallyFilled = totalFilledAssets.some((a) => a.amount > 0n);
|
|
15334
|
-
const solverClause = solver && !solverLockExpired ? ` for requested solver ${solver.address}` : "";
|
|
15335
|
-
const noBidsError = isPartiallyFilled ? `No new bids${solverClause} after partial fill` : `No new bids${solverClause} available within ${bidTimeoutMs}ms timeout`;
|
|
15336
|
-
if (isPartiallyFilled) {
|
|
15337
|
-
yield {
|
|
15338
|
-
status: "PARTIAL_FILL_EXHAUSTED",
|
|
15339
|
-
commitment,
|
|
15340
|
-
totalFilledAssets,
|
|
15341
|
-
remainingAssets,
|
|
15342
|
-
error: noBidsError
|
|
15343
|
-
};
|
|
15344
|
-
} else {
|
|
15345
|
-
yield { status: "FAILED", commitment, error: noBidsError };
|
|
15346
|
-
}
|
|
15347
|
-
return;
|
|
15486
|
+
if (freshBids.length < minBids) {
|
|
15487
|
+
await sleep(pollIntervalMs);
|
|
15488
|
+
continue;
|
|
15348
15489
|
}
|
|
15349
15490
|
yield { status: "BIDS_RECEIVED", commitment, bidCount: freshBids.length, bids: freshBids };
|
|
15350
|
-
let
|
|
15491
|
+
let submitResult;
|
|
15351
15492
|
try {
|
|
15352
|
-
|
|
15493
|
+
submitResult = await this.submitBid({
|
|
15494
|
+
order,
|
|
15495
|
+
freshBids,
|
|
15496
|
+
sessionPrivateKey,
|
|
15497
|
+
commitment,
|
|
15498
|
+
usedUserOps,
|
|
15499
|
+
userOpHashKey
|
|
15500
|
+
});
|
|
15353
15501
|
} catch (err) {
|
|
15354
15502
|
yield {
|
|
15355
15503
|
status: "FAILED",
|
|
@@ -15358,76 +15506,29 @@ var OrderExecutor = class {
|
|
|
15358
15506
|
remainingAssets,
|
|
15359
15507
|
error: `Failed to select bid and submit: ${err instanceof Error ? err.message : String(err)}`
|
|
15360
15508
|
};
|
|
15361
|
-
|
|
15509
|
+
await sleep(pollIntervalMs);
|
|
15510
|
+
continue;
|
|
15362
15511
|
}
|
|
15363
|
-
const usedKey = userOpHashKey(result.userOp);
|
|
15364
|
-
usedUserOps.add(usedKey);
|
|
15365
|
-
await persistUsedUserOps();
|
|
15366
15512
|
yield {
|
|
15367
15513
|
status: "BID_SELECTED",
|
|
15368
15514
|
commitment,
|
|
15369
|
-
selectedSolver:
|
|
15370
|
-
userOpHash:
|
|
15371
|
-
userOp:
|
|
15515
|
+
selectedSolver: submitResult.solverAddress,
|
|
15516
|
+
userOpHash: submitResult.userOpHash,
|
|
15517
|
+
userOp: submitResult.userOp,
|
|
15518
|
+
transactionHash: submitResult.txnHash
|
|
15372
15519
|
};
|
|
15373
|
-
|
|
15374
|
-
|
|
15520
|
+
const fill = this.processFillResult(
|
|
15521
|
+
submitResult,
|
|
15375
15522
|
commitment,
|
|
15376
|
-
|
|
15377
|
-
|
|
15378
|
-
|
|
15379
|
-
|
|
15380
|
-
|
|
15381
|
-
|
|
15382
|
-
|
|
15383
|
-
|
|
15384
|
-
|
|
15385
|
-
remainingAssets = targetAssets.map((a) => ({ token: a.token, amount: 0n }));
|
|
15386
|
-
yield {
|
|
15387
|
-
status: "FILLED",
|
|
15388
|
-
commitment,
|
|
15389
|
-
userOpHash: result.userOpHash,
|
|
15390
|
-
selectedSolver: result.solverAddress,
|
|
15391
|
-
transactionHash: result.txnHash,
|
|
15392
|
-
totalFilledAssets,
|
|
15393
|
-
remainingAssets
|
|
15394
|
-
};
|
|
15395
|
-
return;
|
|
15396
|
-
}
|
|
15397
|
-
if (result.fillStatus === "partial") {
|
|
15398
|
-
const filledAssets = result.filledAssets ?? [];
|
|
15399
|
-
for (const filled of filledAssets) {
|
|
15400
|
-
const entry = totalFilledAssets.find((a) => a.token === filled.token);
|
|
15401
|
-
if (entry) entry.amount += filled.amount;
|
|
15402
|
-
}
|
|
15403
|
-
remainingAssets = targetAssets.map((target) => {
|
|
15404
|
-
const filled = totalFilledAssets.find((a) => a.token === target.token);
|
|
15405
|
-
const filledAmt = filled?.amount ?? 0n;
|
|
15406
|
-
return { token: target.token, amount: filledAmt >= target.amount ? 0n : target.amount - filledAmt };
|
|
15407
|
-
});
|
|
15408
|
-
const fullyFilled = remainingAssets.every((a) => a.amount === 0n);
|
|
15409
|
-
if (fullyFilled) {
|
|
15410
|
-
yield {
|
|
15411
|
-
status: "FILLED",
|
|
15412
|
-
commitment,
|
|
15413
|
-
userOpHash: result.userOpHash,
|
|
15414
|
-
selectedSolver: result.solverAddress,
|
|
15415
|
-
transactionHash: result.txnHash,
|
|
15416
|
-
totalFilledAssets,
|
|
15417
|
-
remainingAssets
|
|
15418
|
-
};
|
|
15419
|
-
return;
|
|
15420
|
-
}
|
|
15421
|
-
yield {
|
|
15422
|
-
status: "PARTIAL_FILL",
|
|
15423
|
-
commitment,
|
|
15424
|
-
userOpHash: result.userOpHash,
|
|
15425
|
-
selectedSolver: result.solverAddress,
|
|
15426
|
-
transactionHash: result.txnHash,
|
|
15427
|
-
filledAssets,
|
|
15428
|
-
totalFilledAssets,
|
|
15429
|
-
remainingAssets
|
|
15430
|
-
};
|
|
15523
|
+
targetAssets,
|
|
15524
|
+
totalFilledAssets,
|
|
15525
|
+
remainingAssets
|
|
15526
|
+
);
|
|
15527
|
+
totalFilledAssets = fill.totalFilledAssets;
|
|
15528
|
+
remainingAssets = fill.remainingAssets;
|
|
15529
|
+
if (fill.update) {
|
|
15530
|
+
yield fill.update;
|
|
15531
|
+
if (fill.done) return;
|
|
15431
15532
|
}
|
|
15432
15533
|
}
|
|
15433
15534
|
} catch (err) {
|
|
@@ -15447,6 +15548,7 @@ var OrderCanceller = class {
|
|
|
15447
15548
|
constructor(ctx) {
|
|
15448
15549
|
this.ctx = ctx;
|
|
15449
15550
|
}
|
|
15551
|
+
ctx;
|
|
15450
15552
|
/**
|
|
15451
15553
|
* Returns both the native token cost and the relayer fee for cancelling an
|
|
15452
15554
|
* order. Frontends can use `relayerFee` to approve the ERC-20 spend before
|
|
@@ -15916,6 +16018,8 @@ var BidManager = class {
|
|
|
15916
16018
|
this.ctx = ctx;
|
|
15917
16019
|
this.crypto = crypto;
|
|
15918
16020
|
}
|
|
16021
|
+
ctx;
|
|
16022
|
+
crypto;
|
|
15919
16023
|
/**
|
|
15920
16024
|
* Constructs a signed `PackedUserOperation` that a solver can submit to the
|
|
15921
16025
|
* Hyperbridge coprocessor as a bid to fill an order.
|
|
@@ -17995,6 +18099,8 @@ var GasEstimator = class {
|
|
|
17995
18099
|
this.ctx = ctx;
|
|
17996
18100
|
this.crypto = crypto;
|
|
17997
18101
|
}
|
|
18102
|
+
ctx;
|
|
18103
|
+
crypto;
|
|
17998
18104
|
/**
|
|
17999
18105
|
* Estimates the gas cost for a solver to fill the given order and returns
|
|
18000
18106
|
* a structured estimate with individual gas components and total costs in
|
|
@@ -18029,11 +18135,13 @@ var GasEstimator = class {
|
|
|
18029
18135
|
const entryPointAddress = this.ctx.dest.configService.getEntryPointV08Address(destStateMachineId);
|
|
18030
18136
|
const chainId = BigInt(Number.parseInt(destStateMachineId.split("-")[1]));
|
|
18031
18137
|
const totalEthValue = order.output.assets.filter((output) => bytes32ToBytes20(output.token) === ADDRESS_ZERO2).reduce((sum, output) => sum + output.amount, 0n);
|
|
18032
|
-
const [sourceFeeToken, destFeeToken, gasPrice] = await Promise.all([
|
|
18138
|
+
const [sourceFeeToken, destFeeToken, gasPrice, latestBlock] = await Promise.all([
|
|
18033
18139
|
getFeeToken(this.ctx, this.ctx.source.config.stateMachineId, this.ctx.source),
|
|
18034
18140
|
getFeeToken(this.ctx, this.ctx.dest.config.stateMachineId, this.ctx.dest),
|
|
18035
|
-
this.ctx.dest.client.getGasPrice()
|
|
18141
|
+
this.ctx.dest.client.getGasPrice(),
|
|
18142
|
+
this.ctx.dest.client.getBlock({ blockTag: "latest" })
|
|
18036
18143
|
]);
|
|
18144
|
+
const baseFeePerGas = latestBlock.baseFeePerGas ?? gasPrice;
|
|
18037
18145
|
const feeTokenAsBytes32 = bytes20ToBytes32(destFeeToken.address);
|
|
18038
18146
|
const assetsForOverrides = [...order.output.assets];
|
|
18039
18147
|
if (!assetsForOverrides.some((asset) => asset.token.toLowerCase() === feeTokenAsBytes32.toLowerCase())) {
|
|
@@ -18081,6 +18189,7 @@ var GasEstimator = class {
|
|
|
18081
18189
|
if (this.ctx.bundlerUrl) {
|
|
18082
18190
|
try {
|
|
18083
18191
|
const callData = this.crypto.encodeERC7821Execute([
|
|
18192
|
+
...params.prependCalls ?? [],
|
|
18084
18193
|
{ target: intentGatewayV2Address, value: totalNativeValue, data: fillOrderCalldata }
|
|
18085
18194
|
]);
|
|
18086
18195
|
const accountGasLimits = this.crypto.packGasLimits(100000n, callGasLimit);
|
|
@@ -18122,7 +18231,9 @@ var GasEstimator = class {
|
|
|
18122
18231
|
sessionSignature
|
|
18123
18232
|
]);
|
|
18124
18233
|
const bundlerUserOp = this.crypto.prepareBundlerCall(preliminaryUserOp);
|
|
18125
|
-
const
|
|
18234
|
+
const bundlerUrlLower = this.ctx.bundlerUrl.toLowerCase();
|
|
18235
|
+
const isPimlico = bundlerUrlLower.includes("pimlico.io");
|
|
18236
|
+
const isAlchemy = bundlerUrlLower.includes("alchemy.com");
|
|
18126
18237
|
const bundlerRequests = [
|
|
18127
18238
|
{
|
|
18128
18239
|
method: BundlerMethod.ETH_ESTIMATE_USER_OPERATION_GAS,
|
|
@@ -18135,14 +18246,24 @@ var GasEstimator = class {
|
|
|
18135
18246
|
params: []
|
|
18136
18247
|
});
|
|
18137
18248
|
}
|
|
18249
|
+
if (isAlchemy) {
|
|
18250
|
+
bundlerRequests.push({
|
|
18251
|
+
method: BundlerMethod.RUNDLER_MAX_PRIORITY_FEE_PER_GAS,
|
|
18252
|
+
params: []
|
|
18253
|
+
});
|
|
18254
|
+
}
|
|
18138
18255
|
let gasEstimate;
|
|
18139
18256
|
let pimlicoGasPrices = null;
|
|
18257
|
+
let alchemyMaxPriorityFee = null;
|
|
18140
18258
|
try {
|
|
18141
18259
|
const batchResults = await this.crypto.sendBundlerBatch(bundlerRequests);
|
|
18142
18260
|
gasEstimate = batchResults[0];
|
|
18143
18261
|
if (isPimlico && batchResults.length > 1) {
|
|
18144
18262
|
pimlicoGasPrices = batchResults[1];
|
|
18145
18263
|
}
|
|
18264
|
+
if (isAlchemy && batchResults.length > 1) {
|
|
18265
|
+
alchemyMaxPriorityFee = batchResults[1];
|
|
18266
|
+
}
|
|
18146
18267
|
} catch {
|
|
18147
18268
|
gasEstimate = await this.crypto.sendBundler(
|
|
18148
18269
|
BundlerMethod.ETH_ESTIMATE_USER_OPERATION_GAS,
|
|
@@ -18161,6 +18282,14 @@ var GasEstimator = class {
|
|
|
18161
18282
|
maxPriorityFeePerGas = pimMaxPriorityFeePerGas + pimMaxPriorityFeePerGas * BigInt(priorityFeeBumpPercent) / 100n;
|
|
18162
18283
|
}
|
|
18163
18284
|
}
|
|
18285
|
+
if (alchemyMaxPriorityFee) {
|
|
18286
|
+
const rundlerPriorityFee = BigInt(alchemyMaxPriorityFee);
|
|
18287
|
+
const isArbitrum = chainId === 42161n;
|
|
18288
|
+
const alchemyPrioBump = isArbitrum ? 0n : 25n;
|
|
18289
|
+
maxPriorityFeePerGas = rundlerPriorityFee + rundlerPriorityFee * alchemyPrioBump / 100n;
|
|
18290
|
+
const bufferedBaseFee = baseFeePerGas + baseFeePerGas * 50n / 100n;
|
|
18291
|
+
maxFeePerGas = bufferedBaseFee + maxPriorityFeePerGas;
|
|
18292
|
+
}
|
|
18164
18293
|
} catch (e) {
|
|
18165
18294
|
console.warn("Bundler gas estimation failed, using fallback values:", e);
|
|
18166
18295
|
}
|
|
@@ -18393,6 +18522,7 @@ var OrderStatusChecker = class {
|
|
|
18393
18522
|
constructor(ctx) {
|
|
18394
18523
|
this.ctx = ctx;
|
|
18395
18524
|
}
|
|
18525
|
+
ctx;
|
|
18396
18526
|
/**
|
|
18397
18527
|
* Checks if a V2 order has been filled by reading the commitment storage slot on the destination chain.
|
|
18398
18528
|
*
|
|
@@ -18574,7 +18704,7 @@ var IntentGateway = class _IntentGateway {
|
|
|
18574
18704
|
* The caller must sign the transaction and pass it back via `gen.next(signedTx)`.
|
|
18575
18705
|
* 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
|
|
18576
18706
|
* the `OrderPlaced` event is confirmed.
|
|
18577
|
-
* 4. Delegates to {@link OrderExecutor.
|
|
18707
|
+
* 4. Delegates to {@link OrderExecutor.executeOrder} and forwards all
|
|
18578
18708
|
* subsequent status updates until the order is filled, exhausted, or fails.
|
|
18579
18709
|
*
|
|
18580
18710
|
* @param order - The order to place and execute. `order.fees` may be 0; it
|
|
@@ -18585,7 +18715,6 @@ var IntentGateway = class _IntentGateway {
|
|
|
18585
18715
|
* - `maxPriorityFeePerGasBumpPercent` — bump % for the priority fee estimate (default 8).
|
|
18586
18716
|
* - `maxFeePerGasBumpPercent` — bump % for the max fee estimate (default 10).
|
|
18587
18717
|
* - `minBids` — minimum bids to collect before selecting (default 1).
|
|
18588
|
-
* - `bidTimeoutMs` — how long to poll for bids before giving up (default 60 000 ms).
|
|
18589
18718
|
* - `pollIntervalMs` — interval between bid-polling attempts.
|
|
18590
18719
|
* @yields {@link IntentOrderStatusUpdate} at each lifecycle stage.
|
|
18591
18720
|
* @throws If the `placeOrder` generator behaves unexpectedly, or if gas
|
|
@@ -18618,11 +18747,10 @@ var IntentGateway = class _IntentGateway {
|
|
|
18618
18747
|
}
|
|
18619
18748
|
const { order: finalizedOrder, receipt: placementReceipt } = placeOrderSecond.value;
|
|
18620
18749
|
yield { status: "ORDER_PLACED", order: finalizedOrder, receipt: placementReceipt };
|
|
18621
|
-
for await (const status of this.orderExecutor.
|
|
18750
|
+
for await (const status of this.orderExecutor.executeOrder({
|
|
18622
18751
|
order: finalizedOrder,
|
|
18623
18752
|
sessionPrivateKey,
|
|
18624
18753
|
minBids: options?.minBids,
|
|
18625
|
-
bidTimeoutMs: options?.bidTimeoutMs,
|
|
18626
18754
|
pollIntervalMs: options?.pollIntervalMs,
|
|
18627
18755
|
solver: options?.solver
|
|
18628
18756
|
})) {
|
|
@@ -18630,6 +18758,52 @@ var IntentGateway = class _IntentGateway {
|
|
|
18630
18758
|
}
|
|
18631
18759
|
return;
|
|
18632
18760
|
}
|
|
18761
|
+
/**
|
|
18762
|
+
* Validates that an order has the minimum fields required for post-placement
|
|
18763
|
+
* resume (i.e. it was previously placed and has an on-chain identity).
|
|
18764
|
+
*
|
|
18765
|
+
* @throws If `order.id` or `order.session` is missing or zero-valued.
|
|
18766
|
+
*/
|
|
18767
|
+
assertOrderCanResume(order) {
|
|
18768
|
+
if (!order.id) {
|
|
18769
|
+
throw new Error("Cannot resume execution without order.id");
|
|
18770
|
+
}
|
|
18771
|
+
if (!order.session || order.session === ADDRESS_ZERO2) {
|
|
18772
|
+
throw new Error("Cannot resume execution without order.session");
|
|
18773
|
+
}
|
|
18774
|
+
}
|
|
18775
|
+
/**
|
|
18776
|
+
* Resumes execution of a previously placed order.
|
|
18777
|
+
*
|
|
18778
|
+
* Use this method after an app restart or crash to pick up where
|
|
18779
|
+
* {@link execute} left off. The order must already be placed on-chain
|
|
18780
|
+
* (i.e. it must have a valid `id` and `session`).
|
|
18781
|
+
*
|
|
18782
|
+
* Internally delegates to {@link OrderExecutor.executeOrder} and
|
|
18783
|
+
* yields the same status updates as the execution phase of {@link execute}:
|
|
18784
|
+
* `AWAITING_BIDS`, `BIDS_RECEIVED`, `BID_SELECTED`,
|
|
18785
|
+
* `FILLED`, `PARTIAL_FILL`, `EXPIRED`, or `FAILED`.
|
|
18786
|
+
*
|
|
18787
|
+
* Callers may check {@link isOrderFilled} or {@link isOrderRefunded} before
|
|
18788
|
+
* calling this method to avoid resuming an already-terminal order.
|
|
18789
|
+
*
|
|
18790
|
+
* @param order - A previously placed order with a valid `id` and `session`.
|
|
18791
|
+
* @param options - Optional tuning parameters for bid collection and execution.
|
|
18792
|
+
* @yields {@link IntentOrderStatusUpdate} at each execution stage.
|
|
18793
|
+
* @throws If the order is missing required fields for resumption.
|
|
18794
|
+
*/
|
|
18795
|
+
async *resume(order, options) {
|
|
18796
|
+
this.assertOrderCanResume(order);
|
|
18797
|
+
for await (const status of this.orderExecutor.executeOrder({
|
|
18798
|
+
order,
|
|
18799
|
+
sessionPrivateKey: options?.sessionPrivateKey,
|
|
18800
|
+
minBids: options?.minBids,
|
|
18801
|
+
pollIntervalMs: options?.pollIntervalMs,
|
|
18802
|
+
solver: options?.solver
|
|
18803
|
+
})) {
|
|
18804
|
+
yield status;
|
|
18805
|
+
}
|
|
18806
|
+
}
|
|
18633
18807
|
/**
|
|
18634
18808
|
* Returns both the native token cost and the relayer fee for cancelling an
|
|
18635
18809
|
* order. Use `relayerFee` to approve the ERC-20 spend before submitting.
|