@hyperbridge/sdk 2.8.12 → 2.8.16
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 +807 -906
- package/dist/browser/index.js +1487 -2099
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.cjs +1510 -2117
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +405 -179
- package/dist/node/index.d.ts +405 -179
- package/dist/node/index.js +1487 -2099
- package/dist/node/index.js.map +1 -1
- package/dist/node/{intents-helpers-C9PJp8rx.d.cts → intents-helpers-BHl2If1T.d.cts} +909 -2908
- package/dist/node/{intents-helpers-C9PJp8rx.d.ts → intents-helpers-BHl2If1T.d.ts} +909 -2908
- package/dist/node/intents-helpers.cjs +499 -1229
- package/dist/node/intents-helpers.cjs.map +1 -1
- package/dist/node/intents-helpers.d.cts +1 -3
- package/dist/node/intents-helpers.d.ts +1 -3
- package/dist/node/intents-helpers.js +498 -1214
- package/dist/node/intents-helpers.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { encodeAbiParameters, encodeFunctionData, decodeFunctionData, decodeAbiParameters, numberToBytes, bytesToBigInt } from 'viem';
|
|
2
2
|
import '@polkadot/api';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { hexToU8a, u8aToHex, isHex } from '@polkadot/util';
|
|
4
|
+
import '@polkadot/util-crypto';
|
|
5
5
|
import { Struct, Vector, u8, Bytes } from 'scale-ts';
|
|
6
6
|
import 'p-queue';
|
|
7
|
-
import { privateKeyToAccount } from 'viem/accounts';
|
|
8
7
|
|
|
9
8
|
// src/protocols/intents/decode-utils.ts
|
|
10
9
|
|
|
@@ -65,13 +64,70 @@ function decodeERC7821ExecuteBatch(callData) {
|
|
|
65
64
|
}
|
|
66
65
|
}
|
|
67
66
|
|
|
67
|
+
// src/chains/intentsCoprocessor.ts
|
|
68
|
+
new TextEncoder().encode("intents::bid::");
|
|
69
|
+
Struct({ filler: Bytes(32), user_op: Vector(u8) });
|
|
70
|
+
var PackedUserOperationCodec = Struct({
|
|
71
|
+
sender: Bytes(20),
|
|
72
|
+
// address is 20 bytes
|
|
73
|
+
nonce: Bytes(32),
|
|
74
|
+
// uint256 as 32 bytes
|
|
75
|
+
initCode: Vector(u8),
|
|
76
|
+
// variable length bytes
|
|
77
|
+
callData: Vector(u8),
|
|
78
|
+
// variable length bytes
|
|
79
|
+
accountGasLimits: Bytes(32),
|
|
80
|
+
// bytes32
|
|
81
|
+
preVerificationGas: Bytes(32),
|
|
82
|
+
// uint256 as 32 bytes
|
|
83
|
+
gasFees: Bytes(32),
|
|
84
|
+
// bytes32
|
|
85
|
+
paymasterAndData: Vector(u8),
|
|
86
|
+
// variable length bytes
|
|
87
|
+
signature: Vector(u8)
|
|
88
|
+
// variable length bytes
|
|
89
|
+
});
|
|
90
|
+
function encodeUserOpScale(userOp) {
|
|
91
|
+
const encoded = PackedUserOperationCodec.enc({
|
|
92
|
+
sender: hexToU8a(userOp.sender),
|
|
93
|
+
nonce: numberToBytes(userOp.nonce, { size: 32 }),
|
|
94
|
+
initCode: Array.from(hexToU8a(userOp.initCode)),
|
|
95
|
+
callData: Array.from(hexToU8a(userOp.callData)),
|
|
96
|
+
accountGasLimits: hexToU8a(userOp.accountGasLimits),
|
|
97
|
+
preVerificationGas: numberToBytes(userOp.preVerificationGas, { size: 32 }),
|
|
98
|
+
gasFees: hexToU8a(userOp.gasFees),
|
|
99
|
+
paymasterAndData: Array.from(hexToU8a(userOp.paymasterAndData)),
|
|
100
|
+
signature: Array.from(hexToU8a(userOp.signature))
|
|
101
|
+
});
|
|
102
|
+
return u8aToHex(encoded);
|
|
103
|
+
}
|
|
104
|
+
function decodeUserOpScale(hex) {
|
|
105
|
+
const decoded = PackedUserOperationCodec.dec(hexToU8a(hex));
|
|
106
|
+
return {
|
|
107
|
+
sender: u8aToHex(new Uint8Array(decoded.sender)),
|
|
108
|
+
nonce: bytesToBigInt(new Uint8Array(decoded.nonce)),
|
|
109
|
+
initCode: u8aToHex(new Uint8Array(decoded.initCode)),
|
|
110
|
+
callData: u8aToHex(new Uint8Array(decoded.callData)),
|
|
111
|
+
accountGasLimits: u8aToHex(new Uint8Array(decoded.accountGasLimits)),
|
|
112
|
+
preVerificationGas: bytesToBigInt(new Uint8Array(decoded.preVerificationGas)),
|
|
113
|
+
gasFees: u8aToHex(new Uint8Array(decoded.gasFees)),
|
|
114
|
+
paymasterAndData: u8aToHex(new Uint8Array(decoded.paymasterAndData)),
|
|
115
|
+
signature: u8aToHex(new Uint8Array(decoded.signature))
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
68
119
|
// src/abis/IntentGatewayV2.ts
|
|
69
120
|
var ABI2 = [
|
|
70
121
|
{
|
|
71
122
|
type: "constructor",
|
|
72
123
|
inputs: [
|
|
73
124
|
{
|
|
74
|
-
name: "
|
|
125
|
+
name: "intrinsic",
|
|
126
|
+
type: "address",
|
|
127
|
+
internalType: "address"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: "extrinsic",
|
|
75
131
|
type: "address",
|
|
76
132
|
internalType: "address"
|
|
77
133
|
}
|
|
@@ -170,8 +226,8 @@ var ABI2 = [
|
|
|
170
226
|
},
|
|
171
227
|
{
|
|
172
228
|
name: "",
|
|
173
|
-
type: "
|
|
174
|
-
internalType: "
|
|
229
|
+
type: "uint256",
|
|
230
|
+
internalType: "uint256"
|
|
175
231
|
}
|
|
176
232
|
],
|
|
177
233
|
outputs: [
|
|
@@ -185,20 +241,31 @@ var ABI2 = [
|
|
|
185
241
|
},
|
|
186
242
|
{
|
|
187
243
|
type: "function",
|
|
188
|
-
name: "
|
|
189
|
-
inputs: [
|
|
244
|
+
name: "_partialFills",
|
|
245
|
+
inputs: [
|
|
246
|
+
{
|
|
247
|
+
name: "",
|
|
248
|
+
type: "bytes32",
|
|
249
|
+
internalType: "bytes32"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: "",
|
|
253
|
+
type: "uint256",
|
|
254
|
+
internalType: "uint256"
|
|
255
|
+
}
|
|
256
|
+
],
|
|
190
257
|
outputs: [
|
|
191
258
|
{
|
|
192
259
|
name: "",
|
|
193
|
-
type: "
|
|
194
|
-
internalType: "
|
|
260
|
+
type: "uint256",
|
|
261
|
+
internalType: "uint256"
|
|
195
262
|
}
|
|
196
263
|
],
|
|
197
264
|
stateMutability: "view"
|
|
198
265
|
},
|
|
199
266
|
{
|
|
200
267
|
type: "function",
|
|
201
|
-
name: "
|
|
268
|
+
name: "_protocolFees",
|
|
202
269
|
inputs: [
|
|
203
270
|
{
|
|
204
271
|
name: "",
|
|
@@ -207,19 +274,31 @@ var ABI2 = [
|
|
|
207
274
|
},
|
|
208
275
|
{
|
|
209
276
|
name: "",
|
|
210
|
-
type: "
|
|
211
|
-
internalType: "
|
|
277
|
+
type: "uint256",
|
|
278
|
+
internalType: "uint256"
|
|
212
279
|
}
|
|
213
280
|
],
|
|
214
281
|
outputs: [
|
|
215
282
|
{
|
|
216
|
-
name: "",
|
|
283
|
+
name: "amount",
|
|
284
|
+
type: "uint256",
|
|
285
|
+
internalType: "uint256"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
name: "committed",
|
|
217
289
|
type: "uint256",
|
|
218
290
|
internalType: "uint256"
|
|
219
291
|
}
|
|
220
292
|
],
|
|
221
293
|
stateMutability: "view"
|
|
222
294
|
},
|
|
295
|
+
{
|
|
296
|
+
type: "function",
|
|
297
|
+
name: "acceptOwnership",
|
|
298
|
+
inputs: [],
|
|
299
|
+
outputs: [],
|
|
300
|
+
stateMutability: "nonpayable"
|
|
301
|
+
},
|
|
223
302
|
{
|
|
224
303
|
type: "function",
|
|
225
304
|
name: "calculateCommitmentSlotHash",
|
|
@@ -429,6 +508,19 @@ var ABI2 = [
|
|
|
429
508
|
],
|
|
430
509
|
stateMutability: "view"
|
|
431
510
|
},
|
|
511
|
+
{
|
|
512
|
+
type: "function",
|
|
513
|
+
name: "extrinsicModule",
|
|
514
|
+
inputs: [],
|
|
515
|
+
outputs: [
|
|
516
|
+
{
|
|
517
|
+
name: "",
|
|
518
|
+
type: "address",
|
|
519
|
+
internalType: "address"
|
|
520
|
+
}
|
|
521
|
+
],
|
|
522
|
+
stateMutability: "view"
|
|
523
|
+
},
|
|
432
524
|
{
|
|
433
525
|
type: "function",
|
|
434
526
|
name: "fillOrder",
|
|
@@ -591,6 +683,23 @@ var ABI2 = [
|
|
|
591
683
|
internalType: "uint256"
|
|
592
684
|
}
|
|
593
685
|
]
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
name: "inputs",
|
|
689
|
+
type: "tuple[]",
|
|
690
|
+
internalType: "struct TokenInfo[]",
|
|
691
|
+
components: [
|
|
692
|
+
{
|
|
693
|
+
name: "token",
|
|
694
|
+
type: "bytes32",
|
|
695
|
+
internalType: "bytes32"
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
name: "amount",
|
|
699
|
+
type: "uint256",
|
|
700
|
+
internalType: "uint256"
|
|
701
|
+
}
|
|
702
|
+
]
|
|
594
703
|
}
|
|
595
704
|
]
|
|
596
705
|
}
|
|
@@ -616,51 +725,63 @@ var ABI2 = [
|
|
|
616
725
|
name: "initialize",
|
|
617
726
|
inputs: [
|
|
618
727
|
{
|
|
619
|
-
name: "
|
|
728
|
+
name: "init",
|
|
620
729
|
type: "tuple",
|
|
621
|
-
internalType: "struct
|
|
730
|
+
internalType: "struct InitParams",
|
|
622
731
|
components: [
|
|
623
732
|
{
|
|
624
|
-
name: "
|
|
625
|
-
type: "
|
|
626
|
-
internalType: "
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
733
|
+
name: "params",
|
|
734
|
+
type: "tuple",
|
|
735
|
+
internalType: "struct Params",
|
|
736
|
+
components: [
|
|
737
|
+
{
|
|
738
|
+
name: "host",
|
|
739
|
+
type: "address",
|
|
740
|
+
internalType: "address"
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
name: "dispatcher",
|
|
744
|
+
type: "address",
|
|
745
|
+
internalType: "address"
|
|
746
|
+
},
|
|
747
|
+
{
|
|
748
|
+
name: "solverSelection",
|
|
749
|
+
type: "bool",
|
|
750
|
+
internalType: "bool"
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
name: "surplusShareBps",
|
|
754
|
+
type: "uint256",
|
|
755
|
+
internalType: "uint256"
|
|
756
|
+
},
|
|
757
|
+
{
|
|
758
|
+
name: "protocolFeeBps",
|
|
759
|
+
type: "uint256",
|
|
760
|
+
internalType: "uint256"
|
|
761
|
+
},
|
|
762
|
+
{
|
|
763
|
+
name: "priceOracle",
|
|
764
|
+
type: "address",
|
|
765
|
+
internalType: "address"
|
|
766
|
+
}
|
|
767
|
+
]
|
|
637
768
|
},
|
|
638
769
|
{
|
|
639
|
-
name: "
|
|
640
|
-
type: "
|
|
641
|
-
internalType: "
|
|
770
|
+
name: "peerChains",
|
|
771
|
+
type: "bytes[]",
|
|
772
|
+
internalType: "bytes[]"
|
|
642
773
|
},
|
|
643
774
|
{
|
|
644
|
-
name: "
|
|
645
|
-
type: "
|
|
646
|
-
internalType: "
|
|
775
|
+
name: "relayer",
|
|
776
|
+
type: "address",
|
|
777
|
+
internalType: "address"
|
|
647
778
|
},
|
|
648
779
|
{
|
|
649
|
-
name: "
|
|
780
|
+
name: "owner",
|
|
650
781
|
type: "address",
|
|
651
782
|
internalType: "address"
|
|
652
783
|
}
|
|
653
784
|
]
|
|
654
|
-
},
|
|
655
|
-
{
|
|
656
|
-
name: "peerChains",
|
|
657
|
-
type: "bytes[]",
|
|
658
|
-
internalType: "bytes[]"
|
|
659
|
-
},
|
|
660
|
-
{
|
|
661
|
-
name: "relayer",
|
|
662
|
-
type: "address",
|
|
663
|
-
internalType: "address"
|
|
664
785
|
}
|
|
665
786
|
],
|
|
666
787
|
outputs: [],
|
|
@@ -685,12 +806,25 @@ var ABI2 = [
|
|
|
685
806
|
],
|
|
686
807
|
stateMutability: "view"
|
|
687
808
|
},
|
|
809
|
+
{
|
|
810
|
+
type: "function",
|
|
811
|
+
name: "intrinsicModule",
|
|
812
|
+
inputs: [],
|
|
813
|
+
outputs: [
|
|
814
|
+
{
|
|
815
|
+
name: "",
|
|
816
|
+
type: "address",
|
|
817
|
+
internalType: "address"
|
|
818
|
+
}
|
|
819
|
+
],
|
|
820
|
+
stateMutability: "view"
|
|
821
|
+
},
|
|
688
822
|
{
|
|
689
823
|
type: "function",
|
|
690
824
|
name: "migrate",
|
|
691
825
|
inputs: [
|
|
692
826
|
{
|
|
693
|
-
name: "
|
|
827
|
+
name: "owner_",
|
|
694
828
|
type: "address",
|
|
695
829
|
internalType: "address"
|
|
696
830
|
}
|
|
@@ -765,7 +899,7 @@ var ABI2 = [
|
|
|
765
899
|
name: "onGetResponse",
|
|
766
900
|
inputs: [
|
|
767
901
|
{
|
|
768
|
-
name: "
|
|
902
|
+
name: "",
|
|
769
903
|
type: "tuple",
|
|
770
904
|
internalType: "struct IncomingGetResponse",
|
|
771
905
|
components: [
|
|
@@ -980,6 +1114,19 @@ var ABI2 = [
|
|
|
980
1114
|
outputs: [],
|
|
981
1115
|
stateMutability: "nonpayable"
|
|
982
1116
|
},
|
|
1117
|
+
{
|
|
1118
|
+
type: "function",
|
|
1119
|
+
name: "owner",
|
|
1120
|
+
inputs: [],
|
|
1121
|
+
outputs: [
|
|
1122
|
+
{
|
|
1123
|
+
name: "",
|
|
1124
|
+
type: "address",
|
|
1125
|
+
internalType: "address"
|
|
1126
|
+
}
|
|
1127
|
+
],
|
|
1128
|
+
stateMutability: "view"
|
|
1129
|
+
},
|
|
983
1130
|
{
|
|
984
1131
|
type: "function",
|
|
985
1132
|
name: "params",
|
|
@@ -1025,6 +1172,39 @@ var ABI2 = [
|
|
|
1025
1172
|
],
|
|
1026
1173
|
stateMutability: "view"
|
|
1027
1174
|
},
|
|
1175
|
+
{
|
|
1176
|
+
type: "function",
|
|
1177
|
+
name: "pause",
|
|
1178
|
+
inputs: [],
|
|
1179
|
+
outputs: [],
|
|
1180
|
+
stateMutability: "nonpayable"
|
|
1181
|
+
},
|
|
1182
|
+
{
|
|
1183
|
+
type: "function",
|
|
1184
|
+
name: "paused",
|
|
1185
|
+
inputs: [],
|
|
1186
|
+
outputs: [
|
|
1187
|
+
{
|
|
1188
|
+
name: "",
|
|
1189
|
+
type: "bool",
|
|
1190
|
+
internalType: "bool"
|
|
1191
|
+
}
|
|
1192
|
+
],
|
|
1193
|
+
stateMutability: "view"
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
type: "function",
|
|
1197
|
+
name: "pendingOwner",
|
|
1198
|
+
inputs: [],
|
|
1199
|
+
outputs: [
|
|
1200
|
+
{
|
|
1201
|
+
name: "",
|
|
1202
|
+
type: "address",
|
|
1203
|
+
internalType: "address"
|
|
1204
|
+
}
|
|
1205
|
+
],
|
|
1206
|
+
stateMutability: "view"
|
|
1207
|
+
},
|
|
1028
1208
|
{
|
|
1029
1209
|
type: "function",
|
|
1030
1210
|
name: "placeOrder",
|
|
@@ -1280,6 +1460,13 @@ var ABI2 = [
|
|
|
1280
1460
|
],
|
|
1281
1461
|
stateMutability: "view"
|
|
1282
1462
|
},
|
|
1463
|
+
{
|
|
1464
|
+
type: "function",
|
|
1465
|
+
name: "renounceOwnership",
|
|
1466
|
+
inputs: [],
|
|
1467
|
+
outputs: [],
|
|
1468
|
+
stateMutability: "nonpayable"
|
|
1469
|
+
},
|
|
1283
1470
|
{
|
|
1284
1471
|
type: "function",
|
|
1285
1472
|
name: "select",
|
|
@@ -1318,10 +1505,10 @@ var ABI2 = [
|
|
|
1318
1505
|
},
|
|
1319
1506
|
{
|
|
1320
1507
|
type: "function",
|
|
1321
|
-
name: "
|
|
1508
|
+
name: "transferOwnership",
|
|
1322
1509
|
inputs: [
|
|
1323
1510
|
{
|
|
1324
|
-
name: "
|
|
1511
|
+
name: "newOwner",
|
|
1325
1512
|
type: "address",
|
|
1326
1513
|
internalType: "address"
|
|
1327
1514
|
}
|
|
@@ -1331,19 +1518,8 @@ var ABI2 = [
|
|
|
1331
1518
|
},
|
|
1332
1519
|
{
|
|
1333
1520
|
type: "function",
|
|
1334
|
-
name: "
|
|
1335
|
-
inputs: [
|
|
1336
|
-
{
|
|
1337
|
-
name: "newImplementation",
|
|
1338
|
-
type: "address",
|
|
1339
|
-
internalType: "address"
|
|
1340
|
-
},
|
|
1341
|
-
{
|
|
1342
|
-
name: "data",
|
|
1343
|
-
type: "bytes",
|
|
1344
|
-
internalType: "bytes"
|
|
1345
|
-
}
|
|
1346
|
-
],
|
|
1521
|
+
name: "unpause",
|
|
1522
|
+
inputs: [],
|
|
1347
1523
|
outputs: [],
|
|
1348
1524
|
stateMutability: "nonpayable"
|
|
1349
1525
|
},
|
|
@@ -1489,6 +1665,12 @@ var ABI2 = [
|
|
|
1489
1665
|
indexed: true,
|
|
1490
1666
|
internalType: "bytes32"
|
|
1491
1667
|
},
|
|
1668
|
+
{
|
|
1669
|
+
name: "solver",
|
|
1670
|
+
type: "address",
|
|
1671
|
+
indexed: false,
|
|
1672
|
+
internalType: "address"
|
|
1673
|
+
},
|
|
1492
1674
|
{
|
|
1493
1675
|
name: "tokens",
|
|
1494
1676
|
type: "tuple[]",
|
|
@@ -1726,12 +1908,50 @@ var ABI2 = [
|
|
|
1726
1908
|
},
|
|
1727
1909
|
{
|
|
1728
1910
|
type: "event",
|
|
1729
|
-
name: "
|
|
1911
|
+
name: "OwnershipTransferStarted",
|
|
1730
1912
|
inputs: [
|
|
1731
1913
|
{
|
|
1732
|
-
name: "
|
|
1733
|
-
type: "
|
|
1734
|
-
indexed:
|
|
1914
|
+
name: "previousOwner",
|
|
1915
|
+
type: "address",
|
|
1916
|
+
indexed: true,
|
|
1917
|
+
internalType: "address"
|
|
1918
|
+
},
|
|
1919
|
+
{
|
|
1920
|
+
name: "newOwner",
|
|
1921
|
+
type: "address",
|
|
1922
|
+
indexed: true,
|
|
1923
|
+
internalType: "address"
|
|
1924
|
+
}
|
|
1925
|
+
],
|
|
1926
|
+
anonymous: false
|
|
1927
|
+
},
|
|
1928
|
+
{
|
|
1929
|
+
type: "event",
|
|
1930
|
+
name: "OwnershipTransferred",
|
|
1931
|
+
inputs: [
|
|
1932
|
+
{
|
|
1933
|
+
name: "previousOwner",
|
|
1934
|
+
type: "address",
|
|
1935
|
+
indexed: true,
|
|
1936
|
+
internalType: "address"
|
|
1937
|
+
},
|
|
1938
|
+
{
|
|
1939
|
+
name: "newOwner",
|
|
1940
|
+
type: "address",
|
|
1941
|
+
indexed: true,
|
|
1942
|
+
internalType: "address"
|
|
1943
|
+
}
|
|
1944
|
+
],
|
|
1945
|
+
anonymous: false
|
|
1946
|
+
},
|
|
1947
|
+
{
|
|
1948
|
+
type: "event",
|
|
1949
|
+
name: "ParamsUpdated",
|
|
1950
|
+
inputs: [
|
|
1951
|
+
{
|
|
1952
|
+
name: "previous",
|
|
1953
|
+
type: "tuple",
|
|
1954
|
+
indexed: false,
|
|
1735
1955
|
internalType: "struct Params",
|
|
1736
1956
|
components: [
|
|
1737
1957
|
{
|
|
@@ -1864,46 +2084,73 @@ var ABI2 = [
|
|
|
1864
2084
|
},
|
|
1865
2085
|
{
|
|
1866
2086
|
type: "event",
|
|
1867
|
-
name: "
|
|
2087
|
+
name: "Paused",
|
|
1868
2088
|
inputs: [
|
|
1869
2089
|
{
|
|
1870
|
-
name: "
|
|
2090
|
+
name: "account",
|
|
1871
2091
|
type: "address",
|
|
1872
2092
|
indexed: false,
|
|
1873
2093
|
internalType: "address"
|
|
2094
|
+
}
|
|
2095
|
+
],
|
|
2096
|
+
anonymous: false
|
|
2097
|
+
},
|
|
2098
|
+
{
|
|
2099
|
+
type: "event",
|
|
2100
|
+
name: "ProtocolFeeRefunded",
|
|
2101
|
+
inputs: [
|
|
2102
|
+
{
|
|
2103
|
+
name: "commitment",
|
|
2104
|
+
type: "bytes32",
|
|
2105
|
+
indexed: true,
|
|
2106
|
+
internalType: "bytes32"
|
|
1874
2107
|
},
|
|
1875
2108
|
{
|
|
1876
|
-
name: "
|
|
2109
|
+
name: "token",
|
|
1877
2110
|
type: "address",
|
|
1878
|
-
indexed:
|
|
2111
|
+
indexed: true,
|
|
1879
2112
|
internalType: "address"
|
|
2113
|
+
},
|
|
2114
|
+
{
|
|
2115
|
+
name: "amount",
|
|
2116
|
+
type: "uint256",
|
|
2117
|
+
indexed: false,
|
|
2118
|
+
internalType: "uint256"
|
|
1880
2119
|
}
|
|
1881
2120
|
],
|
|
1882
2121
|
anonymous: false
|
|
1883
2122
|
},
|
|
1884
2123
|
{
|
|
1885
2124
|
type: "event",
|
|
1886
|
-
name: "
|
|
2125
|
+
name: "RelayerUpdated",
|
|
1887
2126
|
inputs: [
|
|
1888
2127
|
{
|
|
1889
|
-
name: "
|
|
2128
|
+
name: "previous",
|
|
1890
2129
|
type: "address",
|
|
1891
|
-
indexed:
|
|
2130
|
+
indexed: false,
|
|
2131
|
+
internalType: "address"
|
|
2132
|
+
},
|
|
2133
|
+
{
|
|
2134
|
+
name: "current",
|
|
2135
|
+
type: "address",
|
|
2136
|
+
indexed: false,
|
|
1892
2137
|
internalType: "address"
|
|
1893
2138
|
}
|
|
1894
2139
|
],
|
|
1895
2140
|
anonymous: false
|
|
1896
2141
|
},
|
|
1897
2142
|
{
|
|
1898
|
-
type: "
|
|
1899
|
-
name: "
|
|
2143
|
+
type: "event",
|
|
2144
|
+
name: "Unpaused",
|
|
1900
2145
|
inputs: [
|
|
1901
2146
|
{
|
|
1902
|
-
name: "
|
|
2147
|
+
name: "account",
|
|
1903
2148
|
type: "address",
|
|
2149
|
+
indexed: false,
|
|
1904
2150
|
internalType: "address"
|
|
1905
2151
|
}
|
|
1906
|
-
]
|
|
2152
|
+
],
|
|
2153
|
+
anonymous: false
|
|
1907
2154
|
},
|
|
1908
2155
|
{
|
|
1909
2156
|
type: "error",
|
|
@@ -1939,28 +2186,17 @@ var ABI2 = [
|
|
|
1939
2186
|
},
|
|
1940
2187
|
{
|
|
1941
2188
|
type: "error",
|
|
1942
|
-
name: "
|
|
1943
|
-
inputs: [
|
|
1944
|
-
{
|
|
1945
|
-
name: "implementation",
|
|
1946
|
-
type: "address",
|
|
1947
|
-
internalType: "address"
|
|
1948
|
-
}
|
|
1949
|
-
]
|
|
1950
|
-
},
|
|
1951
|
-
{
|
|
1952
|
-
type: "error",
|
|
1953
|
-
name: "ERC1967NonPayable",
|
|
2189
|
+
name: "EnforcedPause",
|
|
1954
2190
|
inputs: []
|
|
1955
2191
|
},
|
|
1956
2192
|
{
|
|
1957
2193
|
type: "error",
|
|
1958
|
-
name: "
|
|
2194
|
+
name: "ExpectedPause",
|
|
1959
2195
|
inputs: []
|
|
1960
2196
|
},
|
|
1961
2197
|
{
|
|
1962
2198
|
type: "error",
|
|
1963
|
-
name: "
|
|
2199
|
+
name: "Expired",
|
|
1964
2200
|
inputs: []
|
|
1965
2201
|
},
|
|
1966
2202
|
{
|
|
@@ -2003,11 +2239,43 @@ var ABI2 = [
|
|
|
2003
2239
|
name: "NotInitializing",
|
|
2004
2240
|
inputs: []
|
|
2005
2241
|
},
|
|
2242
|
+
{
|
|
2243
|
+
type: "error",
|
|
2244
|
+
name: "OwnableInvalidOwner",
|
|
2245
|
+
inputs: [
|
|
2246
|
+
{
|
|
2247
|
+
name: "owner",
|
|
2248
|
+
type: "address",
|
|
2249
|
+
internalType: "address"
|
|
2250
|
+
}
|
|
2251
|
+
]
|
|
2252
|
+
},
|
|
2253
|
+
{
|
|
2254
|
+
type: "error",
|
|
2255
|
+
name: "OwnableUnauthorizedAccount",
|
|
2256
|
+
inputs: [
|
|
2257
|
+
{
|
|
2258
|
+
name: "account",
|
|
2259
|
+
type: "address",
|
|
2260
|
+
internalType: "address"
|
|
2261
|
+
}
|
|
2262
|
+
]
|
|
2263
|
+
},
|
|
2006
2264
|
{
|
|
2007
2265
|
type: "error",
|
|
2008
2266
|
name: "PartialFillNotAllowed",
|
|
2009
2267
|
inputs: []
|
|
2010
2268
|
},
|
|
2269
|
+
{
|
|
2270
|
+
type: "error",
|
|
2271
|
+
name: "RateBelowOrder",
|
|
2272
|
+
inputs: []
|
|
2273
|
+
},
|
|
2274
|
+
{
|
|
2275
|
+
type: "error",
|
|
2276
|
+
name: "RateFillTooSmall",
|
|
2277
|
+
inputs: []
|
|
2278
|
+
},
|
|
2011
2279
|
{
|
|
2012
2280
|
type: "error",
|
|
2013
2281
|
name: "ReentrancyGuardReentrantCall",
|
|
@@ -2068,60 +2336,6 @@ var ABI2 = [
|
|
|
2068
2336
|
];
|
|
2069
2337
|
var IntentGatewayV2_default = { ABI: ABI2 };
|
|
2070
2338
|
|
|
2071
|
-
// src/chains/intentsCoprocessor.ts
|
|
2072
|
-
u8aToHex(u8aConcat(xxhashAsU8a("System", 128), xxhashAsU8a("Events", 128)));
|
|
2073
|
-
new TextEncoder().encode("intents::bid::");
|
|
2074
|
-
new TextEncoder().encode("intents::phantom::order::");
|
|
2075
|
-
Struct({ filler: Bytes(32), user_op: Vector(u8) });
|
|
2076
|
-
var PackedUserOperationCodec = Struct({
|
|
2077
|
-
sender: Bytes(20),
|
|
2078
|
-
// address is 20 bytes
|
|
2079
|
-
nonce: Bytes(32),
|
|
2080
|
-
// uint256 as 32 bytes
|
|
2081
|
-
initCode: Vector(u8),
|
|
2082
|
-
// variable length bytes
|
|
2083
|
-
callData: Vector(u8),
|
|
2084
|
-
// variable length bytes
|
|
2085
|
-
accountGasLimits: Bytes(32),
|
|
2086
|
-
// bytes32
|
|
2087
|
-
preVerificationGas: Bytes(32),
|
|
2088
|
-
// uint256 as 32 bytes
|
|
2089
|
-
gasFees: Bytes(32),
|
|
2090
|
-
// bytes32
|
|
2091
|
-
paymasterAndData: Vector(u8),
|
|
2092
|
-
// variable length bytes
|
|
2093
|
-
signature: Vector(u8)
|
|
2094
|
-
// variable length bytes
|
|
2095
|
-
});
|
|
2096
|
-
function encodeUserOpScale(userOp) {
|
|
2097
|
-
const encoded = PackedUserOperationCodec.enc({
|
|
2098
|
-
sender: hexToU8a(userOp.sender),
|
|
2099
|
-
nonce: numberToBytes(userOp.nonce, { size: 32 }),
|
|
2100
|
-
initCode: Array.from(hexToU8a(userOp.initCode)),
|
|
2101
|
-
callData: Array.from(hexToU8a(userOp.callData)),
|
|
2102
|
-
accountGasLimits: hexToU8a(userOp.accountGasLimits),
|
|
2103
|
-
preVerificationGas: numberToBytes(userOp.preVerificationGas, { size: 32 }),
|
|
2104
|
-
gasFees: hexToU8a(userOp.gasFees),
|
|
2105
|
-
paymasterAndData: Array.from(hexToU8a(userOp.paymasterAndData)),
|
|
2106
|
-
signature: Array.from(hexToU8a(userOp.signature))
|
|
2107
|
-
});
|
|
2108
|
-
return u8aToHex(encoded);
|
|
2109
|
-
}
|
|
2110
|
-
function decodeUserOpScale(hex) {
|
|
2111
|
-
const decoded = PackedUserOperationCodec.dec(hexToU8a(hex));
|
|
2112
|
-
return {
|
|
2113
|
-
sender: u8aToHex(new Uint8Array(decoded.sender)),
|
|
2114
|
-
nonce: bytesToBigInt(new Uint8Array(decoded.nonce)),
|
|
2115
|
-
initCode: u8aToHex(new Uint8Array(decoded.initCode)),
|
|
2116
|
-
callData: u8aToHex(new Uint8Array(decoded.callData)),
|
|
2117
|
-
accountGasLimits: u8aToHex(new Uint8Array(decoded.accountGasLimits)),
|
|
2118
|
-
preVerificationGas: bytesToBigInt(new Uint8Array(decoded.preVerificationGas)),
|
|
2119
|
-
gasFees: u8aToHex(new Uint8Array(decoded.gasFees)),
|
|
2120
|
-
paymasterAndData: u8aToHex(new Uint8Array(decoded.paymasterAndData)),
|
|
2121
|
-
signature: u8aToHex(new Uint8Array(decoded.signature))
|
|
2122
|
-
};
|
|
2123
|
-
}
|
|
2124
|
-
|
|
2125
2339
|
// src/protocols/intents/liquidity-pool.ts
|
|
2126
2340
|
function sortPoolSymbols(symbolA, symbolB) {
|
|
2127
2341
|
return symbolA.toLowerCase() <= symbolB.toLowerCase() ? [symbolA, symbolB] : [symbolB, symbolA];
|
|
@@ -2129,553 +2343,6 @@ function sortPoolSymbols(symbolA, symbolB) {
|
|
|
2129
2343
|
function poolSlug(symbolA, symbolB) {
|
|
2130
2344
|
return sortPoolSymbols(symbolA, symbolB).join("-");
|
|
2131
2345
|
}
|
|
2132
|
-
var FILL_ORDER_V1_ABI = [
|
|
2133
|
-
{
|
|
2134
|
-
type: "function",
|
|
2135
|
-
name: "fillOrder",
|
|
2136
|
-
stateMutability: "payable",
|
|
2137
|
-
outputs: [],
|
|
2138
|
-
inputs: [
|
|
2139
|
-
ABI2.find((e) => e.type === "function" && e.name === "fillOrder").inputs[0],
|
|
2140
|
-
{
|
|
2141
|
-
name: "options",
|
|
2142
|
-
type: "tuple",
|
|
2143
|
-
internalType: "struct FillOptions",
|
|
2144
|
-
components: [
|
|
2145
|
-
{ name: "relayerFee", type: "uint256", internalType: "uint256" },
|
|
2146
|
-
{ name: "nativeDispatchFee", type: "uint256", internalType: "uint256" },
|
|
2147
|
-
{
|
|
2148
|
-
name: "outputs",
|
|
2149
|
-
type: "tuple[]",
|
|
2150
|
-
internalType: "struct TokenInfo[]",
|
|
2151
|
-
components: [
|
|
2152
|
-
{ name: "token", type: "bytes32", internalType: "bytes32" },
|
|
2153
|
-
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
2154
|
-
]
|
|
2155
|
-
}
|
|
2156
|
-
]
|
|
2157
|
-
}
|
|
2158
|
-
]
|
|
2159
|
-
}
|
|
2160
|
-
];
|
|
2161
|
-
function decodeFillOrder(data) {
|
|
2162
|
-
try {
|
|
2163
|
-
const decoded = decodeFunctionData({ abi: ABI2, data });
|
|
2164
|
-
if (decoded.functionName === "fillOrder" && decoded.args && decoded.args.length >= 2) {
|
|
2165
|
-
return { order: decoded.args[0], options: decoded.args[1] };
|
|
2166
|
-
}
|
|
2167
|
-
} catch {
|
|
2168
|
-
}
|
|
2169
|
-
try {
|
|
2170
|
-
const decoded = decodeFunctionData({ abi: FILL_ORDER_V1_ABI, data });
|
|
2171
|
-
if (decoded.functionName === "fillOrder" && decoded.args && decoded.args.length >= 2) {
|
|
2172
|
-
const legacy = decoded.args[1];
|
|
2173
|
-
return { order: decoded.args[0], options: { ...legacy, validUntil: 0n } };
|
|
2174
|
-
}
|
|
2175
|
-
} catch {
|
|
2176
|
-
}
|
|
2177
|
-
return null;
|
|
2178
|
-
}
|
|
2179
|
-
var SELECT_SOLVER_TYPEHASH = keccak256(toHex("SelectSolver(bytes32 commitment,address solver)"));
|
|
2180
|
-
var PACKED_USEROP_TYPEHASH = keccak256(
|
|
2181
|
-
toHex(
|
|
2182
|
-
"PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)"
|
|
2183
|
-
)
|
|
2184
|
-
);
|
|
2185
|
-
var DOMAIN_TYPEHASH = keccak256(
|
|
2186
|
-
toHex("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
|
|
2187
|
-
);
|
|
2188
|
-
var CryptoUtils = class _CryptoUtils {
|
|
2189
|
-
/**
|
|
2190
|
-
* @param ctx - Shared IntentsV2 context; used to access the bundler URL for
|
|
2191
|
-
* JSON-RPC calls.
|
|
2192
|
-
*/
|
|
2193
|
-
constructor(ctx) {
|
|
2194
|
-
this.ctx = ctx;
|
|
2195
|
-
}
|
|
2196
|
-
ctx;
|
|
2197
|
-
/**
|
|
2198
|
-
* Computes an EIP-712 domain separator for a given contract.
|
|
2199
|
-
*
|
|
2200
|
-
* @param contractName - Human-readable name of the contract (e.g. `"IntentGateway"`).
|
|
2201
|
-
* @param version - Version string (e.g. `"2"`).
|
|
2202
|
-
* @param chainId - Chain ID of the network the contract is deployed on.
|
|
2203
|
-
* @param contractAddress - Address of the verifying contract.
|
|
2204
|
-
* @returns The 32-byte domain separator as a hex string.
|
|
2205
|
-
*/
|
|
2206
|
-
static getDomainSeparator(contractName, version, chainId, contractAddress) {
|
|
2207
|
-
return keccak256(
|
|
2208
|
-
encodeAbiParameters(parseAbiParameters("bytes32, bytes32, bytes32, uint256, address"), [
|
|
2209
|
-
DOMAIN_TYPEHASH,
|
|
2210
|
-
keccak256(toHex(contractName)),
|
|
2211
|
-
keccak256(toHex(version)),
|
|
2212
|
-
chainId,
|
|
2213
|
-
contractAddress
|
|
2214
|
-
])
|
|
2215
|
-
);
|
|
2216
|
-
}
|
|
2217
|
-
/**
|
|
2218
|
-
* Signs a `SelectSolver` EIP-712 message with a session key.
|
|
2219
|
-
*
|
|
2220
|
-
* The session key authorises the selection of a specific solver for the
|
|
2221
|
-
* given order commitment. The resulting signature is appended to the
|
|
2222
|
-
* solver's UserOperation signature before bundle submission.
|
|
2223
|
-
*
|
|
2224
|
-
* @param commitment - The order commitment (bytes32) being fulfilled.
|
|
2225
|
-
* @param solverAddress - Address of the solver account selected to fill the order.
|
|
2226
|
-
* @param domainSeparator - EIP-712 domain separator for the IntentGatewayV2 contract.
|
|
2227
|
-
* @param privateKey - Hex-encoded private key of the session key that signs the message.
|
|
2228
|
-
* @returns The ECDSA signature as a hex string, or `null` if signing fails.
|
|
2229
|
-
*/
|
|
2230
|
-
static async signSolverSelection(commitment, solverAddress, domainSeparator, privateKey) {
|
|
2231
|
-
const account = privateKeyToAccount(privateKey);
|
|
2232
|
-
const structHash = keccak256(
|
|
2233
|
-
encodeAbiParameters(
|
|
2234
|
-
[{ type: "bytes32" }, { type: "bytes32" }, { type: "address" }],
|
|
2235
|
-
[SELECT_SOLVER_TYPEHASH, commitment, solverAddress]
|
|
2236
|
-
)
|
|
2237
|
-
);
|
|
2238
|
-
const digest = keccak256(concat(["0x1901", domainSeparator, structHash]));
|
|
2239
|
-
const signature = await account.sign({ hash: digest });
|
|
2240
|
-
return signature;
|
|
2241
|
-
}
|
|
2242
|
-
/**
|
|
2243
|
-
* Computes the EIP-712 hash of a `PackedUserOperation` as defined by
|
|
2244
|
-
* ERC-4337 EntryPoint v0.8.
|
|
2245
|
-
*
|
|
2246
|
-
* @param userOp - The packed UserOperation to hash.
|
|
2247
|
-
* @param entryPoint - Address of the EntryPoint v0.8 contract.
|
|
2248
|
-
* @param chainId - Chain ID of the network on which the operation will execute.
|
|
2249
|
-
* @returns The UserOperation hash as a hex string.
|
|
2250
|
-
*/
|
|
2251
|
-
static computeUserOpHash(userOp, entryPoint, chainId) {
|
|
2252
|
-
const structHash = _CryptoUtils.getPackedUserStructHash(userOp);
|
|
2253
|
-
const domainSeparator = _CryptoUtils.getDomainSeparator("ERC4337", "1", chainId, entryPoint);
|
|
2254
|
-
return keccak256(
|
|
2255
|
-
encodePacked(["bytes1", "bytes1", "bytes32", "bytes32"], ["0x19", "0x01", domainSeparator, structHash])
|
|
2256
|
-
);
|
|
2257
|
-
}
|
|
2258
|
-
/**
|
|
2259
|
-
* Derives the ERC-4337 nonce key that binds a bid UserOperation to its
|
|
2260
|
-
* order and session key: the lower 192 bits of
|
|
2261
|
-
* `keccak256(commitment ‖ sessionKey)`. `SolverAccount` rejects bid
|
|
2262
|
-
* operations whose nonce key differs — this is what lets the solver sign
|
|
2263
|
-
* the plain userOpHash while staying committed to the order and to the
|
|
2264
|
-
* session key it bid against.
|
|
2265
|
-
*
|
|
2266
|
-
* @param commitment - The order commitment (`order.id`).
|
|
2267
|
-
* @param sessionKey - The order's session key address (`order.session`).
|
|
2268
|
-
* @returns The 192-bit nonce key as a bigint (pass to `EntryPoint.getNonce`).
|
|
2269
|
-
*/
|
|
2270
|
-
static bidNonceKey(commitment, sessionKey) {
|
|
2271
|
-
return BigInt(keccak256(encodePacked(["bytes32", "address"], [commitment, sessionKey]))) & (1n << 192n) - 1n;
|
|
2272
|
-
}
|
|
2273
|
-
/**
|
|
2274
|
-
* Builds the EIP-712 typed-data payload whose digest is the EntryPoint v0.8
|
|
2275
|
-
* `userOpHash` (i.e. `hashTypedData(packedUserOpTypedData(...)) ===
|
|
2276
|
-
* computeUserOpHash(...)`). Signing this typed data is bit-identical to
|
|
2277
|
-
* signing the raw userOpHash, but keeps the full operation visible to
|
|
2278
|
-
* signing infrastructure (hardware wallets, MPC/TEE policy engines) instead
|
|
2279
|
-
* of an opaque 32-byte digest.
|
|
2280
|
-
*
|
|
2281
|
-
* The payload must be a standard self-describing `eth_signTypedData_v4`
|
|
2282
|
-
* payload — `EIP712Domain` listed in `types`, `chainId` as a JSON number —
|
|
2283
|
-
* because some signing backends (e.g. MPC Vault) hash it server-side from
|
|
2284
|
-
* the JSON rather than locally via viem. viem ignores both details when
|
|
2285
|
-
* hashing, so the digest is unchanged for local signers.
|
|
2286
|
-
*
|
|
2287
|
-
* @param userOp - The packed UserOperation to sign (signature field ignored).
|
|
2288
|
-
* @param entryPoint - Address of the EntryPoint v0.8 contract.
|
|
2289
|
-
* @param chainId - Chain ID of the network on which the operation will execute.
|
|
2290
|
-
* @returns A viem `TypedDataDefinition` for the operation.
|
|
2291
|
-
*/
|
|
2292
|
-
static packedUserOpTypedData(userOp, entryPoint, chainId) {
|
|
2293
|
-
return {
|
|
2294
|
-
domain: {
|
|
2295
|
-
name: "ERC4337",
|
|
2296
|
-
version: "1",
|
|
2297
|
-
// Runtime number so JSON.stringify emits a canonical v4 numeric chainId for
|
|
2298
|
-
// server-side hashers; viem's uint256 type mapping wants bigint but its
|
|
2299
|
-
// runtime accepts numbers, hence the cast.
|
|
2300
|
-
chainId: Number(chainId),
|
|
2301
|
-
verifyingContract: entryPoint
|
|
2302
|
-
},
|
|
2303
|
-
// `as const`: viem derives the domain's TYPE from `types.EIP712Domain`, so the
|
|
2304
|
-
// entries must stay string literals — widened `string` fields make viem's
|
|
2305
|
-
// typed-data generics reject the payload at every call site.
|
|
2306
|
-
types: {
|
|
2307
|
-
EIP712Domain: [
|
|
2308
|
-
{ name: "name", type: "string" },
|
|
2309
|
-
{ name: "version", type: "string" },
|
|
2310
|
-
{ name: "chainId", type: "uint256" },
|
|
2311
|
-
{ name: "verifyingContract", type: "address" }
|
|
2312
|
-
],
|
|
2313
|
-
PackedUserOperation: [
|
|
2314
|
-
{ name: "sender", type: "address" },
|
|
2315
|
-
{ name: "nonce", type: "uint256" },
|
|
2316
|
-
{ name: "initCode", type: "bytes" },
|
|
2317
|
-
{ name: "callData", type: "bytes" },
|
|
2318
|
-
{ name: "accountGasLimits", type: "bytes32" },
|
|
2319
|
-
{ name: "preVerificationGas", type: "uint256" },
|
|
2320
|
-
{ name: "gasFees", type: "bytes32" },
|
|
2321
|
-
{ name: "paymasterAndData", type: "bytes" }
|
|
2322
|
-
]
|
|
2323
|
-
},
|
|
2324
|
-
primaryType: "PackedUserOperation",
|
|
2325
|
-
message: {
|
|
2326
|
-
sender: userOp.sender,
|
|
2327
|
-
nonce: userOp.nonce,
|
|
2328
|
-
initCode: userOp.initCode,
|
|
2329
|
-
callData: userOp.callData,
|
|
2330
|
-
accountGasLimits: userOp.accountGasLimits,
|
|
2331
|
-
preVerificationGas: userOp.preVerificationGas,
|
|
2332
|
-
gasFees: userOp.gasFees,
|
|
2333
|
-
paymasterAndData: userOp.paymasterAndData
|
|
2334
|
-
}
|
|
2335
|
-
};
|
|
2336
|
-
}
|
|
2337
|
-
/**
|
|
2338
|
-
* Computes the EIP-712 struct hash of a `PackedUserOperation`.
|
|
2339
|
-
*
|
|
2340
|
-
* Hashes dynamic fields (`initCode`, `callData`, `paymasterAndData`) before
|
|
2341
|
-
* ABI-encoding so the final hash is a fixed-length 32-byte value.
|
|
2342
|
-
*
|
|
2343
|
-
* @param userOp - The packed UserOperation to hash.
|
|
2344
|
-
* @returns The struct hash as a 32-byte hex string.
|
|
2345
|
-
*/
|
|
2346
|
-
static getPackedUserStructHash(userOp) {
|
|
2347
|
-
return keccak256(
|
|
2348
|
-
encodeAbiParameters(
|
|
2349
|
-
parseAbiParameters("bytes32, address, uint256, bytes32, bytes32, bytes32, uint256, bytes32, bytes32"),
|
|
2350
|
-
[
|
|
2351
|
-
PACKED_USEROP_TYPEHASH,
|
|
2352
|
-
userOp.sender,
|
|
2353
|
-
userOp.nonce,
|
|
2354
|
-
keccak256(userOp.initCode),
|
|
2355
|
-
keccak256(userOp.callData),
|
|
2356
|
-
userOp.accountGasLimits,
|
|
2357
|
-
userOp.preVerificationGas,
|
|
2358
|
-
userOp.gasFees,
|
|
2359
|
-
keccak256(userOp.paymasterAndData)
|
|
2360
|
-
]
|
|
2361
|
-
)
|
|
2362
|
-
);
|
|
2363
|
-
}
|
|
2364
|
-
/**
|
|
2365
|
-
* Packs `verificationGasLimit` and `callGasLimit` into the ERC-4337
|
|
2366
|
-
* `accountGasLimits` bytes32 field.
|
|
2367
|
-
*
|
|
2368
|
-
* The high 16 bytes hold `verificationGasLimit` and the low 16 bytes hold
|
|
2369
|
-
* `callGasLimit`, matching the EntryPoint v0.8 packed representation.
|
|
2370
|
-
*
|
|
2371
|
-
* @param verificationGasLimit - Gas limit for the account verification step.
|
|
2372
|
-
* @param callGasLimit - Gas limit for the main execution call.
|
|
2373
|
-
* @returns A 32-byte hex string with both limits packed.
|
|
2374
|
-
*/
|
|
2375
|
-
static packGasLimits(verificationGasLimit, callGasLimit) {
|
|
2376
|
-
const verificationGasHex = pad(toHex(verificationGasLimit), { size: 16 });
|
|
2377
|
-
const callGasHex = pad(toHex(callGasLimit), { size: 16 });
|
|
2378
|
-
return concat([verificationGasHex, callGasHex]);
|
|
2379
|
-
}
|
|
2380
|
-
/**
|
|
2381
|
-
* Packs `maxPriorityFeePerGas` and `maxFeePerGas` into the ERC-4337
|
|
2382
|
-
* `gasFees` bytes32 field.
|
|
2383
|
-
*
|
|
2384
|
-
* The high 16 bytes hold `maxPriorityFeePerGas` and the low 16 bytes hold
|
|
2385
|
-
* `maxFeePerGas`, matching the EntryPoint v0.8 packed representation.
|
|
2386
|
-
*
|
|
2387
|
-
* @param maxPriorityFeePerGas - Maximum tip per gas (EIP-1559).
|
|
2388
|
-
* @param maxFeePerGas - Maximum total fee per gas (EIP-1559).
|
|
2389
|
-
* @returns A 32-byte hex string with both fee values packed.
|
|
2390
|
-
*/
|
|
2391
|
-
static packGasFees(maxPriorityFeePerGas, maxFeePerGas) {
|
|
2392
|
-
const priorityFeeHex = pad(toHex(maxPriorityFeePerGas), { size: 16 });
|
|
2393
|
-
const maxFeeHex = pad(toHex(maxFeePerGas), { size: 16 });
|
|
2394
|
-
return concat([priorityFeeHex, maxFeeHex]);
|
|
2395
|
-
}
|
|
2396
|
-
/**
|
|
2397
|
-
* Unpacks the `accountGasLimits` bytes32 field back into its constituent
|
|
2398
|
-
* gas limits.
|
|
2399
|
-
*
|
|
2400
|
-
* @param accountGasLimits - The packed 32-byte gas limits field from a `PackedUserOperation`.
|
|
2401
|
-
* @returns Object with `verificationGasLimit` and `callGasLimit` as bigints.
|
|
2402
|
-
*/
|
|
2403
|
-
static unpackGasLimits(accountGasLimits) {
|
|
2404
|
-
const hex = accountGasLimits.slice(2);
|
|
2405
|
-
const verificationGasLimit = BigInt(`0x${hex.slice(0, 32)}`);
|
|
2406
|
-
const callGasLimit = BigInt(`0x${hex.slice(32, 64)}`);
|
|
2407
|
-
return { verificationGasLimit, callGasLimit };
|
|
2408
|
-
}
|
|
2409
|
-
/**
|
|
2410
|
-
* Unpacks the `gasFees` bytes32 field back into its constituent fee values.
|
|
2411
|
-
*
|
|
2412
|
-
* @param gasFees - The packed 32-byte gas fees field from a `PackedUserOperation`.
|
|
2413
|
-
* @returns Object with `maxPriorityFeePerGas` and `maxFeePerGas` as bigints.
|
|
2414
|
-
*/
|
|
2415
|
-
static unpackGasFees(gasFees) {
|
|
2416
|
-
const hex = gasFees.slice(2);
|
|
2417
|
-
const maxPriorityFeePerGas = BigInt(`0x${hex.slice(0, 32)}`);
|
|
2418
|
-
const maxFeePerGas = BigInt(`0x${hex.slice(32, 64)}`);
|
|
2419
|
-
return { maxPriorityFeePerGas, maxFeePerGas };
|
|
2420
|
-
}
|
|
2421
|
-
/**
|
|
2422
|
-
* Converts a packed `PackedUserOperation` into the JSON object format
|
|
2423
|
-
* expected by ERC-4337 bundler JSON-RPC endpoints.
|
|
2424
|
-
*
|
|
2425
|
-
* Unpacks `accountGasLimits` and `gasFees`, separates optional factory and
|
|
2426
|
-
* paymaster fields, and converts all numeric fields to hex strings.
|
|
2427
|
-
*
|
|
2428
|
-
* @param userOp - The packed UserOperation to convert.
|
|
2429
|
-
* @returns A plain object safe to pass as the first element of bundler RPC params.
|
|
2430
|
-
*/
|
|
2431
|
-
static prepareBundlerCall(userOp) {
|
|
2432
|
-
const { verificationGasLimit, callGasLimit } = _CryptoUtils.unpackGasLimits(userOp.accountGasLimits);
|
|
2433
|
-
const { maxPriorityFeePerGas, maxFeePerGas } = _CryptoUtils.unpackGasFees(userOp.gasFees);
|
|
2434
|
-
const hasFactory = userOp.initCode && userOp.initCode !== "0x" && userOp.initCode.length > 2;
|
|
2435
|
-
const factory = hasFactory ? `0x${userOp.initCode.slice(2, 42)}` : void 0;
|
|
2436
|
-
const factoryData = hasFactory ? `0x${userOp.initCode.slice(42)}` : void 0;
|
|
2437
|
-
const hasPaymaster = userOp.paymasterAndData && userOp.paymasterAndData !== "0x" && userOp.paymasterAndData.length > 2;
|
|
2438
|
-
const pmHex = hasPaymaster ? userOp.paymasterAndData.slice(2) : "";
|
|
2439
|
-
const paymaster = hasPaymaster ? `0x${pmHex.slice(0, 40)}` : void 0;
|
|
2440
|
-
const paymasterVerificationGasLimit = hasPaymaster ? BigInt(`0x${pmHex.slice(40, 72)}`) : void 0;
|
|
2441
|
-
const paymasterPostOpGasLimit = hasPaymaster ? BigInt(`0x${pmHex.slice(72, 104)}`) : void 0;
|
|
2442
|
-
const paymasterData = hasPaymaster ? `0x${pmHex.slice(104)}` : void 0;
|
|
2443
|
-
const userOpBundler = {
|
|
2444
|
-
sender: userOp.sender,
|
|
2445
|
-
nonce: toHex(userOp.nonce),
|
|
2446
|
-
callData: userOp.callData,
|
|
2447
|
-
callGasLimit: toHex(callGasLimit),
|
|
2448
|
-
verificationGasLimit: toHex(verificationGasLimit),
|
|
2449
|
-
preVerificationGas: toHex(userOp.preVerificationGas),
|
|
2450
|
-
maxFeePerGas: toHex(maxFeePerGas),
|
|
2451
|
-
maxPriorityFeePerGas: toHex(maxPriorityFeePerGas),
|
|
2452
|
-
signature: userOp.signature
|
|
2453
|
-
};
|
|
2454
|
-
if (factory) {
|
|
2455
|
-
userOpBundler.factory = factory;
|
|
2456
|
-
userOpBundler.factoryData = factoryData || "0x";
|
|
2457
|
-
}
|
|
2458
|
-
if (paymaster) {
|
|
2459
|
-
userOpBundler.paymaster = paymaster;
|
|
2460
|
-
userOpBundler.paymasterData = paymasterData || "0x";
|
|
2461
|
-
userOpBundler.paymasterVerificationGasLimit = toHex(paymasterVerificationGasLimit);
|
|
2462
|
-
userOpBundler.paymasterPostOpGasLimit = toHex(paymasterPostOpGasLimit);
|
|
2463
|
-
}
|
|
2464
|
-
return userOpBundler;
|
|
2465
|
-
}
|
|
2466
|
-
/**
|
|
2467
|
-
* Sends a JSON-RPC request to the configured ERC-4337 bundler endpoint.
|
|
2468
|
-
*
|
|
2469
|
-
* @param method - The JSON-RPC method name (one of {@link BundlerMethod}).
|
|
2470
|
-
* @param params - Array of parameters for the RPC call.
|
|
2471
|
-
* @returns Resolves with the `result` field of the bundler's JSON-RPC response,
|
|
2472
|
-
* typed as `T`.
|
|
2473
|
-
* @throws If the bundler URL is not configured or the bundler returns an error.
|
|
2474
|
-
*/
|
|
2475
|
-
async sendBundler(method, params = []) {
|
|
2476
|
-
if (!this.ctx.bundlerUrl) {
|
|
2477
|
-
throw new Error("Bundler URL not configured");
|
|
2478
|
-
}
|
|
2479
|
-
const response = await fetch(this.ctx.bundlerUrl, {
|
|
2480
|
-
method: "POST",
|
|
2481
|
-
headers: { "Content-Type": "application/json" },
|
|
2482
|
-
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params })
|
|
2483
|
-
});
|
|
2484
|
-
const result = await response.json();
|
|
2485
|
-
if (result.error) {
|
|
2486
|
-
throw new Error(`Bundler error: ${result.error.message || JSON.stringify(result.error)}`);
|
|
2487
|
-
}
|
|
2488
|
-
return result.result;
|
|
2489
|
-
}
|
|
2490
|
-
/**
|
|
2491
|
-
* Sends multiple JSON-RPC requests to the bundler in a single HTTP call
|
|
2492
|
-
* using JSON-RPC 2.0 batch syntax. Results are returned in the same order
|
|
2493
|
-
* as the input `requests` array.
|
|
2494
|
-
*
|
|
2495
|
-
* @throws If the bundler URL is not configured, the HTTP call fails, or any
|
|
2496
|
-
* individual response contains an error.
|
|
2497
|
-
*/
|
|
2498
|
-
async sendBundlerBatch(requests) {
|
|
2499
|
-
if (!this.ctx.bundlerUrl) {
|
|
2500
|
-
throw new Error("Bundler URL not configured");
|
|
2501
|
-
}
|
|
2502
|
-
const body = requests.map((r, i) => ({
|
|
2503
|
-
jsonrpc: "2.0",
|
|
2504
|
-
id: i + 1,
|
|
2505
|
-
method: r.method,
|
|
2506
|
-
params: r.params
|
|
2507
|
-
}));
|
|
2508
|
-
const response = await fetch(this.ctx.bundlerUrl, {
|
|
2509
|
-
method: "POST",
|
|
2510
|
-
headers: { "Content-Type": "application/json" },
|
|
2511
|
-
body: JSON.stringify(body)
|
|
2512
|
-
});
|
|
2513
|
-
const results = await response.json();
|
|
2514
|
-
results.sort((a, b) => a.id - b.id);
|
|
2515
|
-
return results.map((r) => {
|
|
2516
|
-
if (r.error) {
|
|
2517
|
-
throw new Error(`Bundler error: ${r.error.message || JSON.stringify(r.error)}`);
|
|
2518
|
-
}
|
|
2519
|
-
return r.result;
|
|
2520
|
-
});
|
|
2521
|
-
}
|
|
2522
|
-
/**
|
|
2523
|
-
* Encodes a list of calls into ERC-7821 `execute` calldata using
|
|
2524
|
-
* single-batch mode (`ERC7821_BATCH_MODE`).
|
|
2525
|
-
*
|
|
2526
|
-
* @param calls - Ordered list of calls to batch; each specifies a `target`
|
|
2527
|
-
* address, ETH `value`, and `data`.
|
|
2528
|
-
* @returns ABI-encoded calldata for the ERC-7821 `execute(bytes32,bytes)` function.
|
|
2529
|
-
*/
|
|
2530
|
-
encodeERC7821Execute(calls) {
|
|
2531
|
-
const executionData = encodeAbiParameters(
|
|
2532
|
-
[{ type: "tuple[]", components: erc7281_default.ABI[1].components }],
|
|
2533
|
-
[calls.map((call) => ({ target: call.target, value: call.value, data: call.data }))]
|
|
2534
|
-
);
|
|
2535
|
-
return encodeFunctionData({
|
|
2536
|
-
abi: erc7281_default.ABI,
|
|
2537
|
-
functionName: "execute",
|
|
2538
|
-
args: [ERC7821_BATCH_MODE, executionData]
|
|
2539
|
-
});
|
|
2540
|
-
}
|
|
2541
|
-
/**
|
|
2542
|
-
* Decodes ERC-7821 `execute` calldata back into its constituent calls.
|
|
2543
|
-
*
|
|
2544
|
-
* Returns `null` if the calldata does not match the expected `execute`
|
|
2545
|
-
* function signature or cannot be decoded.
|
|
2546
|
-
*
|
|
2547
|
-
* @param callData - Hex-encoded calldata previously produced by
|
|
2548
|
-
* {@link encodeERC7821Execute} or an equivalent encoder.
|
|
2549
|
-
* @returns Array of decoded {@link ERC7821Call} objects, or `null` on failure.
|
|
2550
|
-
*/
|
|
2551
|
-
decodeERC7821Execute(callData) {
|
|
2552
|
-
try {
|
|
2553
|
-
const decoded = decodeFunctionData({
|
|
2554
|
-
abi: erc7281_default.ABI,
|
|
2555
|
-
data: callData
|
|
2556
|
-
});
|
|
2557
|
-
if (decoded?.functionName !== "execute" || !decoded.args || decoded.args.length < 2) {
|
|
2558
|
-
return null;
|
|
2559
|
-
}
|
|
2560
|
-
const executionData = decoded.args[1];
|
|
2561
|
-
const [calls] = decodeAbiParameters(
|
|
2562
|
-
[{ type: "tuple[]", components: erc7281_default.ABI[1].components }],
|
|
2563
|
-
executionData
|
|
2564
|
-
);
|
|
2565
|
-
return calls.map((call) => ({
|
|
2566
|
-
target: call.target,
|
|
2567
|
-
value: call.value,
|
|
2568
|
-
data: call.data
|
|
2569
|
-
}));
|
|
2570
|
-
} catch {
|
|
2571
|
-
return null;
|
|
2572
|
-
}
|
|
2573
|
-
}
|
|
2574
|
-
};
|
|
2575
|
-
|
|
2576
|
-
// src/protocols/intents/uniswap-v4-position.ts
|
|
2577
|
-
var Q96 = 1n << 96n;
|
|
2578
|
-
var MIN_TICK = -887272;
|
|
2579
|
-
var MAX_TICK = 887272;
|
|
2580
|
-
function word(data, index) {
|
|
2581
|
-
const hex = data.startsWith("0x") ? data.slice(2) : data;
|
|
2582
|
-
const start = index * 64;
|
|
2583
|
-
if (hex.length < start + 64) throw new Error(`return data too short for word ${index}`);
|
|
2584
|
-
return BigInt(`0x${hex.slice(start, start + 64)}`);
|
|
2585
|
-
}
|
|
2586
|
-
function asSigned(value, bits) {
|
|
2587
|
-
const width = 1n << BigInt(bits);
|
|
2588
|
-
const masked = value & width - 1n;
|
|
2589
|
-
return masked >= width >> 1n ? masked - width : masked;
|
|
2590
|
-
}
|
|
2591
|
-
function addressFromWord(data, index) {
|
|
2592
|
-
const hex = data.startsWith("0x") ? data.slice(2) : data;
|
|
2593
|
-
return `0x${hex.slice(index * 64 + 24, (index + 1) * 64)}`.toLowerCase();
|
|
2594
|
-
}
|
|
2595
|
-
function getSqrtRatioAtTick(tick) {
|
|
2596
|
-
if (!Number.isInteger(tick) || tick < MIN_TICK || tick > MAX_TICK) {
|
|
2597
|
-
throw new Error(`tick out of range: ${tick}`);
|
|
2598
|
-
}
|
|
2599
|
-
const absTick = BigInt(Math.abs(tick));
|
|
2600
|
-
let ratio = (absTick & 0x1n) !== 0n ? 0xfffcb933bd6fad37aa2d162d1a594001n : 0x100000000000000000000000000000000n;
|
|
2601
|
-
const factors = [
|
|
2602
|
-
[0x2n, 0xfff97272373d413259a46990580e213an],
|
|
2603
|
-
[0x4n, 0xfff2e50f5f656932ef12357cf3c7fdccn],
|
|
2604
|
-
[0x8n, 0xffe5caca7e10e4e61c3624eaa0941cd0n],
|
|
2605
|
-
[0x10n, 0xffcb9843d60f6159c9db58835c926644n],
|
|
2606
|
-
[0x20n, 0xff973b41fa98c081472e6896dfb254c0n],
|
|
2607
|
-
[0x40n, 0xff2ea16466c96a3843ec78b326b52861n],
|
|
2608
|
-
[0x80n, 0xfe5dee046a99a2a811c461f1969c3053n],
|
|
2609
|
-
[0x100n, 0xfcbe86c7900a88aedcffc83b479aa3a4n],
|
|
2610
|
-
[0x200n, 0xf987a7253ac413176f2b074cf7815e54n],
|
|
2611
|
-
[0x400n, 0xf3392b0822b70005940c7a398e4b70f3n],
|
|
2612
|
-
[0x800n, 0xe7159475a2c29b7443b29c7fa6e889d9n],
|
|
2613
|
-
[0x1000n, 0xd097f3bdfd2022b8845ad8f792aa5825n],
|
|
2614
|
-
[0x2000n, 0xa9f746462d870fdf8a65dc1f90e061e5n],
|
|
2615
|
-
[0x4000n, 0x70d869a156d2a1b890bb3df62baf32f7n],
|
|
2616
|
-
[0x8000n, 0x31be135f97d08fd981231505542fcfa6n],
|
|
2617
|
-
[0x10000n, 0x9aa508b5b7a84e1c677de54f3e99bc9n],
|
|
2618
|
-
[0x20000n, 0x5d6af8dedb81196699c329225ee604n],
|
|
2619
|
-
[0x40000n, 0x2216e584f5fa1ea926041bedfe98n],
|
|
2620
|
-
[0x80000n, 0x48a170391f7dc42444e8fa2n]
|
|
2621
|
-
];
|
|
2622
|
-
for (const [bit, factor] of factors) {
|
|
2623
|
-
if ((absTick & bit) !== 0n) ratio = ratio * factor >> 128n;
|
|
2624
|
-
}
|
|
2625
|
-
if (tick > 0) ratio = (1n << 256n) / ratio;
|
|
2626
|
-
return (ratio >> 32n) + (ratio % (1n << 32n) === 0n ? 0n : 1n);
|
|
2627
|
-
}
|
|
2628
|
-
function positionTicks(info) {
|
|
2629
|
-
return {
|
|
2630
|
-
tickLower: Number(asSigned(info >> 8n, 24)),
|
|
2631
|
-
tickUpper: Number(asSigned(info >> 32n, 24))
|
|
2632
|
-
};
|
|
2633
|
-
}
|
|
2634
|
-
function getAmountsForLiquidity(params) {
|
|
2635
|
-
let { sqrtRatioAX96, sqrtRatioBX96 } = params;
|
|
2636
|
-
const { sqrtPriceX96, liquidity } = params;
|
|
2637
|
-
if (sqrtRatioAX96 > sqrtRatioBX96) [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96];
|
|
2638
|
-
const amount0For = (from, to) => liquidity * Q96 * (to - from) / to / from;
|
|
2639
|
-
const amount1For = (from, to) => liquidity * (to - from) / Q96;
|
|
2640
|
-
if (sqrtPriceX96 <= sqrtRatioAX96) {
|
|
2641
|
-
return { amount0: amount0For(sqrtRatioAX96, sqrtRatioBX96), amount1: 0n };
|
|
2642
|
-
}
|
|
2643
|
-
if (sqrtPriceX96 < sqrtRatioBX96) {
|
|
2644
|
-
return {
|
|
2645
|
-
amount0: amount0For(sqrtPriceX96, sqrtRatioBX96),
|
|
2646
|
-
amount1: amount1For(sqrtRatioAX96, sqrtPriceX96)
|
|
2647
|
-
};
|
|
2648
|
-
}
|
|
2649
|
-
return { amount0: 0n, amount1: amount1For(sqrtRatioAX96, sqrtRatioBX96) };
|
|
2650
|
-
}
|
|
2651
|
-
function decodePoolAndPositionInfo(data) {
|
|
2652
|
-
const hex = data.startsWith("0x") ? data.slice(2) : data;
|
|
2653
|
-
if (hex.length < 6 * 64) throw new Error("getPoolAndPositionInfo returned too little data");
|
|
2654
|
-
const { tickLower, tickUpper } = positionTicks(word(data, 5));
|
|
2655
|
-
return {
|
|
2656
|
-
currency0: addressFromWord(data, 0),
|
|
2657
|
-
currency1: addressFromWord(data, 1),
|
|
2658
|
-
poolKeyEncoded: `0x${hex.slice(0, 5 * 64)}`,
|
|
2659
|
-
tickLower,
|
|
2660
|
-
tickUpper
|
|
2661
|
-
};
|
|
2662
|
-
}
|
|
2663
|
-
function positionAmountOfToken(params) {
|
|
2664
|
-
const { info, liquidity, sqrtPriceX96 } = params;
|
|
2665
|
-
const outputToken = params.outputToken.toLowerCase();
|
|
2666
|
-
if (outputToken !== info.currency0 && outputToken !== info.currency1) return 0n;
|
|
2667
|
-
if (liquidity <= 0n || sqrtPriceX96 <= 0n) return 0n;
|
|
2668
|
-
const { amount0, amount1 } = getAmountsForLiquidity({
|
|
2669
|
-
sqrtPriceX96,
|
|
2670
|
-
sqrtRatioAX96: getSqrtRatioAtTick(info.tickLower),
|
|
2671
|
-
sqrtRatioBX96: getSqrtRatioAtTick(info.tickUpper),
|
|
2672
|
-
liquidity
|
|
2673
|
-
});
|
|
2674
|
-
return outputToken === info.currency0 ? amount0 : amount1;
|
|
2675
|
-
}
|
|
2676
|
-
|
|
2677
|
-
// src/protocols/intents/phantom-aggregation.ts
|
|
2678
|
-
var ENTRY_POINT_V08_ADDRESS = "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108";
|
|
2679
2346
|
var injectedFetch;
|
|
2680
2347
|
function setAggregationFetch(fetchImpl) {
|
|
2681
2348
|
injectedFetch = fetchImpl;
|
|
@@ -2683,18 +2350,10 @@ function setAggregationFetch(fetchImpl) {
|
|
|
2683
2350
|
function rpcFetch() {
|
|
2684
2351
|
const f = injectedFetch ?? globalThis.fetch;
|
|
2685
2352
|
if (typeof f !== "function") {
|
|
2686
|
-
throw new Error("No fetch available; call setAggregationFetch() before
|
|
2353
|
+
throw new Error("No fetch available; call setAggregationFetch() before reading bids");
|
|
2687
2354
|
}
|
|
2688
2355
|
return f;
|
|
2689
2356
|
}
|
|
2690
|
-
var PhantomRpcError = class extends Error {
|
|
2691
|
-
constructor(message, cause) {
|
|
2692
|
-
super(message);
|
|
2693
|
-
this.cause = cause;
|
|
2694
|
-
this.name = "PhantomRpcError";
|
|
2695
|
-
}
|
|
2696
|
-
cause;
|
|
2697
|
-
};
|
|
2698
2357
|
async function rpcCall(url, payload) {
|
|
2699
2358
|
let lastErr;
|
|
2700
2359
|
for (let attempt = 0; attempt < 4; attempt++) {
|
|
@@ -2724,13 +2383,80 @@ async function rpcCall(url, payload) {
|
|
|
2724
2383
|
if (timer) clearTimeout(timer);
|
|
2725
2384
|
}
|
|
2726
2385
|
}
|
|
2727
|
-
throw new
|
|
2386
|
+
throw new Error(`RPC call failed after 4 attempts: ${url}`, { cause: lastErr });
|
|
2387
|
+
}
|
|
2388
|
+
async function fetchBidsForOrder(nodeUrl, commitment) {
|
|
2389
|
+
const data = await rpcCall(nodeUrl, {
|
|
2390
|
+
id: 1,
|
|
2391
|
+
jsonrpc: "2.0",
|
|
2392
|
+
method: "intents_getBidsForOrder",
|
|
2393
|
+
params: [commitment]
|
|
2394
|
+
});
|
|
2395
|
+
return Array.isArray(data.result) ? data.result : [];
|
|
2728
2396
|
}
|
|
2729
|
-
var FILL_ORDER_ABI = IntentGatewayV2_default.ABI;
|
|
2730
2397
|
var DECLARATION_V1 = 1;
|
|
2731
2398
|
var DECLARATION_V2 = 2;
|
|
2399
|
+
var PAYMASTER_ADDRESS_BYTES = 20;
|
|
2400
|
+
var PAYMASTER_GAS_LIMIT_BYTES = 16;
|
|
2401
|
+
var PAYMASTER_DATA_OFFSET = PAYMASTER_ADDRESS_BYTES + 2 * PAYMASTER_GAS_LIMIT_BYTES;
|
|
2402
|
+
var SIMPLEX_MODE_PERMIT2 = 2;
|
|
2403
|
+
var PERMIT2_DATA_BYTES = 1 + 20 + 32 + 32 + 32 + 1 + 32 + 32;
|
|
2404
|
+
var PERMIT2_SPONSORSHIP_BYTES = PAYMASTER_DATA_OFFSET + PERMIT2_DATA_BYTES;
|
|
2732
2405
|
var MAX_DECLARED_ENTRIES = 255;
|
|
2733
2406
|
var MAX_TOKEN_ID_BYTES = 32;
|
|
2407
|
+
function utf8Encode(text) {
|
|
2408
|
+
const bytes = [];
|
|
2409
|
+
for (const char of text) {
|
|
2410
|
+
const codePoint = char.codePointAt(0);
|
|
2411
|
+
if (codePoint < 128) bytes.push(codePoint);
|
|
2412
|
+
else if (codePoint < 2048) bytes.push(192 | codePoint >> 6, 128 | codePoint & 63);
|
|
2413
|
+
else if (codePoint < 65536) {
|
|
2414
|
+
bytes.push(224 | codePoint >> 12, 128 | codePoint >> 6 & 63, 128 | codePoint & 63);
|
|
2415
|
+
} else {
|
|
2416
|
+
bytes.push(
|
|
2417
|
+
240 | codePoint >> 18,
|
|
2418
|
+
128 | codePoint >> 12 & 63,
|
|
2419
|
+
128 | codePoint >> 6 & 63,
|
|
2420
|
+
128 | codePoint & 63
|
|
2421
|
+
);
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
return bytes;
|
|
2425
|
+
}
|
|
2426
|
+
function utf8Decode(bytes) {
|
|
2427
|
+
let text = "";
|
|
2428
|
+
for (let offset = 0; offset < bytes.length; ) {
|
|
2429
|
+
const lead = bytes[offset];
|
|
2430
|
+
let codePoint;
|
|
2431
|
+
let continuations;
|
|
2432
|
+
if (lead < 128) {
|
|
2433
|
+
codePoint = lead;
|
|
2434
|
+
continuations = 0;
|
|
2435
|
+
} else if ((lead & 224) === 192) {
|
|
2436
|
+
codePoint = lead & 31;
|
|
2437
|
+
continuations = 1;
|
|
2438
|
+
} else if ((lead & 240) === 224) {
|
|
2439
|
+
codePoint = lead & 15;
|
|
2440
|
+
continuations = 2;
|
|
2441
|
+
} else if ((lead & 248) === 240) {
|
|
2442
|
+
codePoint = lead & 7;
|
|
2443
|
+
continuations = 3;
|
|
2444
|
+
} else {
|
|
2445
|
+
return null;
|
|
2446
|
+
}
|
|
2447
|
+
if (offset + continuations >= bytes.length) return null;
|
|
2448
|
+
for (let index = 1; index <= continuations; index++) {
|
|
2449
|
+
const byte = bytes[offset + index];
|
|
2450
|
+
if ((byte & 192) !== 128) return null;
|
|
2451
|
+
codePoint = codePoint << 6 | byte & 63;
|
|
2452
|
+
}
|
|
2453
|
+
const overlong = continuations === 1 && codePoint < 128 || continuations === 2 && codePoint < 2048 || continuations === 3 && codePoint < 65536;
|
|
2454
|
+
if (overlong || codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343) return null;
|
|
2455
|
+
text += String.fromCodePoint(codePoint);
|
|
2456
|
+
offset += continuations + 1;
|
|
2457
|
+
}
|
|
2458
|
+
return text;
|
|
2459
|
+
}
|
|
2734
2460
|
function tokenIdToBytes(tokenId) {
|
|
2735
2461
|
if (tokenId < 0n) throw new Error(`Uniswap V4 tokenId cannot be negative: ${tokenId}`);
|
|
2736
2462
|
const bytes = [];
|
|
@@ -2753,7 +2479,7 @@ function encodePhantomBidDeclaration(declaration) {
|
|
|
2753
2479
|
const version = positions.length > 0 ? DECLARATION_V2 : DECLARATION_V1;
|
|
2754
2480
|
const bytes = [version, chains.length];
|
|
2755
2481
|
for (const chain of chains) {
|
|
2756
|
-
const encoded =
|
|
2482
|
+
const encoded = utf8Encode(chain);
|
|
2757
2483
|
if (encoded.length === 0 || encoded.length > 255) {
|
|
2758
2484
|
throw new Error(`Invalid state machine id in source chain declaration: ${chain}`);
|
|
2759
2485
|
}
|
|
@@ -2771,543 +2497,101 @@ function encodePhantomBidDeclaration(declaration) {
|
|
|
2771
2497
|
}
|
|
2772
2498
|
return u8aToHex(new Uint8Array(bytes));
|
|
2773
2499
|
}
|
|
2774
|
-
function
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
if (bytes.length < 2) return absent;
|
|
2779
|
-
const version = bytes[0];
|
|
2780
|
-
if (version !== DECLARATION_V1 && version !== DECLARATION_V2) return absent;
|
|
2500
|
+
function parseDeclaration(bytes, start) {
|
|
2501
|
+
if (bytes.length - start < 2) return null;
|
|
2502
|
+
const version = bytes[start];
|
|
2503
|
+
if (version !== DECLARATION_V1 && version !== DECLARATION_V2) return null;
|
|
2781
2504
|
const chains = [];
|
|
2782
|
-
let offset = 2;
|
|
2783
|
-
for (let entry = 0; entry < bytes[1]; entry++) {
|
|
2784
|
-
if (offset >= bytes.length) return
|
|
2505
|
+
let offset = start + 2;
|
|
2506
|
+
for (let entry = 0; entry < bytes[start + 1]; entry++) {
|
|
2507
|
+
if (offset >= bytes.length) return null;
|
|
2785
2508
|
const length = bytes[offset];
|
|
2786
2509
|
offset += 1;
|
|
2787
|
-
if (length === 0 || offset + length > bytes.length) return
|
|
2788
|
-
|
|
2510
|
+
if (length === 0 || offset + length > bytes.length) return null;
|
|
2511
|
+
const chain = utf8Decode(bytes.subarray(offset, offset + length));
|
|
2512
|
+
if (chain === null) return null;
|
|
2513
|
+
chains.push(chain);
|
|
2789
2514
|
offset += length;
|
|
2790
2515
|
}
|
|
2791
2516
|
const positions = [];
|
|
2792
2517
|
if (version === DECLARATION_V2) {
|
|
2793
|
-
if (offset >= bytes.length) return
|
|
2518
|
+
if (offset >= bytes.length) return null;
|
|
2794
2519
|
const count = bytes[offset];
|
|
2795
2520
|
offset += 1;
|
|
2796
2521
|
for (let entry = 0; entry < count; entry++) {
|
|
2797
|
-
if (offset >= bytes.length) return
|
|
2522
|
+
if (offset >= bytes.length) return null;
|
|
2798
2523
|
const length = bytes[offset];
|
|
2799
2524
|
offset += 1;
|
|
2800
|
-
if (length === 0 || length > MAX_TOKEN_ID_BYTES || offset + length > bytes.length) return
|
|
2801
|
-
|
|
2802
|
-
for (const byte of bytes.subarray(offset, offset + length)) tokenId = tokenId << 8n | BigInt(byte);
|
|
2803
|
-
positions.push(tokenId);
|
|
2525
|
+
if (length === 0 || length > MAX_TOKEN_ID_BYTES || offset + length > bytes.length) return null;
|
|
2526
|
+
positions.push(bytesToBigInt2(bytes.subarray(offset, offset + length)));
|
|
2804
2527
|
offset += length;
|
|
2805
2528
|
}
|
|
2806
2529
|
}
|
|
2807
|
-
if (offset !== bytes.length) return
|
|
2530
|
+
if (offset !== bytes.length) return null;
|
|
2808
2531
|
return { acceptedSources: chains, uniswapV4Positions: positions };
|
|
2809
2532
|
}
|
|
2810
|
-
function
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
return decodePhantomBidDeclaration(paymasterAndData).acceptedSources;
|
|
2815
|
-
}
|
|
2816
|
-
function zipFillLegs(assets, outputs) {
|
|
2817
|
-
return assets.map((asset, index) => {
|
|
2818
|
-
const rawAmount = outputs[index]?.amount;
|
|
2819
|
-
return {
|
|
2820
|
-
outputToken: asset.token,
|
|
2821
|
-
solverAmount: rawAmount === void 0 || rawAmount === null ? 0n : BigInt(rawAmount.toString())
|
|
2822
|
-
};
|
|
2823
|
-
});
|
|
2824
|
-
}
|
|
2825
|
-
var UNISWAP_QUOTE_HAIRCUT_BPS = 10n;
|
|
2826
|
-
function haircut(amount, bps) {
|
|
2827
|
-
return amount * (10000n - bps) / 10000n;
|
|
2828
|
-
}
|
|
2829
|
-
function applyUniswapQuoteHaircut(amount) {
|
|
2830
|
-
return haircut(amount, UNISWAP_QUOTE_HAIRCUT_BPS);
|
|
2831
|
-
}
|
|
2832
|
-
var SELECTOR_GATEWAY_PARAMS = "0xcff0ab96";
|
|
2833
|
-
var GATEWAY_PARAMS_WORDS = 6;
|
|
2834
|
-
var GATEWAY_PARAMS_FEE_WORD = 4;
|
|
2835
|
-
async function readProtocolFeeHaircutBps(evmRpcUrl, gatewayAddress) {
|
|
2836
|
-
const result = await rpcCall(evmRpcUrl, {
|
|
2837
|
-
id: 1,
|
|
2838
|
-
jsonrpc: "2.0",
|
|
2839
|
-
method: "eth_call",
|
|
2840
|
-
params: [{ to: gatewayAddress, data: SELECTOR_GATEWAY_PARAMS }, "latest"]
|
|
2841
|
-
});
|
|
2842
|
-
const hex = result.result;
|
|
2843
|
-
if (typeof hex !== "string" || hex.length < 2 + 64 * GATEWAY_PARAMS_WORDS) {
|
|
2844
|
-
throw new PhantomRpcError(`IntentGateway.params() returned no usable result from ${gatewayAddress} on ${evmRpcUrl}`);
|
|
2845
|
-
}
|
|
2846
|
-
const start = 2 + 64 * GATEWAY_PARAMS_FEE_WORD;
|
|
2847
|
-
const protocolFeeBps = BigInt(`0x${hex.slice(start, start + 64)}`);
|
|
2848
|
-
if (protocolFeeBps >= 10000n) {
|
|
2849
|
-
throw new PhantomRpcError(`IntentGateway ${gatewayAddress} reports an implausible protocol fee: ${protocolFeeBps} bps`);
|
|
2850
|
-
}
|
|
2851
|
-
return protocolFeeBps;
|
|
2852
|
-
}
|
|
2853
|
-
function applyProtocolFeeHaircut(amount, protocolFeeBps) {
|
|
2854
|
-
return haircut(amount, protocolFeeBps);
|
|
2855
|
-
}
|
|
2856
|
-
function weightedMedian(entries) {
|
|
2857
|
-
const sorted = [...entries].sort((a, b) => a.price < b.price ? -1 : a.price > b.price ? 1 : 0);
|
|
2858
|
-
const totalWeight = sorted.reduce((acc, e) => e.weight > 0n ? acc + e.weight : acc, 0n);
|
|
2859
|
-
if (totalWeight === 0n) {
|
|
2860
|
-
return sorted[Math.floor(sorted.length / 2)].price;
|
|
2861
|
-
}
|
|
2862
|
-
let cumulative = 0n;
|
|
2863
|
-
for (const entry of sorted) {
|
|
2864
|
-
if (entry.weight <= 0n) continue;
|
|
2865
|
-
cumulative += entry.weight;
|
|
2866
|
-
if (cumulative * 2n >= totalWeight) return entry.price;
|
|
2867
|
-
}
|
|
2868
|
-
return sorted[sorted.length - 1].price;
|
|
2869
|
-
}
|
|
2870
|
-
function extractFillData(callData, gatewayAddress) {
|
|
2871
|
-
const calls = decodeERC7821ExecuteBatch(callData);
|
|
2872
|
-
if (!calls) return null;
|
|
2873
|
-
const normalized = gatewayAddress.toLowerCase();
|
|
2874
|
-
for (const call of calls) {
|
|
2875
|
-
if (call.target.toLowerCase() !== normalized) continue;
|
|
2876
|
-
try {
|
|
2877
|
-
const decoded = decodeFillOrder(call.data);
|
|
2878
|
-
if (!decoded) continue;
|
|
2879
|
-
const order = decoded.order;
|
|
2880
|
-
const options = decoded.options;
|
|
2881
|
-
const assets = order?.output?.assets;
|
|
2882
|
-
const outputs = options?.outputs;
|
|
2883
|
-
if (!assets?.length || !outputs?.length) continue;
|
|
2884
|
-
return { order, options, legs: zipFillLegs(assets, outputs) };
|
|
2885
|
-
} catch {
|
|
2886
|
-
continue;
|
|
2887
|
-
}
|
|
2888
|
-
}
|
|
2889
|
-
return null;
|
|
2533
|
+
function bytesToBigInt2(bytes) {
|
|
2534
|
+
let value = 0n;
|
|
2535
|
+
for (const byte of bytes) value = value << 8n | BigInt(byte);
|
|
2536
|
+
return value;
|
|
2890
2537
|
}
|
|
2891
|
-
|
|
2892
|
-
(
|
|
2893
|
-
)?.inputs?.[0];
|
|
2894
|
-
function orderCommitmentFromDecoded(order) {
|
|
2895
|
-
try {
|
|
2896
|
-
if (!FILL_ORDER_INPUT) return null;
|
|
2897
|
-
return keccak256(encodeAbiParameters([FILL_ORDER_INPUT], [order]));
|
|
2898
|
-
} catch {
|
|
2899
|
-
return null;
|
|
2900
|
-
}
|
|
2538
|
+
function bytesToAddress(bytes) {
|
|
2539
|
+
return u8aToHex(bytes);
|
|
2901
2540
|
}
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
function splitBidSignature(signature) {
|
|
2905
|
-
const raw = signature.replace(/^0x/, "");
|
|
2906
|
-
const commitmentChars = BID_COMMITMENT_BYTES * 2;
|
|
2907
|
-
const end = commitmentChars + SOLVER_SIGNATURE_BYTES * 2;
|
|
2908
|
-
if (raw.length < end) return null;
|
|
2909
|
-
return {
|
|
2910
|
-
commitment: `0x${raw.slice(0, commitmentChars)}`,
|
|
2911
|
-
solverSignature: `0x${raw.slice(commitmentChars, end)}`
|
|
2912
|
-
};
|
|
2541
|
+
function hasPermit2Sponsorship(bytes) {
|
|
2542
|
+
return bytes.length >= PERMIT2_SPONSORSHIP_BYTES && bytes[PAYMASTER_DATA_OFFSET] === SIMPLEX_MODE_PERMIT2;
|
|
2913
2543
|
}
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
return
|
|
2920
|
-
}
|
|
2921
|
-
};
|
|
2922
|
-
var DELEGATION_INDICATOR_PREFIX = "0xef0100";
|
|
2923
|
-
async function isDelegatedToSolverAccount(evmRpcUrl, account, solverAccounts) {
|
|
2924
|
-
const response = await rpcCall(evmRpcUrl, {
|
|
2925
|
-
id: 1,
|
|
2926
|
-
jsonrpc: "2.0",
|
|
2927
|
-
method: "eth_getCode",
|
|
2928
|
-
params: [account, "latest"]
|
|
2929
|
-
});
|
|
2930
|
-
if (typeof response.result !== "string") {
|
|
2931
|
-
throw new PhantomRpcError(`eth_getCode returned no code for ${account} on ${evmRpcUrl}`);
|
|
2932
|
-
}
|
|
2933
|
-
const code = response.result.toLowerCase();
|
|
2934
|
-
if (!code.startsWith(DELEGATION_INDICATOR_PREFIX)) return false;
|
|
2935
|
-
const delegate = `0x${code.slice(DELEGATION_INDICATOR_PREFIX.length)}`;
|
|
2936
|
-
return solverAccounts.some((solverAccount) => solverAccount.toLowerCase() === delegate);
|
|
2937
|
-
}
|
|
2938
|
-
function memoizedDelegationCheck() {
|
|
2939
|
-
const cache = /* @__PURE__ */ new Map();
|
|
2940
|
-
return (evmRpcUrl, account, solverAccounts) => {
|
|
2941
|
-
const targets = solverAccounts.map((a) => a.toLowerCase()).sort().join(",");
|
|
2942
|
-
const key = `${evmRpcUrl}|${account.toLowerCase()}|${targets}`;
|
|
2943
|
-
let pending = cache.get(key);
|
|
2944
|
-
if (!pending) {
|
|
2945
|
-
pending = isDelegatedToSolverAccount(evmRpcUrl, account, solverAccounts).catch((err) => {
|
|
2946
|
-
cache.delete(key);
|
|
2947
|
-
throw err;
|
|
2948
|
-
});
|
|
2949
|
-
cache.set(key, pending);
|
|
2950
|
-
}
|
|
2951
|
-
return pending;
|
|
2544
|
+
function parseSponsorship(bytes) {
|
|
2545
|
+
let offset = 0;
|
|
2546
|
+
const take = (length) => {
|
|
2547
|
+
const slice = bytes.subarray(offset, offset + length);
|
|
2548
|
+
offset += length;
|
|
2549
|
+
return slice;
|
|
2952
2550
|
};
|
|
2551
|
+
const paymaster = bytesToAddress(take(PAYMASTER_ADDRESS_BYTES));
|
|
2552
|
+
take(2 * PAYMASTER_GAS_LIMIT_BYTES);
|
|
2553
|
+
take(1);
|
|
2554
|
+
const token = bytesToAddress(take(20));
|
|
2555
|
+
const permitAmount = bytesToBigInt2(take(32));
|
|
2556
|
+
const nonce = bytesToBigInt2(take(32));
|
|
2557
|
+
const deadline = bytesToBigInt2(take(32));
|
|
2558
|
+
return { paymaster, token, permitAmount, nonce, deadline };
|
|
2953
2559
|
}
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
solverAccounts,
|
|
2966
|
-
evmRpcUrl,
|
|
2967
|
-
recoverSigner,
|
|
2968
|
-
bidNonceKey,
|
|
2969
|
-
isDelegated,
|
|
2970
|
-
logger
|
|
2971
|
-
} = params;
|
|
2972
|
-
const solver = userOp.sender;
|
|
2973
|
-
const parsed = splitBidSignature(userOp.signature);
|
|
2974
|
-
if (!parsed) {
|
|
2975
|
-
logger?.warn({ solver, commitment }, "Rejecting phantom bid: malformed userOp signature");
|
|
2976
|
-
return false;
|
|
2977
|
-
}
|
|
2978
|
-
if (parsed.commitment.toLowerCase() !== commitment.toLowerCase()) {
|
|
2979
|
-
logger?.warn(
|
|
2980
|
-
{ solver, commitment, signedFor: parsed.commitment },
|
|
2981
|
-
"Rejecting phantom bid: signed for another order"
|
|
2982
|
-
);
|
|
2983
|
-
return false;
|
|
2984
|
-
}
|
|
2985
|
-
if (BigInt(userOp.nonce) >> 64n !== bidNonceKey(commitment, sessionKey)) {
|
|
2986
|
-
logger?.warn({ solver, commitment }, "Rejecting phantom bid: nonce does not bind order and session key");
|
|
2987
|
-
return false;
|
|
2988
|
-
}
|
|
2989
|
-
const signer = await recoverSigner(userOp, ENTRY_POINT_V08_ADDRESS, chainId, parsed.solverSignature);
|
|
2990
|
-
if (!signer || signer.toLowerCase() !== solver.toLowerCase()) {
|
|
2991
|
-
logger?.warn({ solver, commitment, signer }, "Rejecting phantom bid: signature does not recover to the sender");
|
|
2992
|
-
return false;
|
|
2993
|
-
}
|
|
2994
|
-
if (!await isDelegated(evmRpcUrl, solver, solverAccounts)) {
|
|
2995
|
-
logger?.warn({ solver, commitment, solverAccounts }, "Rejecting phantom bid: sender is not a delegated solver");
|
|
2996
|
-
return false;
|
|
2997
|
-
}
|
|
2998
|
-
return true;
|
|
2999
|
-
}
|
|
3000
|
-
async function fetchBidsForOrder(nodeUrl, commitment) {
|
|
3001
|
-
const data = await rpcCall(nodeUrl, {
|
|
3002
|
-
id: 1,
|
|
3003
|
-
jsonrpc: "2.0",
|
|
3004
|
-
method: "intents_getBidsForOrder",
|
|
3005
|
-
params: [commitment]
|
|
3006
|
-
});
|
|
3007
|
-
return Array.isArray(data.result) ? data.result : [];
|
|
3008
|
-
}
|
|
3009
|
-
async function ethCallUint(evmRpcUrl, to, data, blockTag = "latest") {
|
|
3010
|
-
const result = await rpcCall(evmRpcUrl, {
|
|
3011
|
-
id: 1,
|
|
3012
|
-
jsonrpc: "2.0",
|
|
3013
|
-
method: "eth_call",
|
|
3014
|
-
params: [{ to, data }, blockTag]
|
|
3015
|
-
});
|
|
3016
|
-
if (result.result === "0x") return 0n;
|
|
3017
|
-
if (typeof result.result !== "string") {
|
|
3018
|
-
throw new PhantomRpcError(`eth_call returned no result for ${to} on ${evmRpcUrl}`);
|
|
3019
|
-
}
|
|
3020
|
-
return BigInt(result.result);
|
|
2560
|
+
var absentDeclaration = () => ({ acceptedSources: null, uniswapV4Positions: [] });
|
|
2561
|
+
function decodePhantomBidPaymasterAndData(paymasterAndData) {
|
|
2562
|
+
const none = { mode: "none", declaration: absentDeclaration(), sponsorship: null };
|
|
2563
|
+
if (!paymasterAndData || !isHex(paymasterAndData)) return none;
|
|
2564
|
+
const bytes = hexToU8a(paymasterAndData);
|
|
2565
|
+
const bare = parseDeclaration(bytes, 0);
|
|
2566
|
+
if (bare) return { mode: "declaration", declaration: bare, sponsorship: null };
|
|
2567
|
+
if (!hasPermit2Sponsorship(bytes)) return none;
|
|
2568
|
+
const sponsorship = parseSponsorship(bytes);
|
|
2569
|
+
const tail = bytes.length > PERMIT2_SPONSORSHIP_BYTES ? parseDeclaration(bytes, PERMIT2_SPONSORSHIP_BYTES) : null;
|
|
2570
|
+
return { mode: "permit2", declaration: tail ?? absentDeclaration(), sponsorship };
|
|
3021
2571
|
}
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
const raw = await ethCallUint(evmRpcUrl, token, `0x70a08231${padded}`, blockTag);
|
|
3025
|
-
const vaults = yieldVaults[chain]?.[token.toLowerCase()] ?? [];
|
|
3026
|
-
const vaultBalances = await Promise.all(
|
|
3027
|
-
vaults.map((v) => ethCallUint(evmRpcUrl, v, `0xce96cb77${padded}`, blockTag))
|
|
3028
|
-
// maxWithdraw(address)
|
|
3029
|
-
);
|
|
3030
|
-
return vaultBalances.reduce((acc, b) => acc + b, raw);
|
|
2572
|
+
function decodePhantomBidDeclaration(paymasterAndData) {
|
|
2573
|
+
return decodePhantomBidPaymasterAndData(paymasterAndData).declaration;
|
|
3031
2574
|
}
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
id: 1,
|
|
3042
|
-
jsonrpc: "2.0",
|
|
3043
|
-
method: "eth_call",
|
|
3044
|
-
params: [{ to, data }, blockTag]
|
|
3045
|
-
});
|
|
3046
|
-
if (result.result === "0x") return null;
|
|
3047
|
-
if (typeof result.result !== "string") {
|
|
3048
|
-
throw new PhantomRpcError(`eth_call returned no result for ${to} on ${evmRpcUrl}`);
|
|
3049
|
-
}
|
|
3050
|
-
return result.result;
|
|
3051
|
-
};
|
|
3052
|
-
const arg = uint256Arg(tokenId);
|
|
3053
|
-
const [ownerData, infoData, liquidityData] = await Promise.all([
|
|
3054
|
-
call(contracts.positionManager, `${SELECTOR_OWNER_OF}${arg}`),
|
|
3055
|
-
call(contracts.positionManager, `${SELECTOR_POOL_AND_POSITION_INFO}${arg}`),
|
|
3056
|
-
call(contracts.positionManager, `${SELECTOR_POSITION_LIQUIDITY}${arg}`)
|
|
3057
|
-
]);
|
|
3058
|
-
if (!ownerData) return null;
|
|
3059
|
-
if (!infoData || !liquidityData) {
|
|
3060
|
-
logger?.warn(
|
|
3061
|
-
{ tokenId: tokenId.toString(), positionManager: contracts.positionManager },
|
|
3062
|
-
"Uniswap V4 position exists but its pool info or liquidity did not read back \u2014 check the configured PositionManager"
|
|
3063
|
-
);
|
|
3064
|
-
return null;
|
|
3065
|
-
}
|
|
3066
|
-
const info = decodePoolAndPositionInfo(infoData);
|
|
3067
|
-
const slot0Data = await call(contracts.stateView, `${SELECTOR_GET_SLOT0}${keccak(info.poolKeyEncoded).slice(2)}`);
|
|
3068
|
-
if (!slot0Data) {
|
|
3069
|
-
logger?.warn(
|
|
3070
|
-
{ tokenId: tokenId.toString(), stateView: contracts.stateView, evmRpcUrl },
|
|
3071
|
-
"Uniswap V4 slot0 read returned nothing for a live position \u2014 the configured StateView address is wrong"
|
|
2575
|
+
function encodePhantomBidPaymasterAndData(bid) {
|
|
2576
|
+
const declaration = encodePhantomBidDeclaration(bid);
|
|
2577
|
+
const sponsorship = bid.sponsorship;
|
|
2578
|
+
if (!sponsorship || sponsorship === "0x") return declaration;
|
|
2579
|
+
if (!isHex(sponsorship)) throw new Error("Phantom bid sponsorship is not hex");
|
|
2580
|
+
const bytes = hexToU8a(sponsorship);
|
|
2581
|
+
if (bytes.length !== PERMIT2_SPONSORSHIP_BYTES || !hasPermit2Sponsorship(bytes)) {
|
|
2582
|
+
throw new Error(
|
|
2583
|
+
`Phantom bid sponsorship must be a ${PERMIT2_SPONSORSHIP_BYTES}-byte Permit2-mode paymasterAndData, got ${bytes.length} bytes`
|
|
3072
2584
|
);
|
|
3073
|
-
return null;
|
|
3074
2585
|
}
|
|
3075
|
-
return {
|
|
3076
|
-
owner: `0x${ownerData.slice(-40)}`.toLowerCase(),
|
|
3077
|
-
info,
|
|
3078
|
-
liquidity: word(liquidityData, 0),
|
|
3079
|
-
sqrtPriceX96: word(slot0Data, 0)
|
|
3080
|
-
};
|
|
3081
|
-
}
|
|
3082
|
-
function memoizedV4Position(keccak, logger) {
|
|
3083
|
-
const cache = /* @__PURE__ */ new Map();
|
|
3084
|
-
return (evmRpcUrl, chain, contracts, tokenId) => {
|
|
3085
|
-
const key = `${chain}|${tokenId}`;
|
|
3086
|
-
let pending = cache.get(key);
|
|
3087
|
-
if (!pending) {
|
|
3088
|
-
pending = readV4Position({ evmRpcUrl, contracts, tokenId, keccak, logger }).catch((err) => {
|
|
3089
|
-
cache.delete(key);
|
|
3090
|
-
throw err;
|
|
3091
|
-
});
|
|
3092
|
-
cache.set(key, pending);
|
|
3093
|
-
}
|
|
3094
|
-
return pending;
|
|
3095
|
-
};
|
|
3096
|
-
}
|
|
3097
|
-
function memoizedSolverBalance(yieldVaults, blockTags = {}) {
|
|
3098
|
-
const cache = /* @__PURE__ */ new Map();
|
|
3099
|
-
return (evmRpcUrl, chain, token, solver) => {
|
|
3100
|
-
const key = `${chain}|${token.toLowerCase()}|${solver.toLowerCase()}`;
|
|
3101
|
-
let pending = cache.get(key);
|
|
3102
|
-
if (!pending) {
|
|
3103
|
-
pending = getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVaults, blockTags[chain]).catch((err) => {
|
|
3104
|
-
cache.delete(key);
|
|
3105
|
-
throw err;
|
|
3106
|
-
});
|
|
3107
|
-
cache.set(key, pending);
|
|
3108
|
-
}
|
|
3109
|
-
return pending;
|
|
3110
|
-
};
|
|
2586
|
+
return `${sponsorship}${declaration.slice(2)}`;
|
|
3111
2587
|
}
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
for (const [chain, tokens] of Object.entries(yieldVaults)) {
|
|
3115
|
-
const url = evmRpcUrls[chain];
|
|
3116
|
-
if (!url) continue;
|
|
3117
|
-
for (const token of Object.keys(tokens)) {
|
|
3118
|
-
const balance = await getBalance(url, chain, token, solver);
|
|
3119
|
-
const uniswapV4Balance = chain === positions.chain ? positions.states.reduce(
|
|
3120
|
-
(total2, state) => total2 + positionAmountOfToken({
|
|
3121
|
-
info: state.info,
|
|
3122
|
-
liquidity: state.liquidity,
|
|
3123
|
-
sqrtPriceX96: state.sqrtPriceX96,
|
|
3124
|
-
outputToken: token
|
|
3125
|
-
}),
|
|
3126
|
-
0n
|
|
3127
|
-
) : 0n;
|
|
3128
|
-
const total = balance + uniswapV4Balance;
|
|
3129
|
-
if (total === 0n) continue;
|
|
3130
|
-
balances.push({ solver, chain, tokenAddress: token, balance: total });
|
|
3131
|
-
}
|
|
3132
|
-
}
|
|
3133
|
-
return balances;
|
|
3134
|
-
}
|
|
3135
|
-
function toAddress(token) {
|
|
3136
|
-
const hex = token.toLowerCase().replace(/^0x/, "");
|
|
3137
|
-
const addr = hex.length > 40 ? hex.slice(-40) : hex.padStart(40, "0");
|
|
3138
|
-
return `0x${addr}`;
|
|
3139
|
-
}
|
|
3140
|
-
async function aggregatePhantomBids(params) {
|
|
3141
|
-
const isDelegated = memoizedDelegationCheck();
|
|
3142
|
-
let lastErr;
|
|
3143
|
-
for (let attempt = 1; attempt <= AGGREGATION_ATTEMPTS; attempt++) {
|
|
3144
|
-
try {
|
|
3145
|
-
return await runAggregation(params, isDelegated);
|
|
3146
|
-
} catch (err) {
|
|
3147
|
-
lastErr = err;
|
|
3148
|
-
params.logger?.warn(
|
|
3149
|
-
{ err, commitment: params.commitment, chain: params.chain, attempt, of: AGGREGATION_ATTEMPTS },
|
|
3150
|
-
"Phantom aggregation attempt failed"
|
|
3151
|
-
);
|
|
3152
|
-
if (attempt < AGGREGATION_ATTEMPTS) await new Promise((resolve) => setTimeout(resolve, 250 * attempt));
|
|
3153
|
-
}
|
|
3154
|
-
}
|
|
3155
|
-
throw lastErr;
|
|
2588
|
+
function encodeAcceptedSourceChains(chains) {
|
|
2589
|
+
return encodePhantomBidDeclaration({ acceptedSourceChains: chains });
|
|
3156
2590
|
}
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
const { nodeUrl, evmRpcUrls, chain, gatewayAddress, commitment, yieldVaults, logger } = params;
|
|
3160
|
-
const solverAccounts = (Array.isArray(params.solverAccount) ? params.solverAccount : [params.solverAccount]).filter(
|
|
3161
|
-
(a) => typeof a === "string" && a.length > 0
|
|
3162
|
-
);
|
|
3163
|
-
const extractFill = params.extractFill ?? extractFillData;
|
|
3164
|
-
const recoverSigner = params.recoverSigner ?? recoverBidSignerViem;
|
|
3165
|
-
const bidNonceKey = params.bidNonceKey ?? CryptoUtils.bidNonceKey;
|
|
3166
|
-
const orderCommitment = params.orderCommitment ?? orderCommitmentFromDecoded;
|
|
3167
|
-
const destUrl = evmRpcUrls[chain];
|
|
3168
|
-
if (!destUrl) return null;
|
|
3169
|
-
const chainId = evmChainId(chain);
|
|
3170
|
-
if (solverAccounts.length === 0 || chainId === null) {
|
|
3171
|
-
logger?.warn({ chain, commitment }, "Cannot verify phantom bids: no SolverAccount or chain id for chain");
|
|
3172
|
-
return null;
|
|
3173
|
-
}
|
|
3174
|
-
const bids = await fetchBidsForOrder(nodeUrl, commitment);
|
|
3175
|
-
if (bids.length === 0) return null;
|
|
3176
|
-
const protocolFeeHaircutBps = await readProtocolFeeHaircutBps(destUrl, gatewayAddress);
|
|
3177
|
-
const v4Contracts = params.uniswapV4?.[chain];
|
|
3178
|
-
const readPosition = memoizedV4Position(params.keccak ?? keccak256, logger);
|
|
3179
|
-
const getBalance = params.getBalance ?? memoizedSolverBalance(yieldVaults);
|
|
3180
|
-
const quotesByLeg = /* @__PURE__ */ new Map();
|
|
3181
|
-
const lpBalances = [];
|
|
3182
|
-
const verifiedPositions = [];
|
|
3183
|
-
const countedSolvers = /* @__PURE__ */ new Set();
|
|
3184
|
-
for (const bid of bids) {
|
|
3185
|
-
if (!bid.user_op) continue;
|
|
3186
|
-
try {
|
|
3187
|
-
const decoded = decodeUserOpScale(bid.user_op);
|
|
3188
|
-
const solver = decoded.sender;
|
|
3189
|
-
const fillData = extractFill(decoded.callData, gatewayAddress);
|
|
3190
|
-
if (!fillData) continue;
|
|
3191
|
-
const decodedCommitment = orderCommitment(fillData.order);
|
|
3192
|
-
if (!decodedCommitment || decodedCommitment.toLowerCase() !== commitment.toLowerCase()) {
|
|
3193
|
-
logger?.warn({ solver, commitment }, "Rejecting phantom bid: calldata order is not the indexed order");
|
|
3194
|
-
continue;
|
|
3195
|
-
}
|
|
3196
|
-
const sessionKey = fillData.order?.session;
|
|
3197
|
-
if (!sessionKey) {
|
|
3198
|
-
logger?.warn({ solver, commitment }, "Rejecting phantom bid: order carries no session key");
|
|
3199
|
-
continue;
|
|
3200
|
-
}
|
|
3201
|
-
const verified = await isVerifiedSolverBid({
|
|
3202
|
-
userOp: decoded,
|
|
3203
|
-
commitment,
|
|
3204
|
-
sessionKey,
|
|
3205
|
-
chainId,
|
|
3206
|
-
solverAccounts,
|
|
3207
|
-
evmRpcUrl: destUrl,
|
|
3208
|
-
recoverSigner,
|
|
3209
|
-
bidNonceKey,
|
|
3210
|
-
isDelegated,
|
|
3211
|
-
logger
|
|
3212
|
-
});
|
|
3213
|
-
if (!verified) continue;
|
|
3214
|
-
const normalizedSolver = solver.toLowerCase();
|
|
3215
|
-
if (countedSolvers.has(normalizedSolver)) {
|
|
3216
|
-
logger?.warn({ solver, commitment }, "Skipping phantom bid: solver already counted for this order");
|
|
3217
|
-
continue;
|
|
3218
|
-
}
|
|
3219
|
-
countedSolvers.add(normalizedSolver);
|
|
3220
|
-
const declaration = decodePhantomBidDeclaration(decoded.paymasterAndData);
|
|
3221
|
-
const acceptedSources = declaration.acceptedSources;
|
|
3222
|
-
const poolPriced = declaration.uniswapV4Positions.length > 0;
|
|
3223
|
-
const applyHaircut = (amount) => poolPriced ? applyUniswapQuoteHaircut(amount) : applyProtocolFeeHaircut(amount, protocolFeeHaircutBps);
|
|
3224
|
-
const quotedLegs = [...fillData.legs.entries()].map(([legIndex, leg]) => [
|
|
3225
|
-
legIndex,
|
|
3226
|
-
{ ...leg, solverAmount: applyHaircut(leg.solverAmount) }
|
|
3227
|
-
]).filter(([, leg]) => leg.solverAmount !== 0n);
|
|
3228
|
-
const declaredPositions = v4Contracts ? declaration.uniswapV4Positions : [];
|
|
3229
|
-
const ownedPositions = (await Promise.all(
|
|
3230
|
-
declaredPositions.map(async (tokenId) => ({
|
|
3231
|
-
tokenId,
|
|
3232
|
-
state: await readPosition(destUrl, chain, v4Contracts, tokenId)
|
|
3233
|
-
}))
|
|
3234
|
-
)).filter((entry) => {
|
|
3235
|
-
if (!entry.state) return false;
|
|
3236
|
-
if (entry.state.owner !== normalizedSolver) {
|
|
3237
|
-
logger?.warn(
|
|
3238
|
-
{ solver, commitment, tokenId: entry.tokenId.toString(), owner: entry.state.owner },
|
|
3239
|
-
"Ignoring declared Uniswap V4 position: not owned by the bidding solver"
|
|
3240
|
-
);
|
|
3241
|
-
return false;
|
|
3242
|
-
}
|
|
3243
|
-
return true;
|
|
3244
|
-
});
|
|
3245
|
-
const positions = ownedPositions.map((entry) => entry.state);
|
|
3246
|
-
for (const entry of ownedPositions) {
|
|
3247
|
-
verifiedPositions.push({ solver: normalizedSolver, chain, tokenId: entry.tokenId });
|
|
3248
|
-
}
|
|
3249
|
-
const weights = await Promise.all(
|
|
3250
|
-
// Price influence: the solver's liquidity in THIS leg's output token on the destination
|
|
3251
|
-
// chain, so a leg is weighted by the inventory that actually backs it.
|
|
3252
|
-
quotedLegs.map(async ([, leg]) => {
|
|
3253
|
-
const outputToken = toAddress(leg.outputToken);
|
|
3254
|
-
const balance = await getBalance(destUrl, chain, outputToken, solver);
|
|
3255
|
-
return positions.reduce(
|
|
3256
|
-
(total, state) => total + positionAmountOfToken({
|
|
3257
|
-
info: state.info,
|
|
3258
|
-
liquidity: state.liquidity,
|
|
3259
|
-
sqrtPriceX96: state.sqrtPriceX96,
|
|
3260
|
-
outputToken
|
|
3261
|
-
}),
|
|
3262
|
-
balance
|
|
3263
|
-
);
|
|
3264
|
-
})
|
|
3265
|
-
);
|
|
3266
|
-
for (const [position, [legIndex, leg]] of quotedLegs.entries()) {
|
|
3267
|
-
const weight = weights[position];
|
|
3268
|
-
const entry = quotesByLeg.get(legIndex) ?? { outputToken: leg.outputToken, quotes: [], bidders: [] };
|
|
3269
|
-
entry.quotes.push({ price: leg.solverAmount, weight });
|
|
3270
|
-
entry.bidders.push({ solver: normalizedSolver, weight, acceptedSources });
|
|
3271
|
-
quotesByLeg.set(legIndex, entry);
|
|
3272
|
-
}
|
|
3273
|
-
lpBalances.push(
|
|
3274
|
-
...await sweepSolverLiquidity(evmRpcUrls, yieldVaults, solver, getBalance, {
|
|
3275
|
-
chain,
|
|
3276
|
-
states: positions
|
|
3277
|
-
})
|
|
3278
|
-
);
|
|
3279
|
-
} catch (err) {
|
|
3280
|
-
if (err instanceof PhantomRpcError) throw err;
|
|
3281
|
-
logger?.warn({ err, filler: bid.filler }, "Failed to process bid for price snapshot");
|
|
3282
|
-
}
|
|
3283
|
-
}
|
|
3284
|
-
if (quotesByLeg.size === 0) return null;
|
|
3285
|
-
const legs = [...quotesByLeg.entries()].sort(([a], [b]) => a - b).flatMap(([legIndex, { outputToken, quotes, bidders }]) => {
|
|
3286
|
-
const backedQuotes = quotes.filter((quote) => quote.weight > 0n);
|
|
3287
|
-
const backedBidders = bidders.filter((bidder) => bidder.weight > 0n);
|
|
3288
|
-
if (backedQuotes.length === 0) {
|
|
3289
|
-
logger?.warn(
|
|
3290
|
-
{ commitment, chain, legIndex, outputToken, quotes: quotes.length },
|
|
3291
|
-
"Dropping phantom leg: no bidder holds the output token on this chain, so no quote is backed"
|
|
3292
|
-
);
|
|
3293
|
-
return [];
|
|
3294
|
-
}
|
|
3295
|
-
const medianPrice = weightedMedian(backedQuotes);
|
|
3296
|
-
return [
|
|
3297
|
-
{
|
|
3298
|
-
legIndex,
|
|
3299
|
-
outputToken,
|
|
3300
|
-
lowestPrice: medianPrice,
|
|
3301
|
-
highestPrice: medianPrice,
|
|
3302
|
-
medianPrice,
|
|
3303
|
-
bidCount: backedQuotes.length,
|
|
3304
|
-
bidders: backedBidders
|
|
3305
|
-
}
|
|
3306
|
-
];
|
|
3307
|
-
});
|
|
3308
|
-
return { legs, lpBalances, positions: verifiedPositions, solvers: [...countedSolvers] };
|
|
2591
|
+
function decodeAcceptedSourceChains(paymasterAndData) {
|
|
2592
|
+
return decodePhantomBidDeclaration(paymasterAndData).acceptedSources;
|
|
3309
2593
|
}
|
|
3310
2594
|
|
|
3311
|
-
export {
|
|
2595
|
+
export { IntentGatewayV2_default as IntentGatewayV2, MAX_DECLARED_ENTRIES, PERMIT2_SPONSORSHIP_BYTES, decodeAcceptedSourceChains, decodeERC7821ExecuteBatch, decodePhantomBidDeclaration, decodePhantomBidPaymasterAndData, decodeUserOpScale, encodeAcceptedSourceChains, encodeERC7821ExecuteBatch, encodePhantomBidDeclaration, encodePhantomBidPaymasterAndData, encodeUserOpScale, fetchBidsForOrder, poolSlug, setAggregationFetch, sortPoolSymbols };
|
|
3312
2596
|
//# sourceMappingURL=intents-helpers.js.map
|
|
3313
2597
|
//# sourceMappingURL=intents-helpers.js.map
|