@hyperbridge/simplex 0.16.12 → 0.17.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/bin/simplex.js +1728 -409
- package/dist/bin/simplex.js.map +1 -1
- package/dist/index.cjs +1086 -145
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +224 -23
- package/dist/index.d.ts +224 -23
- package/dist/index.js +1080 -134
- package/dist/index.js.map +1 -1
- package/dist/sqlite.cjs +67 -4
- package/dist/sqlite.cjs.map +1 -1
- package/dist/sqlite.d.cts +21 -2
- package/dist/sqlite.d.ts +21 -2
- package/dist/sqlite.js +66 -4
- package/dist/sqlite.js.map +1 -1
- package/dist/{types-B5zkFhxR.d.cts → types-BPyUX8qu.d.cts} +64 -1
- package/dist/{types-B5zkFhxR.d.ts → types-BPyUX8qu.d.ts} +64 -1
- package/dist/ui/assets/Novatica-Medium-CjNgGPEL.ttf +0 -0
- package/dist/ui/assets/index-CK8E6aPx.css +1 -0
- package/dist/ui/assets/index-D8DLeEH0.js +106 -0
- package/dist/ui/index.html +2 -2
- package/package.json +5 -5
- package/dist/ui/assets/index-QU1Ik7IX.js +0 -106
- package/dist/ui/assets/index-XKHMOpY2.css +0 -1
package/dist/bin/simplex.js
CHANGED
|
@@ -29007,17 +29007,17 @@ function cosh(x4) {
|
|
|
29007
29007
|
}
|
|
29008
29008
|
function clone(obj) {
|
|
29009
29009
|
var i6, p3, ps;
|
|
29010
|
-
function
|
|
29010
|
+
function Decimal3(v7) {
|
|
29011
29011
|
var e4, i7, t6, x4 = this;
|
|
29012
|
-
if (!(x4 instanceof
|
|
29013
|
-
x4.constructor =
|
|
29012
|
+
if (!(x4 instanceof Decimal3)) return new Decimal3(v7);
|
|
29013
|
+
x4.constructor = Decimal3;
|
|
29014
29014
|
if (isDecimalInstance(v7)) {
|
|
29015
29015
|
x4.s = v7.s;
|
|
29016
29016
|
if (external) {
|
|
29017
|
-
if (!v7.d || v7.e >
|
|
29017
|
+
if (!v7.d || v7.e > Decimal3.maxE) {
|
|
29018
29018
|
x4.e = NaN;
|
|
29019
29019
|
x4.d = null;
|
|
29020
|
-
} else if (v7.e <
|
|
29020
|
+
} else if (v7.e < Decimal3.minE) {
|
|
29021
29021
|
x4.e = 0;
|
|
29022
29022
|
x4.d = [0];
|
|
29023
29023
|
} else {
|
|
@@ -29047,10 +29047,10 @@ function clone(obj) {
|
|
|
29047
29047
|
if (v7 === ~~v7 && v7 < 1e7) {
|
|
29048
29048
|
for (e4 = 0, i7 = v7; i7 >= 10; i7 /= 10) e4++;
|
|
29049
29049
|
if (external) {
|
|
29050
|
-
if (e4 >
|
|
29050
|
+
if (e4 > Decimal3.maxE) {
|
|
29051
29051
|
x4.e = NaN;
|
|
29052
29052
|
x4.d = null;
|
|
29053
|
-
} else if (e4 <
|
|
29053
|
+
} else if (e4 < Decimal3.minE) {
|
|
29054
29054
|
x4.e = 0;
|
|
29055
29055
|
x4.d = [0];
|
|
29056
29056
|
} else {
|
|
@@ -29092,58 +29092,58 @@ function clone(obj) {
|
|
|
29092
29092
|
}
|
|
29093
29093
|
throw Error(invalidArgument + v7);
|
|
29094
29094
|
}
|
|
29095
|
-
|
|
29096
|
-
|
|
29097
|
-
|
|
29098
|
-
|
|
29099
|
-
|
|
29100
|
-
|
|
29101
|
-
|
|
29102
|
-
|
|
29103
|
-
|
|
29104
|
-
|
|
29105
|
-
|
|
29106
|
-
|
|
29107
|
-
|
|
29108
|
-
|
|
29109
|
-
|
|
29110
|
-
|
|
29111
|
-
|
|
29112
|
-
|
|
29113
|
-
|
|
29114
|
-
|
|
29115
|
-
|
|
29116
|
-
|
|
29117
|
-
|
|
29118
|
-
|
|
29119
|
-
|
|
29120
|
-
|
|
29121
|
-
|
|
29122
|
-
|
|
29123
|
-
|
|
29124
|
-
|
|
29125
|
-
|
|
29126
|
-
|
|
29127
|
-
|
|
29128
|
-
|
|
29129
|
-
|
|
29130
|
-
|
|
29131
|
-
|
|
29132
|
-
|
|
29133
|
-
|
|
29134
|
-
|
|
29135
|
-
|
|
29136
|
-
|
|
29137
|
-
|
|
29138
|
-
|
|
29139
|
-
|
|
29140
|
-
|
|
29141
|
-
|
|
29142
|
-
|
|
29143
|
-
|
|
29144
|
-
|
|
29145
|
-
|
|
29146
|
-
|
|
29095
|
+
Decimal3.prototype = P;
|
|
29096
|
+
Decimal3.ROUND_UP = 0;
|
|
29097
|
+
Decimal3.ROUND_DOWN = 1;
|
|
29098
|
+
Decimal3.ROUND_CEIL = 2;
|
|
29099
|
+
Decimal3.ROUND_FLOOR = 3;
|
|
29100
|
+
Decimal3.ROUND_HALF_UP = 4;
|
|
29101
|
+
Decimal3.ROUND_HALF_DOWN = 5;
|
|
29102
|
+
Decimal3.ROUND_HALF_EVEN = 6;
|
|
29103
|
+
Decimal3.ROUND_HALF_CEIL = 7;
|
|
29104
|
+
Decimal3.ROUND_HALF_FLOOR = 8;
|
|
29105
|
+
Decimal3.EUCLID = 9;
|
|
29106
|
+
Decimal3.config = Decimal3.set = config;
|
|
29107
|
+
Decimal3.clone = clone;
|
|
29108
|
+
Decimal3.isDecimal = isDecimalInstance;
|
|
29109
|
+
Decimal3.abs = abs;
|
|
29110
|
+
Decimal3.acos = acos;
|
|
29111
|
+
Decimal3.acosh = acosh;
|
|
29112
|
+
Decimal3.add = add2;
|
|
29113
|
+
Decimal3.asin = asin;
|
|
29114
|
+
Decimal3.asinh = asinh;
|
|
29115
|
+
Decimal3.atan = atan;
|
|
29116
|
+
Decimal3.atanh = atanh;
|
|
29117
|
+
Decimal3.atan2 = atan2;
|
|
29118
|
+
Decimal3.cbrt = cbrt;
|
|
29119
|
+
Decimal3.ceil = ceil;
|
|
29120
|
+
Decimal3.clamp = clamp;
|
|
29121
|
+
Decimal3.cos = cos;
|
|
29122
|
+
Decimal3.cosh = cosh;
|
|
29123
|
+
Decimal3.div = div;
|
|
29124
|
+
Decimal3.exp = exp;
|
|
29125
|
+
Decimal3.floor = floor;
|
|
29126
|
+
Decimal3.hypot = hypot;
|
|
29127
|
+
Decimal3.ln = ln;
|
|
29128
|
+
Decimal3.log = log;
|
|
29129
|
+
Decimal3.log10 = log10;
|
|
29130
|
+
Decimal3.log2 = log2;
|
|
29131
|
+
Decimal3.max = max;
|
|
29132
|
+
Decimal3.min = min;
|
|
29133
|
+
Decimal3.mod = mod3;
|
|
29134
|
+
Decimal3.mul = mul;
|
|
29135
|
+
Decimal3.pow = pow;
|
|
29136
|
+
Decimal3.random = random;
|
|
29137
|
+
Decimal3.round = round;
|
|
29138
|
+
Decimal3.sign = sign;
|
|
29139
|
+
Decimal3.sin = sin;
|
|
29140
|
+
Decimal3.sinh = sinh;
|
|
29141
|
+
Decimal3.sqrt = sqrt;
|
|
29142
|
+
Decimal3.sub = sub;
|
|
29143
|
+
Decimal3.sum = sum;
|
|
29144
|
+
Decimal3.tan = tan;
|
|
29145
|
+
Decimal3.tanh = tanh;
|
|
29146
|
+
Decimal3.trunc = trunc;
|
|
29147
29147
|
if (obj === void 0) obj = {};
|
|
29148
29148
|
if (obj) {
|
|
29149
29149
|
if (obj.defaults !== true) {
|
|
@@ -29151,8 +29151,8 @@ function clone(obj) {
|
|
|
29151
29151
|
for (i6 = 0; i6 < ps.length; ) if (!obj.hasOwnProperty(p3 = ps[i6++])) obj[p3] = this[p3];
|
|
29152
29152
|
}
|
|
29153
29153
|
}
|
|
29154
|
-
|
|
29155
|
-
return
|
|
29154
|
+
Decimal3.config(obj);
|
|
29155
|
+
return Decimal3;
|
|
29156
29156
|
}
|
|
29157
29157
|
function div(x4, y5) {
|
|
29158
29158
|
return new this(x4).div(y5);
|
|
@@ -30656,7 +30656,8 @@ var init_asset_registry = __esm({
|
|
|
30656
30656
|
ZARP: { resolve: (r7, chain2) => r7.getAssetBySymbol(chain2, "ZARP") },
|
|
30657
30657
|
EURC: { resolve: (r7, chain2) => r7.getAssetBySymbol(chain2, "EURC") },
|
|
30658
30658
|
XSGD: { resolve: (r7, chain2) => r7.getAssetBySymbol(chain2, "XSGD") },
|
|
30659
|
-
TRYB: { resolve: (r7, chain2) => r7.getAssetBySymbol(chain2, "TRYB") }
|
|
30659
|
+
TRYB: { resolve: (r7, chain2) => r7.getAssetBySymbol(chain2, "TRYB") },
|
|
30660
|
+
BRIDGE: { resolve: (r7, chain2) => r7.getAssetBySymbol(chain2, "BRIDGE") }
|
|
30660
30661
|
};
|
|
30661
30662
|
USD_STABLE_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USDT", "DAI"]);
|
|
30662
30663
|
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
@@ -30755,7 +30756,7 @@ function assertPairSymbolsResolve(pairs, registry, chainNames) {
|
|
|
30755
30756
|
const pairSymbols = new Set(pairs.flatMap((pair) => [pair.token0, pair.token1]));
|
|
30756
30757
|
for (const pair of pairs) {
|
|
30757
30758
|
for (const symbol3 of [pair.token0, pair.token1]) {
|
|
30758
|
-
const resolvesSomewhere = chainNames.some((
|
|
30759
|
+
const resolvesSomewhere = chainNames.some((chainName2) => registry.getAddress(symbol3, chainName2) !== null);
|
|
30759
30760
|
if (!resolvesSomewhere) {
|
|
30760
30761
|
throw new Error(
|
|
30761
30762
|
`pairs.${pair.token0}/${pair.token1}: '${symbol3}' does not resolve to a deployed contract on any configured chain`
|
|
@@ -30763,15 +30764,15 @@ function assertPairSymbolsResolve(pairs, registry, chainNames) {
|
|
|
30763
30764
|
}
|
|
30764
30765
|
}
|
|
30765
30766
|
}
|
|
30766
|
-
for (const
|
|
30767
|
+
for (const chainName2 of chainNames) {
|
|
30767
30768
|
const addressOwner = /* @__PURE__ */ new Map();
|
|
30768
30769
|
for (const symbol3 of pairSymbols) {
|
|
30769
|
-
const address = registry.getAddress(symbol3,
|
|
30770
|
+
const address = registry.getAddress(symbol3, chainName2)?.toLowerCase();
|
|
30770
30771
|
if (!address) continue;
|
|
30771
30772
|
const owner = addressOwner.get(address);
|
|
30772
30773
|
if (owner && normalizeSymbol(owner) !== normalizeSymbol(symbol3)) {
|
|
30773
30774
|
throw new Error(
|
|
30774
|
-
`assets: '${symbol3}' and '${owner}' both resolve to ${address} on ${
|
|
30775
|
+
`assets: '${symbol3}' and '${owner}' both resolve to ${address} on ${chainName2} \u2014 symbols must map to distinct contracts`
|
|
30775
30776
|
);
|
|
30776
30777
|
}
|
|
30777
30778
|
addressOwner.set(address, symbol3);
|
|
@@ -48802,11 +48803,11 @@ var init_esm2 = __esm({
|
|
|
48802
48803
|
init_encodeFunctionData2();
|
|
48803
48804
|
init_encodePacked2();
|
|
48804
48805
|
init_parseEventLogs2();
|
|
48805
|
-
init_isAddress2();
|
|
48806
48806
|
init_defineChain2();
|
|
48807
48807
|
init_concat2();
|
|
48808
48808
|
init_isHex2();
|
|
48809
48809
|
init_pad2();
|
|
48810
|
+
init_slice2();
|
|
48810
48811
|
init_fromBytes2();
|
|
48811
48812
|
init_fromHex2();
|
|
48812
48813
|
init_toBytes2();
|
|
@@ -48814,6 +48815,7 @@ var init_esm2 = __esm({
|
|
|
48814
48815
|
init_keccak2562();
|
|
48815
48816
|
init_toEventSelector2();
|
|
48816
48817
|
init_toFunctionSelector2();
|
|
48818
|
+
init_recoverAddress2();
|
|
48817
48819
|
init_formatUnits2();
|
|
48818
48820
|
init_parseUnits2();
|
|
48819
48821
|
}
|
|
@@ -51069,7 +51071,7 @@ var require_bn = __commonJS({
|
|
|
51069
51071
|
}
|
|
51070
51072
|
return this;
|
|
51071
51073
|
};
|
|
51072
|
-
BN3.prototype.add = function
|
|
51074
|
+
BN3.prototype.add = function add4(num2) {
|
|
51073
51075
|
var res;
|
|
51074
51076
|
if (num2.negative !== 0 && this.negative === 0) {
|
|
51075
51077
|
num2.negative = 0;
|
|
@@ -52906,7 +52908,7 @@ var require_bn = __commonJS({
|
|
|
52906
52908
|
}
|
|
52907
52909
|
return this.m.sub(a6)._forceRed(this);
|
|
52908
52910
|
};
|
|
52909
|
-
Red.prototype.add = function
|
|
52911
|
+
Red.prototype.add = function add4(a6, b5) {
|
|
52910
52912
|
this._verify2(a6, b5);
|
|
52911
52913
|
var res = a6.add(b5);
|
|
52912
52914
|
if (res.cmp(this.m) >= 0) {
|
|
@@ -55786,10 +55788,10 @@ var init_fflate = __esm({
|
|
|
55786
55788
|
lm = void 0;
|
|
55787
55789
|
break;
|
|
55788
55790
|
} else {
|
|
55789
|
-
let
|
|
55791
|
+
let add4 = sym - 254;
|
|
55790
55792
|
if (sym > 264) {
|
|
55791
55793
|
const i6 = sym - 257, b5 = fleb[i6];
|
|
55792
|
-
|
|
55794
|
+
add4 = bits(dat, pos, (1 << b5) - 1) + fl[i6];
|
|
55793
55795
|
pos += b5;
|
|
55794
55796
|
}
|
|
55795
55797
|
const d5 = dm[bits16(dat, pos) & dms], dsym = d5 >>> 4;
|
|
@@ -55805,7 +55807,7 @@ var init_fflate = __esm({
|
|
|
55805
55807
|
throw "unexpected EOF";
|
|
55806
55808
|
if (noBuf)
|
|
55807
55809
|
cbuf(bt + 131072);
|
|
55808
|
-
const end = bt +
|
|
55810
|
+
const end = bt + add4;
|
|
55809
55811
|
for (; bt < end; bt += 4) {
|
|
55810
55812
|
buf[bt] = buf[bt - dt];
|
|
55811
55813
|
buf[bt + 1] = buf[bt + 1 - dt];
|
|
@@ -83509,15 +83511,15 @@ var require_fromEvent = __commonJS({
|
|
|
83509
83511
|
return function(handler) {
|
|
83510
83512
|
return target[methodName](eventName, handler, options);
|
|
83511
83513
|
};
|
|
83512
|
-
}) : isNodeStyleEventEmitter(target) ? nodeEventEmitterMethods.map(toCommonHandlerRegistry(target, eventName)) : isJQueryStyleEventEmitter(target) ? jqueryMethods.map(toCommonHandlerRegistry(target, eventName)) : [], 2),
|
|
83513
|
-
if (!
|
|
83514
|
+
}) : isNodeStyleEventEmitter(target) ? nodeEventEmitterMethods.map(toCommonHandlerRegistry(target, eventName)) : isJQueryStyleEventEmitter(target) ? jqueryMethods.map(toCommonHandlerRegistry(target, eventName)) : [], 2), add4 = _a10[0], remove = _a10[1];
|
|
83515
|
+
if (!add4) {
|
|
83514
83516
|
if (isArrayLike_1.isArrayLike(target)) {
|
|
83515
83517
|
return mergeMap_1.mergeMap(function(subTarget) {
|
|
83516
83518
|
return fromEvent(subTarget, eventName, options);
|
|
83517
83519
|
})(innerFrom_1.innerFrom(target));
|
|
83518
83520
|
}
|
|
83519
83521
|
}
|
|
83520
|
-
if (!
|
|
83522
|
+
if (!add4) {
|
|
83521
83523
|
throw new TypeError("Invalid event target");
|
|
83522
83524
|
}
|
|
83523
83525
|
return new Observable_1.Observable(function(subscriber) {
|
|
@@ -83528,7 +83530,7 @@ var require_fromEvent = __commonJS({
|
|
|
83528
83530
|
}
|
|
83529
83531
|
return subscriber.next(1 < args.length ? args : args[0]);
|
|
83530
83532
|
};
|
|
83531
|
-
|
|
83533
|
+
add4(handler);
|
|
83532
83534
|
return function() {
|
|
83533
83535
|
return remove(handler);
|
|
83534
83536
|
};
|
|
@@ -135098,21 +135100,21 @@ var init_upgrades = __esm({
|
|
|
135098
135100
|
});
|
|
135099
135101
|
|
|
135100
135102
|
// ../../node_modules/.pnpm/@polkadot+types-known@16.5.6/node_modules/@polkadot/types-known/util.js
|
|
135101
|
-
function withNames(
|
|
135102
|
-
return fn(
|
|
135103
|
+
function withNames(chainName2, specName, fn) {
|
|
135104
|
+
return fn(chainName2.toString(), specName.toString());
|
|
135103
135105
|
}
|
|
135104
135106
|
function filterVersions(versions = [], specVersion) {
|
|
135105
135107
|
return versions.filter(({ minmax: [min2, max3] }) => (min2 === void 0 || min2 === null || specVersion >= min2) && (max3 === void 0 || max3 === null || specVersion <= max3)).reduce((result, { types: types4 }) => ({ ...result, ...types4 }), {});
|
|
135106
135108
|
}
|
|
135107
|
-
function getSpecExtensions({ knownTypes: knownTypes2 },
|
|
135108
|
-
return withNames(
|
|
135109
|
+
function getSpecExtensions({ knownTypes: knownTypes2 }, chainName2, specName) {
|
|
135110
|
+
return withNames(chainName2, specName, (c6, s4) => ({
|
|
135109
135111
|
...knownTypes2.typesBundle?.spec?.[s4]?.signedExtensions ?? {},
|
|
135110
135112
|
...knownTypes2.typesBundle?.chain?.[c6]?.signedExtensions ?? {}
|
|
135111
135113
|
}));
|
|
135112
135114
|
}
|
|
135113
|
-
function getSpecTypes({ knownTypes: knownTypes2 },
|
|
135115
|
+
function getSpecTypes({ knownTypes: knownTypes2 }, chainName2, specName, specVersion) {
|
|
135114
135116
|
const _specVersion = bnToBn(specVersion).toNumber();
|
|
135115
|
-
return withNames(
|
|
135117
|
+
return withNames(chainName2, specName, (c6, s4) => ({
|
|
135116
135118
|
// The order here is always, based on -
|
|
135117
135119
|
// - spec then chain
|
|
135118
135120
|
// - typesBundle takes higher precedence
|
|
@@ -135126,23 +135128,23 @@ function getSpecTypes({ knownTypes: knownTypes2 }, chainName, specName, specVers
|
|
|
135126
135128
|
...knownTypes2.types ?? {}
|
|
135127
135129
|
}));
|
|
135128
135130
|
}
|
|
135129
|
-
function getSpecHasher({ knownTypes: knownTypes2 },
|
|
135130
|
-
return withNames(
|
|
135131
|
+
function getSpecHasher({ knownTypes: knownTypes2 }, chainName2, specName) {
|
|
135132
|
+
return withNames(chainName2, specName, (c6, s4) => knownTypes2.hasher || knownTypes2.typesBundle?.chain?.[c6]?.hasher || knownTypes2.typesBundle?.spec?.[s4]?.hasher || null);
|
|
135131
135133
|
}
|
|
135132
|
-
function getSpecRpc({ knownTypes: knownTypes2 },
|
|
135133
|
-
return withNames(
|
|
135134
|
+
function getSpecRpc({ knownTypes: knownTypes2 }, chainName2, specName) {
|
|
135135
|
+
return withNames(chainName2, specName, (c6, s4) => ({
|
|
135134
135136
|
...knownTypes2.typesBundle?.spec?.[s4]?.rpc ?? {},
|
|
135135
135137
|
...knownTypes2.typesBundle?.chain?.[c6]?.rpc ?? {}
|
|
135136
135138
|
}));
|
|
135137
135139
|
}
|
|
135138
|
-
function getSpecRuntime({ knownTypes: knownTypes2 },
|
|
135139
|
-
return withNames(
|
|
135140
|
+
function getSpecRuntime({ knownTypes: knownTypes2 }, chainName2, specName) {
|
|
135141
|
+
return withNames(chainName2, specName, (c6, s4) => ({
|
|
135140
135142
|
...knownTypes2.typesBundle?.spec?.[s4]?.runtime ?? {},
|
|
135141
135143
|
...knownTypes2.typesBundle?.chain?.[c6]?.runtime ?? {}
|
|
135142
135144
|
}));
|
|
135143
135145
|
}
|
|
135144
|
-
function getSpecAlias({ knownTypes: knownTypes2 },
|
|
135145
|
-
return withNames(
|
|
135146
|
+
function getSpecAlias({ knownTypes: knownTypes2 }, chainName2, specName) {
|
|
135147
|
+
return withNames(chainName2, specName, (c6, s4) => ({
|
|
135146
135148
|
// as per versions, first spec, then chain then finally non-versioned
|
|
135147
135149
|
...knownTypes2.typesBundle?.spec?.[s4]?.alias ?? {},
|
|
135148
135150
|
...knownTypes2.typesBundle?.chain?.[c6]?.alias ?? {},
|
|
@@ -156390,7 +156392,7 @@ var require_isTime = __commonJS({
|
|
|
156390
156392
|
hourFormat: "hour24",
|
|
156391
156393
|
mode: "default"
|
|
156392
156394
|
};
|
|
156393
|
-
var
|
|
156395
|
+
var formats2 = {
|
|
156394
156396
|
hour24: {
|
|
156395
156397
|
default: /^([01]?[0-9]|2[0-3]):([0-5][0-9])$/,
|
|
156396
156398
|
withSeconds: /^([01]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/,
|
|
@@ -156405,7 +156407,7 @@ var require_isTime = __commonJS({
|
|
|
156405
156407
|
function isTime(input, options) {
|
|
156406
156408
|
options = (0, _merge.default)(options, default_time_options);
|
|
156407
156409
|
if (typeof input !== "string") return false;
|
|
156408
|
-
return
|
|
156410
|
+
return formats2[options.hourFormat][options.mode].test(input);
|
|
156409
156411
|
}
|
|
156410
156412
|
module2.exports = exports2.default;
|
|
156411
156413
|
module2.exports.default = exports2.default;
|
|
@@ -233930,8 +233932,8 @@ function addToExternrefTable0(obj) {
|
|
|
233930
233932
|
function passArrayJsValueToWasm0(array, malloc) {
|
|
233931
233933
|
const ptr = malloc(array.length * 4, 4) >>> 0;
|
|
233932
233934
|
for (let i6 = 0; i6 < array.length; i6++) {
|
|
233933
|
-
const
|
|
233934
|
-
getDataViewMemory0().setUint32(ptr + 4 * i6,
|
|
233935
|
+
const add4 = addToExternrefTable0(array[i6]);
|
|
233936
|
+
getDataViewMemory0().setUint32(ptr + 4 * i6, add4, true);
|
|
233935
233937
|
}
|
|
233936
233938
|
WASM_VECTOR_LEN = array.length;
|
|
233937
233939
|
return ptr;
|
|
@@ -234901,6 +234903,10 @@ function createSessionKeyStorage(options = {}) {
|
|
|
234901
234903
|
listSessionKeys
|
|
234902
234904
|
});
|
|
234903
234905
|
}
|
|
234906
|
+
async function signTypedDigest(domainSeparator2, structHash, privateKey) {
|
|
234907
|
+
const digest = keccak2563(concat3(["0x1901", domainSeparator2, structHash]));
|
|
234908
|
+
return privateKeyToAccount(privateKey).sign({ hash: digest });
|
|
234909
|
+
}
|
|
234904
234910
|
function encodeERC7821ExecuteBatch(calls) {
|
|
234905
234911
|
const executionData = encodeAbiParameters2(
|
|
234906
234912
|
[{ type: "tuple[]", components: erc7281_default.ABI[1].components }],
|
|
@@ -235162,6 +235168,9 @@ function cancelFromSourceContext(order, commitment) {
|
|
|
235162
235168
|
]
|
|
235163
235169
|
);
|
|
235164
235170
|
}
|
|
235171
|
+
function supportedReleases(stateMachineId) {
|
|
235172
|
+
return TESTNET_CHAINS.has(stateMachineId) ? TESTNET_INTENTS_VERSIONS : [SUPPORTED_INTENTS_VERSION];
|
|
235173
|
+
}
|
|
235165
235174
|
async function readContractVersion(client, address) {
|
|
235166
235175
|
try {
|
|
235167
235176
|
return await client.readContract({ address, abi: CONTRACT_VERSION_ABI, functionName: "version" });
|
|
@@ -235170,14 +235179,17 @@ async function readContractVersion(client, address) {
|
|
|
235170
235179
|
throw error;
|
|
235171
235180
|
}
|
|
235172
235181
|
}
|
|
235173
|
-
async function supportsRateFills(client, gateway) {
|
|
235174
|
-
|
|
235182
|
+
async function supportsRateFills(client, gateway, stateMachineId) {
|
|
235183
|
+
const version17 = await readContractVersion(client, gateway);
|
|
235184
|
+
return supportedReleases(stateMachineId).some((release) => release === version17);
|
|
235175
235185
|
}
|
|
235176
|
-
async function assertGatewayRelease(client, gateway) {
|
|
235186
|
+
async function assertGatewayRelease(client, gateway, stateMachineId) {
|
|
235187
|
+
const supported = supportedReleases(stateMachineId);
|
|
235177
235188
|
const version17 = await readContractVersion(client, gateway);
|
|
235178
|
-
if (
|
|
235189
|
+
if (supported.some((release) => release === version17)) return;
|
|
235190
|
+
const required2 = supported.join(" or ");
|
|
235179
235191
|
throw new Error(
|
|
235180
|
-
version17 === void 0 ? `IntentGateway ${gateway} reports no version(); this SDK requires release ${
|
|
235192
|
+
version17 === void 0 ? `IntentGateway ${gateway} reports no version(); this SDK requires release ${required2}` : `IntentGateway ${gateway} reports release ${String(version17)}; this SDK requires release ${required2}`
|
|
235181
235193
|
);
|
|
235182
235194
|
}
|
|
235183
235195
|
function isCanonicalEvmToken(token) {
|
|
@@ -235219,6 +235231,40 @@ function decodeFillOrder(data4) {
|
|
|
235219
235231
|
return null;
|
|
235220
235232
|
}
|
|
235221
235233
|
}
|
|
235234
|
+
function readSelectionFormat(client, chainId, gateway) {
|
|
235235
|
+
const key = `${chainId}:${gateway.toLowerCase()}`;
|
|
235236
|
+
const cached = formats.get(key);
|
|
235237
|
+
if (cached) return cached;
|
|
235238
|
+
const format2 = client.readContract({ address: gateway, abi: ABI3, functionName: "SELECT_SOLVER_TYPEHASH" }).then((typehash) => {
|
|
235239
|
+
switch (typehash.toLowerCase()) {
|
|
235240
|
+
case SELECT_SOLVER_TYPEHASH:
|
|
235241
|
+
return "userOpHash";
|
|
235242
|
+
case LEGACY_SELECT_SOLVER_TYPEHASH:
|
|
235243
|
+
return "address";
|
|
235244
|
+
default:
|
|
235245
|
+
throw new Error(
|
|
235246
|
+
`IntentGatewayV2 ${gateway} on chain ${chainId} has unknown SELECT_SOLVER_TYPEHASH ${typehash}`
|
|
235247
|
+
);
|
|
235248
|
+
}
|
|
235249
|
+
});
|
|
235250
|
+
formats.set(key, format2);
|
|
235251
|
+
format2.catch(() => {
|
|
235252
|
+
if (formats.get(key) === format2) formats.delete(key);
|
|
235253
|
+
});
|
|
235254
|
+
return format2;
|
|
235255
|
+
}
|
|
235256
|
+
function refreshSelectionFormat(client, chainId, gateway, stale) {
|
|
235257
|
+
const key = `${chainId}:${gateway.toLowerCase()}`;
|
|
235258
|
+
if (formats.get(key) === stale) formats.delete(key);
|
|
235259
|
+
return readSelectionFormat(client, chainId, gateway);
|
|
235260
|
+
}
|
|
235261
|
+
async function selectionOffStateDiff(client, gateway) {
|
|
235262
|
+
const word = await client.getStorageAt({ address: gateway, slot: SELECTION_PARAMS_SLOT });
|
|
235263
|
+
return {
|
|
235264
|
+
slot: SELECTION_PARAMS_SLOT,
|
|
235265
|
+
value: toHex3(hexToBigInt2(word ?? "0x0") & SOLVER_SELECTION_CLEARED, { size: 32 })
|
|
235266
|
+
};
|
|
235267
|
+
}
|
|
235222
235268
|
function userOperationLogs(logs, entryPoint, userOpHash) {
|
|
235223
235269
|
const [beforeExecution, userOperationEvent] = ENTRY_POINT_EVENT_ABI.map((event) => toEventSelector2(event));
|
|
235224
235270
|
const isBoundary = (log4) => log4.address.toLowerCase() === entryPoint.toLowerCase() && (log4.topics[0] === beforeExecution || log4.topics[0] === userOperationEvent);
|
|
@@ -235237,6 +235283,40 @@ function userOperationLogs(logs, entryPoint, userOpHash) {
|
|
|
235237
235283
|
while (start >= 0 && !isBoundary(logs[start])) start--;
|
|
235238
235284
|
return logs.slice(start + 1, end);
|
|
235239
235285
|
}
|
|
235286
|
+
async function fetchRundlerPriorityFee(bundlerUrl) {
|
|
235287
|
+
if (bundlersWithoutRundlerFees.has(bundlerUrl)) return null;
|
|
235288
|
+
try {
|
|
235289
|
+
const response = await fetch(bundlerUrl, {
|
|
235290
|
+
method: "POST",
|
|
235291
|
+
headers: { "Content-Type": "application/json" },
|
|
235292
|
+
body: JSON.stringify({
|
|
235293
|
+
jsonrpc: "2.0",
|
|
235294
|
+
id: 1,
|
|
235295
|
+
method: BundlerMethod.RUNDLER_MAX_PRIORITY_FEE_PER_GAS,
|
|
235296
|
+
params: []
|
|
235297
|
+
})
|
|
235298
|
+
});
|
|
235299
|
+
const { result, error } = await response.json();
|
|
235300
|
+
if (error) {
|
|
235301
|
+
if (error.code !== void 0 && UNSUPPORTED_REQUEST_CODES.has(error.code)) {
|
|
235302
|
+
bundlersWithoutRundlerFees.add(bundlerUrl);
|
|
235303
|
+
}
|
|
235304
|
+
return null;
|
|
235305
|
+
}
|
|
235306
|
+
return result == null ? null : BigInt(result);
|
|
235307
|
+
} catch {
|
|
235308
|
+
return null;
|
|
235309
|
+
}
|
|
235310
|
+
}
|
|
235311
|
+
function applyRundlerPriorityFee(fees4, params) {
|
|
235312
|
+
const { rundlerPriorityFee, baseFeePerGas, priorityFeeBumpPercent, maxFeeBumpPercent } = params;
|
|
235313
|
+
const priorityFloor = rundlerPriorityFee + rundlerPriorityFee * priorityFeeBumpPercent / 100n;
|
|
235314
|
+
const maxFeeFloor = baseFeePerGas + baseFeePerGas * maxFeeBumpPercent / 100n + priorityFloor;
|
|
235315
|
+
return {
|
|
235316
|
+
maxPriorityFeePerGas: fees4.maxPriorityFeePerGas > priorityFloor ? fees4.maxPriorityFeePerGas : priorityFloor,
|
|
235317
|
+
maxFeePerGas: fees4.maxFeePerGas > maxFeeFloor ? fees4.maxFeePerGas : maxFeeFloor
|
|
235318
|
+
};
|
|
235319
|
+
}
|
|
235240
235320
|
function escrowSlot(commitment, leg) {
|
|
235241
235321
|
const byCommitment = keccak2563(
|
|
235242
235322
|
encodeAbiParameters2([{ type: "bytes32" }, { type: "uint256" }], [commitment, ESCROW_MAPPING_SLOT])
|
|
@@ -235422,7 +235502,7 @@ function encodePhantomBidDeclaration(declaration) {
|
|
|
235422
235502
|
}
|
|
235423
235503
|
return u8aToHex(new Uint8Array(bytes5));
|
|
235424
235504
|
}
|
|
235425
|
-
var import_merge_race, __defProp3, __getOwnPropNames2, __esm2, __export2, node_exports, wasm, full_path, __dirname$1, cachedTextDecoder, cachedUint8ArrayMemory0, WASM_VECTOR_LEN, cachedTextEncoder, encodeString5, cachedDataViewMemory0, KeccakMergeFinalization, KeccakMerge, wasmPath, wasmBytes2, bindings, wasmModule, wasmInstance, __wasm, init_node11, RequestStatus, TimeoutStatus, IntentOrderStatus, ABI, evmHost_default, ABI2, handlerV2_default, polkadotAssetHubPaseo, polkadotHubMainnet, pharosMainnet, pharosAtlantic, tronNile, chainConfigs, configsByStateMachineId, getConfigByStateMachineId, getChainId3, getViemChain, hyperbridgeAddress, ABI3, IntentGatewayV2_default, ChainConfigService, ABI4, uniswapRouterV2_default, chains, DEFAULT_ADDRESS, EvmChain, REQUEST_COMMITMENTS_SLOT, RESPONSE_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, STATE_COMMITMENTS_SLOT, MISSING_CONSENSUS_UPDATE_TIME_MESSAGE, MissingConsensusUpdateTimeError, TokenBucket, BATCHES_NOT_SUPPORTED_CODE, TOO_BIG_BATCH_REQUEST_CODE, DEFAULT_MAX_BATCH_SIZE, _endpoint2, _headers3, _limiter, _maxBatchSize, _batchingSupported, _pending2, _flushTimer, _flushing, _nextId, __BatchingHttpProvider_instances, scheduleFlush_fn, flushNow_fn, flush_fn, post_fn, settleBatch_fn, settle_fn, handleBatchRefusal_fn, requeue_fn, _a5, BatchingHttpProvider, OFFCHAIN_BID_PREFIX, HYPERBRIDGE_TYPES_BUNDLE, BASE_TIP, HTTP_CONNECT_TIMEOUT_MS, INCLUSION_TIMEOUT_MS, DEFAULT_RPC_MAX_RPS, rpcLimiters, BidCodec, PackedUserOperationCodec, IntentsCoprocessor, ReviveContractInfo, ReviveAccountType, ReviveAccountInfo, H256, EvmStateProof, SubstrateHashing, SubstrateStateMachineProof, BasicProof, LeafIndexAndPos, MmrProof, ConsensusStateId, ConsensusMessage, FraudProofMessage, StateMachine, StateMachineId, StateMachineHeight, Proof, PostRequest, PostResponse, GetRequest, StorageValue, GetResponse, Request3, Response2, RequestMessage, RequestResponse, ResponseMessage, TimeoutMessage, GetRequestsWithProof, Message, DEFAULT_CHILD_STORAGE_PREFIX, PharosProofNodeCodec, SiblingLeftmostLeafProofCodec, NonExistenceProofCodec, AccountProofDataCodec, PharosStateProof, DEFAULT_POLL_INTERVAL, ADDRESS_ZERO2, DEFAULT_GRAFFITI, DEFAULT_LOGGER, REQUEST_STATUS_WEIGHTS, TIMEOUT_STATUS_WEIGHTS, COMBINED_STATUS_WEIGHTS, CHAIN_ID_TO_COINGECKO_NATIVE, TESTNET_CHAINS, ORDER_STATUS, loadDriver, detectEnvironment, STORAGE_KEYS, LEGACY_STORAGE_KEYS, ABI5, uniswapV3Quoter_default, UNISWAP_V4_QUOTER_ABI, ABI6, universalRouter_default, PERMIT2_ABI, UniswapQuoteEngine, COMMON_FEE_TIERS, Swap, ABI7, erc7281_default, DEFAULT_GRAFFITI2, ERC7821_BATCH_MODE, BundlerMethod, SELECT_SOLVER_TYPEHASH, PACKED_USEROP_TYPEHASH, DOMAIN_TYPEHASH, CryptoUtils, FEE_TOKEN_CACHE_TTL_MS, OrderPlacer, TOKEN_KEYED_GATEWAY_ABI, keyingByClient, PARTIAL_FILLS_SLOT, USED_USEROPS_STORAGE_KEY, OrderExecutor, _a6, OrderCanceller, FILL_ORDER_SELECTOR, SUPPORTED_INTENTS_VERSION, CONTRACT_VERSION_ABI, CANONICAL_EVM_TOKEN, ENTRY_POINT_EVENT_ABI, BidImpl, BidManager, RELAYER_MESSAGE_GAS, NO_BUNDLER_FILL_GAS_BASE, NO_BUNDLER_FILL_GAS_PER_OUTPUT, NO_BUNDLER_PAYMASTER_VERIFICATION_GAS, NO_BUNDLER_PAYMASTER_POST_OP_GAS, BID_PVG_ESTIMATION_ACCOUNT_CODE, SELECTED_BID_SIGNATURE_BYTES, BID_PVG_HEADROOM_PERCENT, ESCROW_MAPPING_SLOT, GasEstimator, OrderStatusChecker, ORDERBOOK_URLS, ORDERBOOK_DECIMALS, ORDERBOOK_SCALE, OrderbookRequestError, RATE_FIELDS, TOP_OF_BOOK_QUERY, ROUTE_LIQUIDITY_QUERY, QUOTE_QUERY, QUOTE_PESSIMISTIC_QUERY, HyperFxOrderbook, UnsupportedLiquidityAssetError, UnsupportedLiquidityChainError, OrderbookQuoteNotConvergedError, MAX_EXACT_OUTPUT_ROUNDS, OrderbookMarket, ETHEREUM_ORDER_FEE_GAS_PRICE_BUMP_PERCENT, DEFAULT_ORDER_FEE_GAS_PRICE_BUMP_PERCENT, IntentGateway, DECLARATION_V1, DECLARATION_V2, PAYMASTER_ADDRESS_BYTES, PAYMASTER_GAS_LIMIT_BYTES, PAYMASTER_DATA_OFFSET, PERMIT2_DATA_BYTES, PERMIT2_SPONSORSHIP_BYTES, MAX_DECLARED_ENTRIES, MAX_TOKEN_ID_BYTES, TeleportParams, MultiAccount;
|
|
235505
|
+
var import_merge_race, __defProp3, __getOwnPropNames2, __esm2, __export2, node_exports, wasm, full_path, __dirname$1, cachedTextDecoder, cachedUint8ArrayMemory0, WASM_VECTOR_LEN, cachedTextEncoder, encodeString5, cachedDataViewMemory0, KeccakMergeFinalization, KeccakMerge, wasmPath, wasmBytes2, bindings, wasmModule, wasmInstance, __wasm, init_node11, RequestStatus, TimeoutStatus, IntentOrderStatus, ABI, evmHost_default, ABI2, handlerV2_default, polkadotAssetHubPaseo, polkadotHubMainnet, pharosMainnet, pharosAtlantic, tronNile, ENTRY_POINT_V08, ENTRY_POINT_V09, KNOWN_ENTRY_POINTS, chainConfigs, configsByStateMachineId, getConfigByStateMachineId, getChainId3, getViemChain, hyperbridgeAddress, ABI3, IntentGatewayV2_default, ChainConfigService, ABI4, uniswapRouterV2_default, chains, DEFAULT_ADDRESS, EvmChain, REQUEST_COMMITMENTS_SLOT, RESPONSE_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, STATE_COMMITMENTS_SLOT, MISSING_CONSENSUS_UPDATE_TIME_MESSAGE, MissingConsensusUpdateTimeError, TokenBucket, BATCHES_NOT_SUPPORTED_CODE, TOO_BIG_BATCH_REQUEST_CODE, DEFAULT_MAX_BATCH_SIZE, _endpoint2, _headers3, _limiter, _maxBatchSize, _batchingSupported, _pending2, _flushTimer, _flushing, _nextId, __BatchingHttpProvider_instances, scheduleFlush_fn, flushNow_fn, flush_fn, post_fn, settleBatch_fn, settle_fn, handleBatchRefusal_fn, requeue_fn, _a5, BatchingHttpProvider, OFFCHAIN_BID_PREFIX, HYPERBRIDGE_TYPES_BUNDLE, BASE_TIP, HTTP_CONNECT_TIMEOUT_MS, INCLUSION_TIMEOUT_MS, DEFAULT_RPC_MAX_RPS, rpcLimiters, BidCodec, PackedUserOperationCodec, IntentsCoprocessor, ReviveContractInfo, ReviveAccountType, ReviveAccountInfo, H256, EvmStateProof, SubstrateHashing, SubstrateStateMachineProof, BasicProof, LeafIndexAndPos, MmrProof, ConsensusStateId, ConsensusMessage, FraudProofMessage, StateMachine, StateMachineId, StateMachineHeight, Proof, PostRequest, PostResponse, GetRequest, StorageValue, GetResponse, Request3, Response2, RequestMessage, RequestResponse, ResponseMessage, TimeoutMessage, GetRequestsWithProof, Message, DEFAULT_CHILD_STORAGE_PREFIX, PharosProofNodeCodec, SiblingLeftmostLeafProofCodec, NonExistenceProofCodec, AccountProofDataCodec, PharosStateProof, DEFAULT_POLL_INTERVAL, ADDRESS_ZERO2, DEFAULT_GRAFFITI, DEFAULT_LOGGER, REQUEST_STATUS_WEIGHTS, TIMEOUT_STATUS_WEIGHTS, COMBINED_STATUS_WEIGHTS, CHAIN_ID_TO_COINGECKO_NATIVE, TESTNET_CHAINS, ORDER_STATUS, loadDriver, detectEnvironment, STORAGE_KEYS, LEGACY_STORAGE_KEYS, ABI5, uniswapV3Quoter_default, UNISWAP_V4_QUOTER_ABI, ABI6, universalRouter_default, PERMIT2_ABI, UniswapQuoteEngine, COMMON_FEE_TIERS, Swap, ABI7, erc7281_default, DEFAULT_GRAFFITI2, ERC7821_BATCH_MODE, BundlerMethod, SELECT_SOLVER_TYPEHASH, LEGACY_SELECT_SOLVER_TYPEHASH, PACKED_USEROP_TYPEHASH, DOMAIN_TYPEHASH, CryptoUtils, FEE_TOKEN_CACHE_TTL_MS, OrderPlacer, TOKEN_KEYED_GATEWAY_ABI, keyingByClient, PARTIAL_FILLS_SLOT, USED_USEROPS_STORAGE_KEY, OrderExecutor, _a6, OrderCanceller, FILL_ORDER_SELECTOR, SUPPORTED_INTENTS_VERSION, TESTNET_INTENTS_VERSIONS, CONTRACT_VERSION_ABI, CANONICAL_EVM_TOKEN, formats, SELECTION_PARAMS_SLOT, SOLVER_SELECTION_CLEARED, SELECTION_FORMAT_BY_ENTRY_POINT, ENTRY_POINT_EVENT_ABI, BidImpl, BidManager, UNSUPPORTED_REQUEST_CODES, bundlersWithoutRundlerFees, RELAYER_MESSAGE_GAS, NO_BUNDLER_FILL_GAS_BASE, NO_BUNDLER_FILL_GAS_PER_OUTPUT, NO_BUNDLER_PAYMASTER_VERIFICATION_GAS, NO_BUNDLER_PAYMASTER_POST_OP_GAS, BID_PVG_ESTIMATION_ACCOUNT_CODE, BID_PVG_ESTIMATION_PAYMASTER_CODE, SELECTED_BID_SIGNATURE_BYTES, BID_PVG_HEADROOM_PERCENT, ESCROW_MAPPING_SLOT, GasEstimator, OrderStatusChecker, ORDERBOOK_URLS, ORDERBOOK_DECIMALS, ORDERBOOK_SCALE, OrderbookRequestError, RATE_FIELDS, TOP_OF_BOOK_QUERY, ROUTE_LIQUIDITY_QUERY, QUOTE_QUERY, QUOTE_PESSIMISTIC_QUERY, HyperFxOrderbook, UnsupportedLiquidityAssetError, UnsupportedLiquidityChainError, OrderbookQuoteNotConvergedError, MAX_EXACT_OUTPUT_ROUNDS, OrderbookMarket, ETHEREUM_ORDER_FEE_GAS_PRICE_BUMP_PERCENT, DEFAULT_ORDER_FEE_GAS_PRICE_BUMP_PERCENT, IntentGateway, DECLARATION_V1, DECLARATION_V2, PAYMASTER_ADDRESS_BYTES, PAYMASTER_GAS_LIMIT_BYTES, PAYMASTER_DATA_OFFSET, PERMIT2_DATA_BYTES, PERMIT2_SPONSORSHIP_BYTES, MAX_DECLARED_ENTRIES, MAX_TOKEN_ID_BYTES, TeleportParams, MultiAccount;
|
|
235426
235506
|
var init_node10 = __esm({
|
|
235427
235507
|
"../sdk/dist/node/index.js"() {
|
|
235428
235508
|
"use strict";
|
|
@@ -237775,6 +237855,9 @@ var init_node10 = __esm({
|
|
|
237775
237855
|
default: { name: "Nile Tronscan", url: "https://nile.tronscan.org" }
|
|
237776
237856
|
}
|
|
237777
237857
|
});
|
|
237858
|
+
ENTRY_POINT_V08 = "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108";
|
|
237859
|
+
ENTRY_POINT_V09 = "0x433709009B8330FDa32311DF1C2AFA402eD8D009";
|
|
237860
|
+
KNOWN_ENTRY_POINTS = [ENTRY_POINT_V09, ENTRY_POINT_V08];
|
|
237778
237861
|
chainConfigs = {
|
|
237779
237862
|
97: {
|
|
237780
237863
|
chainId: 97,
|
|
@@ -237807,8 +237890,10 @@ var init_node10 = __esm({
|
|
|
237807
237890
|
UniversalRouter: "0xcc6d5ece3d4a57245bf5a2f64f3ed9179b81f714",
|
|
237808
237891
|
UniswapV3Quoter: "0x0000000000000000000000000000000000000000",
|
|
237809
237892
|
UniswapV4Quoter: "0x0000000000000000000000000000000000000000",
|
|
237810
|
-
|
|
237811
|
-
|
|
237893
|
+
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
237894
|
+
EntryPoint: "0x433709009B8330FDa32311DF1C2AFA402eD8D009",
|
|
237895
|
+
SolverAccount: "0x7484C6Ff790b898bf7e6960Ffc82f63330445Dc2",
|
|
237896
|
+
SimplexPaymaster: "0x9f4a6F1254f27373C2aca5bDd0e48FbA45EA3aeC"
|
|
237812
237897
|
},
|
|
237813
237898
|
rpcEnvKey: "BSC_CHAPEL",
|
|
237814
237899
|
defaultRpcUrl: "https://bnb-testnet.api.onfinality.io/public",
|
|
@@ -237843,7 +237928,7 @@ var init_node10 = __esm({
|
|
|
237843
237928
|
UniswapRouter02: "0x0000000000000000000000000000000000000000",
|
|
237844
237929
|
UniswapV2Factory: "0x0000000000000000000000000000000000000000",
|
|
237845
237930
|
UniswapV3Factory: "0x0000000000000000000000000000000000000000",
|
|
237846
|
-
|
|
237931
|
+
EntryPoint: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
237847
237932
|
},
|
|
237848
237933
|
rpcEnvKey: "GNOSIS_CHIADO",
|
|
237849
237934
|
defaultRpcUrl: "https://gnosis-chiado-rpc.publicnode.com",
|
|
@@ -237883,7 +237968,7 @@ var init_node10 = __esm({
|
|
|
237883
237968
|
UniswapV2Factory: "0x0000000000000000000000000000000000000000",
|
|
237884
237969
|
UniswapV3Factory: "0x0000000000000000000000000000000000000000",
|
|
237885
237970
|
Calldispatcher: "0xC7f13b6D03A0A7F3239d38897503E90553ABe155",
|
|
237886
|
-
|
|
237971
|
+
EntryPoint: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
237887
237972
|
},
|
|
237888
237973
|
rpcEnvKey: "SEPOLIA",
|
|
237889
237974
|
defaultRpcUrl: "https://1rpc.io/sepolia",
|
|
@@ -237934,7 +238019,7 @@ var init_node10 = __esm({
|
|
|
237934
238019
|
},
|
|
237935
238020
|
addresses: {
|
|
237936
238021
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
237937
|
-
SolverAccount: "
|
|
238022
|
+
SolverAccount: "0xaAd062555800a97Af062795189e32a3CBd045612",
|
|
237938
238023
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
237939
238024
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
237940
238025
|
UniswapRouter02: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
|
|
@@ -237948,7 +238033,7 @@ var init_node10 = __esm({
|
|
|
237948
238033
|
UniswapV4StateView: "0x7ffe42c4a5deea5b0fec41c94c136cf115597227",
|
|
237949
238034
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
237950
238035
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
237951
|
-
|
|
238036
|
+
EntryPoint: "0x433709009B8330FDa32311DF1C2AFA402eD8D009",
|
|
237952
238037
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
237953
238038
|
SimplexPaymaster: "0xD4340d7466e040626383cb9cda9307ba8E081149",
|
|
237954
238039
|
Usdt0Oft: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee"
|
|
@@ -237980,7 +238065,8 @@ var init_node10 = __esm({
|
|
|
237980
238065
|
USDC: "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d",
|
|
237981
238066
|
USDT: "0x55d398326f99059ff775485246999027b3197955",
|
|
237982
238067
|
EXT: "0x7C8c11ADb8EF7cd3CFa718008Ea048445C6E7209",
|
|
237983
|
-
cNGN: "0xa8AEA66B361a8d53e8865c62D142167Af28Af058"
|
|
238068
|
+
cNGN: "0xa8AEA66B361a8d53e8865c62D142167Af28Af058",
|
|
238069
|
+
BRIDGE: "0x5b0c50fDd52ECC0d4c682c441eaBaD41FfDEABBB"
|
|
237984
238070
|
},
|
|
237985
238071
|
tokenDecimals: {
|
|
237986
238072
|
USDC: 18,
|
|
@@ -237989,19 +238075,21 @@ var init_node10 = __esm({
|
|
|
237989
238075
|
// Binance-pegged stables above. Every phantom standard_amount and pool rate divides
|
|
237990
238076
|
// by this, so the divergence from its neighbours here is load-bearing, not a typo.
|
|
237991
238077
|
cNGN: 6,
|
|
237992
|
-
EXT: 18
|
|
238078
|
+
EXT: 18,
|
|
238079
|
+
BRIDGE: 18
|
|
237993
238080
|
},
|
|
237994
238081
|
tokenStorageSlots: {
|
|
237995
238082
|
USDT: { balanceSlot: 1, allowanceSlot: 2 },
|
|
237996
238083
|
USDC: { balanceSlot: 1, allowanceSlot: 2 },
|
|
237997
238084
|
WETH: { balanceSlot: 3, allowanceSlot: 4 },
|
|
237998
238085
|
DAI: { balanceSlot: 0, allowanceSlot: 0 },
|
|
237999
|
-
cNGN: { balanceSlot: 201, allowanceSlot: 202 }
|
|
238086
|
+
cNGN: { balanceSlot: 201, allowanceSlot: 202 },
|
|
238000
238087
|
// custom upgradeable layout, as on Base
|
|
238088
|
+
BRIDGE: { balanceSlot: 0, allowanceSlot: 1 }
|
|
238001
238089
|
},
|
|
238002
238090
|
addresses: {
|
|
238003
238091
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
238004
|
-
SolverAccount: "
|
|
238092
|
+
SolverAccount: "0xaAd062555800a97Af062795189e32a3CBd045612",
|
|
238005
238093
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
238006
238094
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
238007
238095
|
UniswapRouter02: "0x10ED43C718714eb63d5aA57B78B54704E256024E",
|
|
@@ -238015,7 +238103,7 @@ var init_node10 = __esm({
|
|
|
238015
238103
|
UniswapV4StateView: "0xd13dd3d6e93f276fafc9db9e6bb47c1180aee0c4",
|
|
238016
238104
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
238017
238105
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
238018
|
-
|
|
238106
|
+
EntryPoint: "0x433709009B8330FDa32311DF1C2AFA402eD8D009",
|
|
238019
238107
|
SimplexPaymaster: "0xeD02f9f0df8F562B89cC5b25867Ad3C2d61252A9"
|
|
238020
238108
|
// "Usdt0Oft": Not available on BSC
|
|
238021
238109
|
},
|
|
@@ -238062,7 +238150,7 @@ var init_node10 = __esm({
|
|
|
238062
238150
|
},
|
|
238063
238151
|
addresses: {
|
|
238064
238152
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
238065
|
-
SolverAccount: "
|
|
238153
|
+
SolverAccount: "0xaAd062555800a97Af062795189e32a3CBd045612",
|
|
238066
238154
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
238067
238155
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
238068
238156
|
UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
|
|
@@ -238076,7 +238164,7 @@ var init_node10 = __esm({
|
|
|
238076
238164
|
UniswapV4StateView: "0x76fd297e2d437cd7f76d50f01afe6160f86e9990",
|
|
238077
238165
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
238078
238166
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
238079
|
-
|
|
238167
|
+
EntryPoint: "0x433709009B8330FDa32311DF1C2AFA402eD8D009",
|
|
238080
238168
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
238081
238169
|
SimplexPaymaster: "0x7281Bccb4f0BCE44F3B8542d1fC5e51c2F5fC08C",
|
|
238082
238170
|
Usdt0Oft: "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92"
|
|
@@ -238136,7 +238224,7 @@ var init_node10 = __esm({
|
|
|
238136
238224
|
},
|
|
238137
238225
|
addresses: {
|
|
238138
238226
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
238139
|
-
SolverAccount: "
|
|
238227
|
+
SolverAccount: "0xaAd062555800a97Af062795189e32a3CBd045612",
|
|
238140
238228
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
238141
238229
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
238142
238230
|
UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
|
|
@@ -238147,7 +238235,7 @@ var init_node10 = __esm({
|
|
|
238147
238235
|
UniswapV4Quoter: "0x0d5e0f971ed27fbff6c2837bf31316121532048d",
|
|
238148
238236
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
238149
238237
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
238150
|
-
|
|
238238
|
+
EntryPoint: "0x433709009B8330FDa32311DF1C2AFA402eD8D009",
|
|
238151
238239
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
238152
238240
|
SimplexPaymaster: "0x15b3B03C870c7ef252029c35A12d3b339F5c8d7f",
|
|
238153
238241
|
AerodromeRouter: "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43",
|
|
@@ -238186,7 +238274,8 @@ var init_node10 = __esm({
|
|
|
238186
238274
|
cNGN: "0x52828daa48C1a9A06F37500882b42daf0bE04C3B",
|
|
238187
238275
|
ZARP: "0xb755506531786C8aC63B756BaB1ac387bACB0C04",
|
|
238188
238276
|
XSGD: "0xDC3326e71D45186F113a2F448984CA0e8D201995",
|
|
238189
|
-
USDR: "0x3B5F2810fB2168FfA9C73160F97BF9f2461fFa5c"
|
|
238277
|
+
USDR: "0x3B5F2810fB2168FfA9C73160F97BF9f2461fFa5c",
|
|
238278
|
+
BRIDGE: "0x5b0c50fDd52ECC0d4c682c441eaBaD41FfDEABBB"
|
|
238190
238279
|
},
|
|
238191
238280
|
tokenDecimals: {
|
|
238192
238281
|
USDC: 6,
|
|
@@ -238195,7 +238284,8 @@ var init_node10 = __esm({
|
|
|
238195
238284
|
cNGN: 6,
|
|
238196
238285
|
ZARP: 18,
|
|
238197
238286
|
XSGD: 6,
|
|
238198
|
-
USDR: 6
|
|
238287
|
+
USDR: 6,
|
|
238288
|
+
BRIDGE: 18
|
|
238199
238289
|
},
|
|
238200
238290
|
tokenStorageSlots: {
|
|
238201
238291
|
USDT: { balanceSlot: 0, allowanceSlot: 1 },
|
|
@@ -238206,11 +238296,12 @@ var init_node10 = __esm({
|
|
|
238206
238296
|
// custom upgradeable layout
|
|
238207
238297
|
ZARP: { balanceSlot: 51, allowanceSlot: 52 },
|
|
238208
238298
|
XSGD: { balanceSlot: 7, allowanceSlot: 8 },
|
|
238209
|
-
USDR: { balanceSlot: 51, allowanceSlot: 52 }
|
|
238299
|
+
USDR: { balanceSlot: 51, allowanceSlot: 52 },
|
|
238300
|
+
BRIDGE: { balanceSlot: 0, allowanceSlot: 1 }
|
|
238210
238301
|
},
|
|
238211
238302
|
addresses: {
|
|
238212
238303
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
238213
|
-
SolverAccount: "
|
|
238304
|
+
SolverAccount: "0xaAd062555800a97Af062795189e32a3CBd045612",
|
|
238214
238305
|
TokenGateway: "0x8b536105b6Fae2aE9199f5146D3C57Dfe53b614E",
|
|
238215
238306
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
238216
238307
|
UniswapRouter02: "0xd2f9496824951D5237cC71245D659E48d0d5f9E8",
|
|
@@ -238224,7 +238315,7 @@ var init_node10 = __esm({
|
|
|
238224
238315
|
UniswapV4StateView: "0x5ea1bd7974c8a611cbab0bdcafcb1d9cc9b3ba5a",
|
|
238225
238316
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
238226
238317
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
238227
|
-
|
|
238318
|
+
EntryPoint: "0x433709009B8330FDa32311DF1C2AFA402eD8D009",
|
|
238228
238319
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
238229
238320
|
SimplexPaymaster: "0xe99acFe0f5fC4C8ea54A187D8D3b05f136150095",
|
|
238230
238321
|
Usdt0Oft: "0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13"
|
|
@@ -238303,8 +238394,9 @@ var init_node10 = __esm({
|
|
|
238303
238394
|
Host: "0x9AA003594d59C62EE17A73A569Fd7B1DbdBd71E1",
|
|
238304
238395
|
Calldispatcher: "0x876F1891982E260026630c233A4897160A281Fb8",
|
|
238305
238396
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
238306
|
-
|
|
238307
|
-
SolverAccount: "
|
|
238397
|
+
EntryPoint: "0x433709009B8330FDa32311DF1C2AFA402eD8D009",
|
|
238398
|
+
SolverAccount: "0x7484C6Ff790b898bf7e6960Ffc82f63330445Dc2",
|
|
238399
|
+
SimplexPaymaster: "0x6085a14078B7d26259145a894140f7C8361e02ae"
|
|
238308
238400
|
},
|
|
238309
238401
|
rpcEnvKey: "POLYGON_AMOY",
|
|
238310
238402
|
defaultRpcUrl: "https://rpc-amoy.polygon.technology",
|
|
@@ -238336,7 +238428,7 @@ var init_node10 = __esm({
|
|
|
238336
238428
|
UniswapV3Factory: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
238337
238429
|
Calldispatcher: "0xC71251c8b3e7B02697A84363Eef6DcE8DfBdF333",
|
|
238338
238430
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
238339
|
-
|
|
238431
|
+
EntryPoint: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
238340
238432
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
238341
238433
|
UniswapV4PositionManager: "0x3c3ea4b57a46241e54610e5f022e5c45859a1017",
|
|
238342
238434
|
UniswapV4PoolManager: "0x9a13f98cb987694c9f086b1f5eb990eea8264ec3"
|
|
@@ -238370,7 +238462,7 @@ var init_node10 = __esm({
|
|
|
238370
238462
|
// Mocked
|
|
238371
238463
|
UniswapV2Factory: "0x0000000000000000000000000000000000000000",
|
|
238372
238464
|
Calldispatcher: "0xC71251c8b3e7B02697A84363Eef6DcE8DfBdF333",
|
|
238373
|
-
|
|
238465
|
+
EntryPoint: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
238374
238466
|
},
|
|
238375
238467
|
defaultRpcUrl: "https://rpc.gnosischain.com",
|
|
238376
238468
|
consensusStateId: "GNO0",
|
|
@@ -238395,7 +238487,7 @@ var init_node10 = __esm({
|
|
|
238395
238487
|
addresses: {
|
|
238396
238488
|
TokenGateway: "0xCe304770236f39F9911BfCC51afBdfF3b8635718",
|
|
238397
238489
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
238398
|
-
|
|
238490
|
+
EntryPoint: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
238399
238491
|
UniswapV4PositionManager: "0x1b35d13a2e2528f192637f14b05f0dc0e7deb566",
|
|
238400
238492
|
UniswapV4PoolManager: "0x360e68faccca8ca495c1b759fd9eee466db9fb32"
|
|
238401
238493
|
},
|
|
@@ -238421,7 +238513,7 @@ var init_node10 = __esm({
|
|
|
238421
238513
|
addresses: {
|
|
238422
238514
|
TokenGateway: "0xFcDa26cA021d5535C3059547390E6cCd8De7acA6",
|
|
238423
238515
|
Host: "0x9AA003594d59C62EE17A73A569Fd7B1DbdBd71E1",
|
|
238424
|
-
|
|
238516
|
+
EntryPoint: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
238425
238517
|
},
|
|
238426
238518
|
defaultRpcUrl: "https://sepolia-rollup.arbitrum.io/rpc",
|
|
238427
238519
|
consensusStateId: "ETH0",
|
|
@@ -238445,7 +238537,7 @@ var init_node10 = __esm({
|
|
|
238445
238537
|
addresses: {
|
|
238446
238538
|
TokenGateway: "0xFcDa26cA021d5535C3059547390E6cCd8De7acA6",
|
|
238447
238539
|
Host: "0x9AA003594d59C62EE17A73A569Fd7B1DbdBd71E1",
|
|
238448
|
-
|
|
238540
|
+
EntryPoint: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
238449
238541
|
},
|
|
238450
238542
|
defaultRpcUrl: "https://sepolia.optimism.io",
|
|
238451
238543
|
consensusStateId: "ETH0",
|
|
@@ -238469,7 +238561,7 @@ var init_node10 = __esm({
|
|
|
238469
238561
|
addresses: {
|
|
238470
238562
|
TokenGateway: "0xFcDa26cA021d5535C3059547390E6cCd8De7acA6",
|
|
238471
238563
|
Host: "0x9AA003594d59C62EE17A73A569Fd7B1DbdBd71E1",
|
|
238472
|
-
|
|
238564
|
+
EntryPoint: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
238473
238565
|
},
|
|
238474
238566
|
defaultRpcUrl: "https://sepolia.base.org",
|
|
238475
238567
|
consensusStateId: "ETH0",
|
|
@@ -238495,7 +238587,7 @@ var init_node10 = __esm({
|
|
|
238495
238587
|
IntentGateway: "0x606ba811aa6cb424ce2108e8977c5284686f0d1f",
|
|
238496
238588
|
TokenGateway: "0x1c1e5be83df4a54c7a2230c337e4a3e8b7354b1c",
|
|
238497
238589
|
Host: "0x9AA003594d59C62EE17A73A569Fd7B1DbdBd71E1",
|
|
238498
|
-
|
|
238590
|
+
EntryPoint: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
238499
238591
|
},
|
|
238500
238592
|
defaultRpcUrl: "https://testnet-asset-hub-eth-rpc.polkadot.io",
|
|
238501
238593
|
consensusStateId: "PAS0",
|
|
@@ -238519,7 +238611,7 @@ var init_node10 = __esm({
|
|
|
238519
238611
|
},
|
|
238520
238612
|
addresses: {
|
|
238521
238613
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
238522
|
-
SolverAccount: "
|
|
238614
|
+
SolverAccount: "0xaAd062555800a97Af062795189e32a3CBd045612",
|
|
238523
238615
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
238524
238616
|
Calldispatcher: "0xE2C7e576E26E0bE7aC97c6fE925bcDAbD87c4bEd"
|
|
238525
238617
|
},
|
|
@@ -239924,9 +240016,9 @@ var init_node10 = __esm({
|
|
|
239924
240016
|
internalType: "bytes32"
|
|
239925
240017
|
},
|
|
239926
240018
|
{
|
|
239927
|
-
name: "
|
|
239928
|
-
type: "
|
|
239929
|
-
internalType: "
|
|
240019
|
+
name: "userOpHash",
|
|
240020
|
+
type: "bytes32",
|
|
240021
|
+
internalType: "bytes32"
|
|
239930
240022
|
},
|
|
239931
240023
|
{
|
|
239932
240024
|
name: "signature",
|
|
@@ -240972,8 +241064,8 @@ var init_node10 = __esm({
|
|
|
240972
241064
|
getPopularTokens(chain2) {
|
|
240973
241065
|
return this.getConfig(chain2)?.popularTokens ?? [];
|
|
240974
241066
|
}
|
|
240975
|
-
|
|
240976
|
-
return this.getConfig(chain2)?.addresses.
|
|
241067
|
+
getEntryPointAddress(chain2) {
|
|
241068
|
+
return this.getConfig(chain2)?.addresses.EntryPoint;
|
|
240977
241069
|
}
|
|
240978
241070
|
getCirclePaymasterAddress(chain2) {
|
|
240979
241071
|
return this.getConfig(chain2)?.addresses.CirclePaymaster;
|
|
@@ -243235,6 +243327,9 @@ Failed HTTP Request: ${JSON.stringify(
|
|
|
243235
243327
|
* fails on-chain, and a second `retractBid` that pulls the bid just placed. When the signed nonce
|
|
243236
243328
|
* cannot be read, the stalled result is returned rather than guessed at.
|
|
243237
243329
|
*
|
|
243330
|
+
* A stall in `Future` first fills the missing nonce below it ({@link fillNonceGap}), so the
|
|
243331
|
+
* replacement can land.
|
|
243332
|
+
*
|
|
243238
243333
|
* A rejection that bounced off a copy already pooled (1013/1014) is likewise left alone: that
|
|
243239
243334
|
* copy is in flight and its outcome is unknown here, so the `pending` result goes back to the
|
|
243240
243335
|
* caller to confirm later.
|
|
@@ -243259,6 +243354,7 @@ Failed HTTP Request: ${JSON.stringify(
|
|
|
243259
243354
|
stalled = result;
|
|
243260
243355
|
nonce ?? (nonce = this.signedNonce(extrinsic));
|
|
243261
243356
|
if (nonce === void 0) return result;
|
|
243357
|
+
if (result.future) await this.fillNonceGap(keyPair, nonce, timeoutMs);
|
|
243262
243358
|
continue;
|
|
243263
243359
|
}
|
|
243264
243360
|
if (result.pending) return stalled ?? result;
|
|
@@ -243298,19 +243394,6 @@ Failed HTTP Request: ${JSON.stringify(
|
|
|
243298
243394
|
const inFlight = code === 1013 || code === 1014 || /already imported|already in the pool|priority is too low/i.test(err.message);
|
|
243299
243395
|
return { success: false, pending: inFlight || void 0, error: err.message };
|
|
243300
243396
|
}
|
|
243301
|
-
/**
|
|
243302
|
-
* Sends an extrinsic with a timeout.
|
|
243303
|
-
*
|
|
243304
|
-
* A timeout is only a failure when the extrinsic never made it into the transaction pool.
|
|
243305
|
-
* Once a pool-entry status (Future/Ready/Broadcast/Retracted) has been seen, the extrinsic is
|
|
243306
|
-
* in flight and may well execute after the watch is abandoned — the result is then `pending`
|
|
243307
|
-
* and `stalled`, telling the caller to replace it under the same nonce or confirm it later,
|
|
243308
|
-
* never to re-sign the same call under a fresh one.
|
|
243309
|
-
*
|
|
243310
|
-
* `nonce` pins the submission to a specific account nonce, which is what makes a retry a pool
|
|
243311
|
-
* replacement rather than a second extrinsic queued behind the first. Left undefined on the
|
|
243312
|
-
* first attempt, where the api's auto-nonce is correct.
|
|
243313
|
-
*/
|
|
243314
243397
|
/**
|
|
243315
243398
|
* The nonce the next submission signs with, or undefined when the node cannot be asked.
|
|
243316
243399
|
*
|
|
@@ -243327,6 +243410,7 @@ Failed HTTP Request: ${JSON.stringify(
|
|
|
243327
243410
|
* queued as future, or simply not counted yet — is covered by `lastPooledNonce` instead, which
|
|
243328
243411
|
* is the highest nonce this instance has put into the pool. The two are combined rather than
|
|
243329
243412
|
* trusted separately, so a burst never reuses a nonce and a restart still picks up the chain's.
|
|
243413
|
+
* A nonce left missing by an extrinsic the node dropped is filled by {@link fillNonceGap}.
|
|
243330
243414
|
*/
|
|
243331
243415
|
async nextNonce(api) {
|
|
243332
243416
|
try {
|
|
@@ -243340,11 +243424,53 @@ Failed HTTP Request: ${JSON.stringify(
|
|
|
243340
243424
|
return void 0;
|
|
243341
243425
|
}
|
|
243342
243426
|
}
|
|
243427
|
+
/**
|
|
243428
|
+
* A stall in `Future` means the node is missing a lower nonce of this account's, one whose
|
|
243429
|
+
* extrinsic it dropped, and everything signed above that nonce waits behind it. This fills the
|
|
243430
|
+
* lowest missing nonce, which `system_accountNextIndex` reports on the same node, with a
|
|
243431
|
+
* `system.remark` rather than the next call, so the calls already pooled above it land in the
|
|
243432
|
+
* order they were signed. One nonce per stall; a further gap shows up as the next `Future` stall.
|
|
243433
|
+
*
|
|
243434
|
+
* The remark carries no tip, so on any node or pool view that still holds a live call of ours at
|
|
243435
|
+
* that nonce, the call outranks it and the remark only ever fills a real gap.
|
|
243436
|
+
*
|
|
243437
|
+
* It runs inside the submission queue, so it submits directly rather than enqueueing, and gives
|
|
243438
|
+
* up after `timeoutMs` so a silent socket cannot hold the queue. A failure or timeout is logged
|
|
243439
|
+
* and left to the next stall.
|
|
243440
|
+
*/
|
|
243441
|
+
async fillNonceGap(keyPair, nonce, timeoutMs) {
|
|
243442
|
+
const fill = async () => {
|
|
243443
|
+
const accountNextIndex = this.api.rpc?.system?.accountNextIndex;
|
|
243444
|
+
if (!accountNextIndex) return;
|
|
243445
|
+
const missing = Number((await accountNextIndex(keyPair.address)).toString());
|
|
243446
|
+
if (!Number.isFinite(missing) || missing >= nonce) return;
|
|
243447
|
+
await this.api.tx.system.remark("0x").signAndSend(keyPair, { tip: 0n, nonce: missing });
|
|
243448
|
+
};
|
|
243449
|
+
try {
|
|
243450
|
+
await Promise.race([fill(), rejectAfter(timeoutMs, `Timed out after ${timeoutMs}ms`)]);
|
|
243451
|
+
} catch (err) {
|
|
243452
|
+
console.warn(`Could not fill the nonce gap below ${nonce}:`, err);
|
|
243453
|
+
}
|
|
243454
|
+
}
|
|
243455
|
+
/**
|
|
243456
|
+
* Sends an extrinsic with a timeout.
|
|
243457
|
+
*
|
|
243458
|
+
* A timeout is only a failure when the extrinsic never made it into the transaction pool.
|
|
243459
|
+
* Once a pool-entry status (Future/Ready/Broadcast/Retracted) has been seen, the extrinsic is
|
|
243460
|
+
* in flight and may well execute after the watch is abandoned — the result is then `pending`
|
|
243461
|
+
* and `stalled`, telling the caller to replace it under the same nonce or confirm it later,
|
|
243462
|
+
* never to re-sign the same call under a fresh one.
|
|
243463
|
+
*
|
|
243464
|
+
* `nonce` pins the submission to a specific account nonce, which is what makes a retry a pool
|
|
243465
|
+
* replacement rather than a second extrinsic queued behind the first. Left undefined on the
|
|
243466
|
+
* first attempt, where the api's auto-nonce is correct.
|
|
243467
|
+
*/
|
|
243343
243468
|
async sendWithTimeout(extrinsic, keyPair, tip, timeoutMs, nonce) {
|
|
243344
243469
|
return new Promise((resolve12) => {
|
|
243345
243470
|
let resolved = false;
|
|
243346
243471
|
let unsubscribe = null;
|
|
243347
243472
|
let enteredPool = false;
|
|
243473
|
+
let inFuture = false;
|
|
243348
243474
|
const timeoutId = setTimeout(() => {
|
|
243349
243475
|
if (!resolved) {
|
|
243350
243476
|
resolved = true;
|
|
@@ -243355,6 +243481,7 @@ Failed HTTP Request: ${JSON.stringify(
|
|
|
243355
243481
|
success: false,
|
|
243356
243482
|
pending: enteredPool || void 0,
|
|
243357
243483
|
stalled: enteredPool || void 0,
|
|
243484
|
+
future: enteredPool && inFuture || void 0,
|
|
243358
243485
|
extrinsicHash: enteredPool ? extrinsic.hash.toHex() : void 0,
|
|
243359
243486
|
error: `Transaction timed out after ${timeoutMs}ms${enteredPool ? " while in the transaction pool" : ""}`
|
|
243360
243487
|
});
|
|
@@ -243364,6 +243491,7 @@ Failed HTTP Request: ${JSON.stringify(
|
|
|
243364
243491
|
if (resolved) return;
|
|
243365
243492
|
if (result.status.isFuture || result.status.isReady || result.status.isBroadcast || result.status.isRetracted) {
|
|
243366
243493
|
enteredPool = true;
|
|
243494
|
+
inFuture = result.status.isFuture;
|
|
243367
243495
|
}
|
|
243368
243496
|
if (result.dispatchError && (result.status.isInBlock || result.status.isFinalized)) {
|
|
243369
243497
|
resolved = true;
|
|
@@ -246659,7 +246787,8 @@ query OrderStatus($commitment: String!) {
|
|
|
246659
246787
|
/** Alchemy (Rundler) method to fetch recommended priority fee for UserOperations. */
|
|
246660
246788
|
RUNDLER_MAX_PRIORITY_FEE_PER_GAS: "rundler_maxPriorityFeePerGas"
|
|
246661
246789
|
};
|
|
246662
|
-
SELECT_SOLVER_TYPEHASH = keccak2563(toHex3("SelectSolver(bytes32 commitment,
|
|
246790
|
+
SELECT_SOLVER_TYPEHASH = keccak2563(toHex3("SelectSolver(bytes32 commitment,bytes32 userOpHash)"));
|
|
246791
|
+
LEGACY_SELECT_SOLVER_TYPEHASH = keccak2563(toHex3("SelectSolver(bytes32 commitment,address solver)"));
|
|
246663
246792
|
PACKED_USEROP_TYPEHASH = keccak2563(
|
|
246664
246793
|
toHex3(
|
|
246665
246794
|
"PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)"
|
|
@@ -246698,29 +246827,50 @@ query OrderStatus($commitment: String!) {
|
|
|
246698
246827
|
);
|
|
246699
246828
|
}
|
|
246700
246829
|
/**
|
|
246701
|
-
* Signs
|
|
246830
|
+
* Signs `SelectSolver(bytes32 commitment,bytes32 userOpHash)` with the
|
|
246831
|
+
* order's session key, for gateways whose `SELECT_SOLVER_TYPEHASH` is
|
|
246832
|
+
* {@link SELECT_SOLVER_TYPEHASH}.
|
|
246702
246833
|
*
|
|
246703
|
-
* The
|
|
246704
|
-
*
|
|
246705
|
-
* solver's UserOperation signature before bundle submission.
|
|
246834
|
+
* The signature selects one bid UserOperation for the order and is appended
|
|
246835
|
+
* to that operation's signature before it is sent to the bundler.
|
|
246706
246836
|
*
|
|
246707
|
-
* @param commitment - The order commitment
|
|
246708
|
-
* @param
|
|
246709
|
-
* @param domainSeparator - EIP-712 domain separator
|
|
246710
|
-
* @param privateKey -
|
|
246711
|
-
* @returns The ECDSA signature
|
|
246837
|
+
* @param commitment - The order commitment.
|
|
246838
|
+
* @param userOpHash - EntryPoint userOpHash of the selected bid UserOperation.
|
|
246839
|
+
* @param domainSeparator - EIP-712 domain separator of the IntentGatewayV2 contract.
|
|
246840
|
+
* @param privateKey - Private key of the order's session key.
|
|
246841
|
+
* @returns The 65-byte ECDSA signature.
|
|
246712
246842
|
*/
|
|
246713
|
-
static async
|
|
246714
|
-
const
|
|
246843
|
+
static async signUserOpHashSelection(commitment, userOpHash, domainSeparator2, privateKey) {
|
|
246844
|
+
const structHash = keccak2563(
|
|
246845
|
+
encodeAbiParameters2(
|
|
246846
|
+
[{ type: "bytes32" }, { type: "bytes32" }, { type: "bytes32" }],
|
|
246847
|
+
[SELECT_SOLVER_TYPEHASH, commitment, userOpHash]
|
|
246848
|
+
)
|
|
246849
|
+
);
|
|
246850
|
+
return signTypedDigest(domainSeparator2, structHash, privateKey);
|
|
246851
|
+
}
|
|
246852
|
+
/**
|
|
246853
|
+
* Signs `SelectSolver(bytes32 commitment,address solver)` with the order's
|
|
246854
|
+
* session key, for gateways whose `SELECT_SOLVER_TYPEHASH` is
|
|
246855
|
+
* {@link LEGACY_SELECT_SOLVER_TYPEHASH}.
|
|
246856
|
+
*
|
|
246857
|
+
* The signature selects a solver account for the order and is appended to
|
|
246858
|
+
* that solver's bid UserOperation signature before it is sent to the bundler.
|
|
246859
|
+
*
|
|
246860
|
+
* @param commitment - The order commitment.
|
|
246861
|
+
* @param solverAddress - Address of the selected solver account.
|
|
246862
|
+
* @param domainSeparator - EIP-712 domain separator of the IntentGatewayV2 contract.
|
|
246863
|
+
* @param privateKey - Private key of the order's session key.
|
|
246864
|
+
* @returns The 65-byte ECDSA signature.
|
|
246865
|
+
*/
|
|
246866
|
+
static async signLegacySolverSelection(commitment, solverAddress, domainSeparator2, privateKey) {
|
|
246715
246867
|
const structHash = keccak2563(
|
|
246716
246868
|
encodeAbiParameters2(
|
|
246717
246869
|
[{ type: "bytes32" }, { type: "bytes32" }, { type: "address" }],
|
|
246718
|
-
[
|
|
246870
|
+
[LEGACY_SELECT_SOLVER_TYPEHASH, commitment, solverAddress]
|
|
246719
246871
|
)
|
|
246720
246872
|
);
|
|
246721
|
-
|
|
246722
|
-
const signature = await account5.sign({ hash: digest });
|
|
246723
|
-
return signature;
|
|
246873
|
+
return signTypedDigest(domainSeparator2, structHash, privateKey);
|
|
246724
246874
|
}
|
|
246725
246875
|
/**
|
|
246726
246876
|
* Computes the EIP-712 hash of a `PackedUserOperation` as defined by
|
|
@@ -247247,16 +247397,13 @@ query OrderStatus($commitment: String!) {
|
|
|
247247
247397
|
}
|
|
247248
247398
|
/**
|
|
247249
247399
|
* Creates a closure that computes the deduplication hash key for a
|
|
247250
|
-
* UserOperation, pre-bound to the
|
|
247400
|
+
* UserOperation, pre-bound to the destination chain.
|
|
247251
247401
|
*/
|
|
247252
|
-
createUserOpHasher(
|
|
247253
|
-
const entryPointAddress = this.ctx.dest.configService.getEntryPointV08Address(
|
|
247254
|
-
normalizeStateMachineId(order.destination)
|
|
247255
|
-
);
|
|
247402
|
+
createUserOpHasher() {
|
|
247256
247403
|
const chainId = BigInt(
|
|
247257
247404
|
this.ctx.dest.client.chain?.id ?? Number.parseInt(this.ctx.dest.config.stateMachineId.split("-")[1])
|
|
247258
247405
|
);
|
|
247259
|
-
return (userOp) => CryptoUtils.computeUserOpHash(userOp,
|
|
247406
|
+
return (userOp) => CryptoUtils.computeUserOpHash(userOp, ENTRY_POINT_V08, chainId);
|
|
247260
247407
|
}
|
|
247261
247408
|
/**
|
|
247262
247409
|
* Fetches bids from the coprocessor for a given order commitment.
|
|
@@ -247372,7 +247519,7 @@ query OrderStatus($commitment: String!) {
|
|
|
247372
247519
|
return;
|
|
247373
247520
|
}
|
|
247374
247521
|
const usedUserOps = await this.loadUsedUserOps(commitment);
|
|
247375
|
-
const userOpHashKey = this.createUserOpHasher(
|
|
247522
|
+
const userOpHashKey = this.createUserOpHasher();
|
|
247376
247523
|
const targetAssets = order.output.assets.map((a6) => ({ token: a6.token, amount: a6.amount }));
|
|
247377
247524
|
let initial;
|
|
247378
247525
|
try {
|
|
@@ -247568,9 +247715,17 @@ query OrderStatus($commitment: String!) {
|
|
|
247568
247715
|
* order. Frontends can use `relayerFee` to approve the ERC-20 spend before
|
|
247569
247716
|
* submitting the cancel transaction.
|
|
247570
247717
|
*
|
|
247718
|
+
* A cross-chain cancel is paid on the chain that receives the cancel
|
|
247719
|
+
* transaction: the source chain for the source route, the destination chain
|
|
247720
|
+
* for the destination route. When that chain is a testnet, the quote has no
|
|
247721
|
+
* native value, since testnet hosts have no router to swap it into the fee
|
|
247722
|
+
* token. The caller must first approve `relayerFee` of that host's fee token
|
|
247723
|
+
* to that chain's IntentGateway.
|
|
247724
|
+
*
|
|
247571
247725
|
* @param order - The order to quote.
|
|
247572
247726
|
* @param options - Choose the initiation side. Defaults to source-side cancellation.
|
|
247573
|
-
* @returns `{ nativeValue }` — native token amount (wei) to send as `value
|
|
247727
|
+
* @returns `{ nativeValue }` — native token amount (wei) to send as `value`,
|
|
247728
|
+
* or `0n` when the relayer fee must be paid in the fee token;
|
|
247574
247729
|
* `{ relayerFee }` — relayer incentive denominated in the chain's fee token.
|
|
247575
247730
|
*/
|
|
247576
247731
|
async quoteCancelOrder(order, options = {}) {
|
|
@@ -247584,11 +247739,12 @@ query OrderStatus($commitment: String!) {
|
|
|
247584
247739
|
*
|
|
247585
247740
|
* Constructs the ISMP GET request the source gateway will dispatch, one
|
|
247586
247741
|
* `_partialFills` key per leg, and calls `quoteNative` on the source host to
|
|
247587
|
-
* obtain the dispatch fee.
|
|
247742
|
+
* obtain the dispatch fee. Returns a zero `nativeValue` when the source is a
|
|
247743
|
+
* testnet chain, leaving the relayer fee to be paid in its fee token.
|
|
247588
247744
|
* Returns 0 for same-chain orders (no ISMP call needed).
|
|
247589
247745
|
*
|
|
247590
247746
|
* @param order - The order to quote.
|
|
247591
|
-
* @returns The native token dispatch fee in wei.
|
|
247747
|
+
* @returns The native token dispatch fee in wei and the relayer fee.
|
|
247592
247748
|
*/
|
|
247593
247749
|
async quoteCancelFromSource(order) {
|
|
247594
247750
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
@@ -247596,6 +247752,14 @@ query OrderStatus($commitment: String!) {
|
|
|
247596
247752
|
if (sourceStateMachine === destStateMachine) {
|
|
247597
247753
|
return { nativeValue: 0n, relayerFee: 0n };
|
|
247598
247754
|
}
|
|
247755
|
+
const feeInSourceFeeToken = await convertGasToFeeToken(
|
|
247756
|
+
this.ctx,
|
|
247757
|
+
_a6.SOURCE_GET_RESPONSE_GAS,
|
|
247758
|
+
"source",
|
|
247759
|
+
sourceStateMachine
|
|
247760
|
+
);
|
|
247761
|
+
const relayerFee = feeInSourceFeeToken * 1005n / 1000n;
|
|
247762
|
+
if (TESTNET_CHAINS.has(sourceStateMachine)) return { nativeValue: 0n, relayerFee };
|
|
247599
247763
|
const height = order.deadline + 1n;
|
|
247600
247764
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
247601
247765
|
const commitment = this.orderId(order);
|
|
@@ -247604,20 +247768,13 @@ query OrderStatus($commitment: String!) {
|
|
|
247604
247768
|
const getRequest = {
|
|
247605
247769
|
source: sourceStateMachine,
|
|
247606
247770
|
dest: destStateMachine,
|
|
247607
|
-
from: this.ctx.source.configService.getIntentGatewayAddress(
|
|
247771
|
+
from: this.ctx.source.configService.getIntentGatewayAddress(sourceStateMachine),
|
|
247608
247772
|
nonce: await this.ctx.source.getHostNonce(),
|
|
247609
247773
|
height,
|
|
247610
247774
|
keys: keys3,
|
|
247611
247775
|
timeoutTimestamp: 0n,
|
|
247612
247776
|
context
|
|
247613
247777
|
};
|
|
247614
|
-
const feeInSourceFeeToken = await convertGasToFeeToken(
|
|
247615
|
-
this.ctx,
|
|
247616
|
-
_a6.SOURCE_GET_RESPONSE_GAS,
|
|
247617
|
-
"source",
|
|
247618
|
-
sourceStateMachine
|
|
247619
|
-
);
|
|
247620
|
-
const relayerFee = feeInSourceFeeToken * 1005n / 1000n;
|
|
247621
247778
|
const nativeValue = await this.ctx.source.quoteNative(getRequest, relayerFee) * 101n / 100n;
|
|
247622
247779
|
return { nativeValue, relayerFee };
|
|
247623
247780
|
}
|
|
@@ -247638,7 +247795,10 @@ query OrderStatus($commitment: String!) {
|
|
|
247638
247795
|
* cancellation. Same-chain orders always use the direct local route.
|
|
247639
247796
|
* @yields {@link CancelEvent} objects describing each stage of the
|
|
247640
247797
|
* cancellation lifecycle. The caller signs or broadcasts the yielded
|
|
247641
|
-
* transaction,
|
|
247798
|
+
* transaction, and the gateway decides who may sign it. A same-chain cancel
|
|
247799
|
+
* or a cross-chain cancel from the destination accepts only `order.user`
|
|
247800
|
+
* through the deadline and any signer strictly after it. A cross-chain
|
|
247801
|
+
* cancel from the source accepts only `order.user`, before or after expiry.
|
|
247642
247802
|
*/
|
|
247643
247803
|
async *cancelOrder(order, indexerClient, options = {}) {
|
|
247644
247804
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
@@ -247858,11 +248018,13 @@ query OrderStatus($commitment: String!) {
|
|
|
247858
248018
|
*
|
|
247859
248019
|
* Estimates the relayer fee for delivering the refund POST request from the
|
|
247860
248020
|
* destination chain back to the source chain, converts it to the destination
|
|
247861
|
-
* fee token, and calls `quoteNative` on the destination host.
|
|
248021
|
+
* fee token, and calls `quoteNative` on the destination host. Returns a zero
|
|
248022
|
+
* `nativeValue` when the destination is a testnet chain, leaving the relayer
|
|
248023
|
+
* fee to be paid in its fee token.
|
|
247862
248024
|
* Returns 0 for same-chain orders.
|
|
247863
248025
|
*
|
|
247864
248026
|
* @param order - The order to quote.
|
|
247865
|
-
* @returns The native token dispatch fee in wei.
|
|
248027
|
+
* @returns The native token dispatch fee in wei and the relayer fee.
|
|
247866
248028
|
*/
|
|
247867
248029
|
async quoteCancelFromDest(order) {
|
|
247868
248030
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
@@ -247873,6 +248035,7 @@ query OrderStatus($commitment: String!) {
|
|
|
247873
248035
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
247874
248036
|
const sourceIntentGateway = this.ctx.source.configService.getIntentGatewayAddress(sourceStateMachine);
|
|
247875
248037
|
const relayerFee = await this.estimateRelayerFee(sourceStateMachine, destStateMachine);
|
|
248038
|
+
if (TESTNET_CHAINS.has(destStateMachine)) return { nativeValue: 0n, relayerFee };
|
|
247876
248039
|
const body = constructRefundEscrowRequestBody(order, order.user);
|
|
247877
248040
|
const postRequest = {
|
|
247878
248041
|
source: destStateMachine,
|
|
@@ -248220,7 +248383,8 @@ query OrderStatus($commitment: String!) {
|
|
|
248220
248383
|
}, __publicField(_a6, "DEFAULT_MAX_RECOVERY_RESTARTS", 1), __publicField(_a6, "PROOF_FRESHNESS_MAX_RETRIES", 3), __publicField(_a6, "PROOF_FRESHNESS_BACKOFF_MS", 500), /** Gas budgets used to price cancellation delivery on the source chain. */
|
|
248221
248384
|
__publicField(_a6, "SOURCE_GET_RESPONSE_GAS", 1000000n), __publicField(_a6, "REFUND_POST_GAS", 1000000n), _a6);
|
|
248222
248385
|
FILL_ORDER_SELECTOR = "0x68ddf058";
|
|
248223
|
-
SUPPORTED_INTENTS_VERSION =
|
|
248386
|
+
SUPPORTED_INTENTS_VERSION = 4n;
|
|
248387
|
+
TESTNET_INTENTS_VERSIONS = [3n, SUPPORTED_INTENTS_VERSION];
|
|
248224
248388
|
CONTRACT_VERSION_ABI = [
|
|
248225
248389
|
{
|
|
248226
248390
|
type: "function",
|
|
@@ -248231,6 +248395,13 @@ query OrderStatus($commitment: String!) {
|
|
|
248231
248395
|
}
|
|
248232
248396
|
];
|
|
248233
248397
|
CANONICAL_EVM_TOKEN = /^0x0{24}[0-9a-fA-F]{40}$/;
|
|
248398
|
+
formats = /* @__PURE__ */ new Map();
|
|
248399
|
+
SELECTION_PARAMS_SLOT = pad4(toHex3(5n), { size: 32 });
|
|
248400
|
+
SOLVER_SELECTION_CLEARED = maxUint2563 ^ 0xffn << 160n;
|
|
248401
|
+
SELECTION_FORMAT_BY_ENTRY_POINT = /* @__PURE__ */ new Map([
|
|
248402
|
+
[ENTRY_POINT_V09.toLowerCase(), "userOpHash"],
|
|
248403
|
+
[ENTRY_POINT_V08.toLowerCase(), "address"]
|
|
248404
|
+
]);
|
|
248234
248405
|
ENTRY_POINT_EVENT_ABI = [
|
|
248235
248406
|
{ type: "event", name: "BeforeExecution", inputs: [] },
|
|
248236
248407
|
{
|
|
@@ -248265,6 +248436,8 @@ query OrderStatus($commitment: String!) {
|
|
|
248265
248436
|
__publicField(this, "domainSeparator");
|
|
248266
248437
|
/** Cached session-key signature over the `SelectSolver` message. */
|
|
248267
248438
|
__publicField(this, "cachedSignature");
|
|
248439
|
+
/** Cached result of {@link route}. */
|
|
248440
|
+
__publicField(this, "cachedRoute");
|
|
248268
248441
|
this.ctx = params.ctx;
|
|
248269
248442
|
this.crypto = params.crypto;
|
|
248270
248443
|
this.order = params.order;
|
|
@@ -248294,69 +248467,117 @@ query OrderStatus($commitment: String!) {
|
|
|
248294
248467
|
);
|
|
248295
248468
|
}
|
|
248296
248469
|
/**
|
|
248297
|
-
*
|
|
248298
|
-
*
|
|
248470
|
+
* Finds the EntryPoint this bid's solver signed it for and checks that the
|
|
248471
|
+
* destination gateway's selection format pairs with it, reading the format
|
|
248472
|
+
* again before refusing a bid in case the gateway was upgraded since it was
|
|
248473
|
+
* cached. Caches the result.
|
|
248474
|
+
*
|
|
248475
|
+
* @throws If the solver's signature recovers under no known EntryPoint, the
|
|
248476
|
+
* EntryPoint does not pair with the gateway's selection format, or the
|
|
248477
|
+
* format cannot be read.
|
|
248478
|
+
*/
|
|
248479
|
+
async route() {
|
|
248480
|
+
if (this.cachedRoute) return this.cachedRoute;
|
|
248481
|
+
const chainId = this.chainId();
|
|
248482
|
+
let signed;
|
|
248483
|
+
for (const entryPoint of KNOWN_ENTRY_POINTS) {
|
|
248484
|
+
const userOpHash = CryptoUtils.computeUserOpHash(this.userOp, entryPoint, chainId);
|
|
248485
|
+
if (await this.signedBySolver(userOpHash)) {
|
|
248486
|
+
signed = { entryPoint, userOpHash };
|
|
248487
|
+
break;
|
|
248488
|
+
}
|
|
248489
|
+
}
|
|
248490
|
+
if (!signed) {
|
|
248491
|
+
throw new Error(`Bid from solver=${this.solverAddress} is not signed for a known EntryPoint`);
|
|
248492
|
+
}
|
|
248493
|
+
const pairsWith = SELECTION_FORMAT_BY_ENTRY_POINT.get(signed.entryPoint.toLowerCase());
|
|
248494
|
+
const cached = readSelectionFormat(this.ctx.dest.client, chainId, this.intentGatewayV2Address);
|
|
248495
|
+
let format2 = await cached;
|
|
248496
|
+
if (pairsWith !== format2) {
|
|
248497
|
+
format2 = await refreshSelectionFormat(this.ctx.dest.client, chainId, this.intentGatewayV2Address, cached);
|
|
248498
|
+
}
|
|
248499
|
+
if (pairsWith !== format2) {
|
|
248500
|
+
throw new Error(
|
|
248501
|
+
`Bid from solver=${this.solverAddress} is signed for EntryPoint ${signed.entryPoint}, which the destination gateway's ${format2} selection does not pair with`
|
|
248502
|
+
);
|
|
248503
|
+
}
|
|
248504
|
+
this.cachedRoute = { ...signed, format: format2 };
|
|
248505
|
+
return this.cachedRoute;
|
|
248506
|
+
}
|
|
248507
|
+
/**
|
|
248508
|
+
* Whether the solver's signature in the bid, `signature[32:97]` after the order
|
|
248509
|
+
* commitment, recovers to the solver over `userOpHash`.
|
|
248510
|
+
*/
|
|
248511
|
+
async signedBySolver(userOpHash) {
|
|
248512
|
+
try {
|
|
248513
|
+
const recovered = await recoverAddress3({
|
|
248514
|
+
hash: userOpHash,
|
|
248515
|
+
signature: slice4(this.userOp.signature, 32, 97)
|
|
248516
|
+
});
|
|
248517
|
+
return recovered.toLowerCase() === this.solverAddress.toLowerCase();
|
|
248518
|
+
} catch {
|
|
248519
|
+
return false;
|
|
248520
|
+
}
|
|
248521
|
+
}
|
|
248522
|
+
/**
|
|
248523
|
+
* Resolves the session key, signs the `SelectSolver` message for this bid in
|
|
248524
|
+
* the destination gateway's selection format, and caches the signature. Signs
|
|
248525
|
+
* at most once per bid.
|
|
248299
248526
|
*
|
|
248300
|
-
* @throws If the session key is missing
|
|
248527
|
+
* @throws If the bid cannot be routed, or the session key is missing.
|
|
248301
248528
|
*/
|
|
248302
248529
|
async signSelection() {
|
|
248303
248530
|
if (this.cachedSignature) return this.cachedSignature;
|
|
248531
|
+
const { format: format2, userOpHash } = await this.route();
|
|
248304
248532
|
const commitment = this.order.id;
|
|
248305
248533
|
const sessionKeyAddress = this.order.session;
|
|
248306
248534
|
const sessionKeyData = this.sessionPrivateKey ? { privateKey: this.sessionPrivateKey } : await this.ctx.sessionKeyStorage.getSessionKeyByAddress(sessionKeyAddress);
|
|
248307
248535
|
if (!sessionKeyData) {
|
|
248308
248536
|
throw new Error(`SessionKey not found for commitment: ${commitment}`);
|
|
248309
248537
|
}
|
|
248310
|
-
|
|
248538
|
+
this.cachedSignature = format2 === "userOpHash" ? await CryptoUtils.signUserOpHashSelection(
|
|
248539
|
+
commitment,
|
|
248540
|
+
userOpHash,
|
|
248541
|
+
this.domainSeparator,
|
|
248542
|
+
sessionKeyData.privateKey
|
|
248543
|
+
) : await CryptoUtils.signLegacySolverSelection(
|
|
248311
248544
|
commitment,
|
|
248312
248545
|
this.solverAddress,
|
|
248313
248546
|
this.domainSeparator,
|
|
248314
248547
|
sessionKeyData.privateKey
|
|
248315
248548
|
);
|
|
248316
|
-
|
|
248317
|
-
throw new Error("Failed to sign solver selection");
|
|
248318
|
-
}
|
|
248319
|
-
this.cachedSignature = signature;
|
|
248320
|
-
return signature;
|
|
248549
|
+
return this.cachedSignature;
|
|
248321
248550
|
}
|
|
248322
248551
|
/**
|
|
248323
|
-
* Simulates this bid on-chain
|
|
248324
|
-
*
|
|
248325
|
-
*
|
|
248552
|
+
* Simulates this bid on-chain with an `eth_call` of its calldata from the
|
|
248553
|
+
* solver's account, after checking that the bid can be routed.
|
|
248554
|
+
*
|
|
248555
|
+
* The gateway's solver selection is turned off for the call with
|
|
248556
|
+
* {@link selectionOffStateDiff} and no `select` is made: a gateway that selects
|
|
248557
|
+
* by userOpHash checks the selection against the EntryPoint's current
|
|
248558
|
+
* operation, which only exists inside a bundle. The session's selection is
|
|
248559
|
+
* therefore not part of the simulation.
|
|
248326
248560
|
*
|
|
248327
248561
|
* The native value forwarded to the simulation is the sum of any native-token
|
|
248328
248562
|
* (`address(0)`) output amounts plus the Hyperbridge dispatch fee.
|
|
248329
248563
|
*
|
|
248330
|
-
* @throws If the `eth_call` simulation reverts or errors.
|
|
248564
|
+
* @throws If the bid cannot be routed, or the `eth_call` simulation reverts or errors.
|
|
248331
248565
|
*/
|
|
248332
248566
|
async simulate() {
|
|
248333
|
-
|
|
248334
|
-
const selectOptions = {
|
|
248335
|
-
commitment: this.order.id,
|
|
248336
|
-
solver: this.solverAddress,
|
|
248337
|
-
signature
|
|
248338
|
-
};
|
|
248567
|
+
await this.route();
|
|
248339
248568
|
const nativeOutputs = this.fillOptions.outputs.reduce(
|
|
248340
248569
|
(acc, o6) => bytes32ToBytes20(o6.token) === ADDRESS_ZERO2 ? acc + o6.amount : acc,
|
|
248341
248570
|
0n
|
|
248342
248571
|
);
|
|
248343
248572
|
const simulationValue = nativeOutputs + this.fillOptions.nativeDispatchFee;
|
|
248344
|
-
const selectCalldata = encodeFunctionData2({
|
|
248345
|
-
abi: ABI3,
|
|
248346
|
-
functionName: "select",
|
|
248347
|
-
args: [selectOptions]
|
|
248348
|
-
});
|
|
248349
|
-
const calls = [
|
|
248350
|
-
{ target: this.intentGatewayV2Address, value: 0n, data: selectCalldata },
|
|
248351
|
-
{ target: this.solverAddress, value: simulationValue, data: this.userOp.callData }
|
|
248352
|
-
];
|
|
248353
|
-
const batchedCalldata = this.crypto.encodeERC7821Execute(calls);
|
|
248354
248573
|
try {
|
|
248574
|
+
const selectionOff = await selectionOffStateDiff(this.ctx.dest.client, this.intentGatewayV2Address);
|
|
248355
248575
|
await this.ctx.dest.client.call({
|
|
248356
248576
|
account: this.solverAddress,
|
|
248357
248577
|
to: this.solverAddress,
|
|
248358
|
-
data:
|
|
248359
|
-
value: simulationValue
|
|
248578
|
+
data: this.userOp.callData,
|
|
248579
|
+
value: simulationValue,
|
|
248580
|
+
stateOverride: [{ address: this.intentGatewayV2Address, stateDiff: [selectionOff] }]
|
|
248360
248581
|
});
|
|
248361
248582
|
} catch (e4) {
|
|
248362
248583
|
throw new Error(`Simulation failed: ${e4 instanceof Error ? e4.message : String(e4)}`);
|
|
@@ -248365,31 +248586,29 @@ query OrderStatus($commitment: String!) {
|
|
|
248365
248586
|
/**
|
|
248366
248587
|
* Signs the `SelectSolver` message with the session key, appends it to the
|
|
248367
248588
|
* solver's existing UserOp signature, and submits the UserOperation to the
|
|
248368
|
-
* bundler. Waits for the receipt and
|
|
248369
|
-
* logs to determine fill status.
|
|
248589
|
+
* bundler on the EntryPoint the bid was signed for. Waits for the receipt and
|
|
248590
|
+
* reads `OrderFilled` / `PartialFill` logs to determine fill status.
|
|
248370
248591
|
*
|
|
248371
248592
|
* @returns A {@link SelectBidResult} with the submitted UserOperation, its hash,
|
|
248372
248593
|
* the solver address, transaction hash, and fill status.
|
|
248373
|
-
* @throws If the bundler is not configured, the
|
|
248374
|
-
* bundler rejects the UserOperation.
|
|
248594
|
+
* @throws If the bundler is not configured, the bid cannot be routed, the
|
|
248595
|
+
* session key is missing, or the bundler rejects the UserOperation.
|
|
248375
248596
|
*/
|
|
248376
248597
|
async execute() {
|
|
248377
248598
|
const commitment = this.order.id;
|
|
248378
248599
|
if (!this.ctx.bundlerUrl) {
|
|
248379
248600
|
throw new Error("Bundler URL not configured");
|
|
248380
248601
|
}
|
|
248602
|
+
const { entryPoint } = await this.route();
|
|
248381
248603
|
const sessionSignature = await this.signSelection();
|
|
248382
248604
|
const finalSignature = concat3([this.userOp.signature, sessionSignature]);
|
|
248383
248605
|
const signedUserOp = {
|
|
248384
248606
|
...this.userOp,
|
|
248385
248607
|
signature: finalSignature
|
|
248386
248608
|
};
|
|
248387
|
-
const entryPointAddress = this.ctx.dest.configService.getEntryPointV08Address(
|
|
248388
|
-
normalizeStateMachineId(this.order.destination)
|
|
248389
|
-
);
|
|
248390
248609
|
const userOpHash = await this.crypto.sendBundler(BundlerMethod.ETH_SEND_USER_OPERATION, [
|
|
248391
248610
|
CryptoUtils.prepareBundlerCall(signedUserOp),
|
|
248392
|
-
|
|
248611
|
+
entryPoint
|
|
248393
248612
|
]);
|
|
248394
248613
|
let txnHash;
|
|
248395
248614
|
let fillStatus;
|
|
@@ -248415,7 +248634,7 @@ query OrderStatus($commitment: String!) {
|
|
|
248415
248634
|
);
|
|
248416
248635
|
const fills = parseEventLogs2({
|
|
248417
248636
|
abi: ABI3,
|
|
248418
|
-
logs: userOperationLogs(chainReceipt.logs,
|
|
248637
|
+
logs: userOperationLogs(chainReceipt.logs, entryPoint, userOpHash),
|
|
248419
248638
|
eventName: ["OrderFilled", "PartialFill"]
|
|
248420
248639
|
}).filter(
|
|
248421
248640
|
(event) => event.address.toLowerCase() === gateway.toLowerCase() && event.args.commitment.toLowerCase() === commitment.toLowerCase()
|
|
@@ -248467,12 +248686,15 @@ query OrderStatus($commitment: String!) {
|
|
|
248467
248686
|
* Constructs a signed `PackedUserOperation` that a solver can submit to the
|
|
248468
248687
|
* Hyperbridge coprocessor as a bid to fill an order.
|
|
248469
248688
|
*
|
|
248470
|
-
* The solver signs the operation as
|
|
248471
|
-
* whose digest is
|
|
248472
|
-
* the
|
|
248473
|
-
*
|
|
248474
|
-
*
|
|
248475
|
-
*
|
|
248689
|
+
* The solver signs the operation as EIP-712 typed data for
|
|
248690
|
+
* `entryPointAddress`, whose digest is that EntryPoint's userOpHash. It must
|
|
248691
|
+
* be the EntryPoint the solver's `SolverAccount` accepts: the user's SDK
|
|
248692
|
+
* recovers it from this signature and executes the bid there. The binding
|
|
248693
|
+
* to the order lives in the operation itself: the 4337 nonce key must derive
|
|
248694
|
+
* from the order commitment, the session key and the calldata
|
|
248695
|
+
* (`SolverAccount` enforces this during validation), and the callData
|
|
248696
|
+
* carries the order. This keeps the signed payload fully transparent to
|
|
248697
|
+
* signing infrastructure instead of an opaque digest.
|
|
248476
248698
|
*
|
|
248477
248699
|
* @param options - Parameters describing the solver account, gas limits, fee
|
|
248478
248700
|
* market values, and pre-built `callData` for the fill operation.
|
|
@@ -248505,7 +248727,7 @@ query OrderStatus($commitment: String!) {
|
|
|
248505
248727
|
}
|
|
248506
248728
|
const chain2 = normalizeStateMachineId(order.destination);
|
|
248507
248729
|
const gateway = this.ctx.dest.configService.getIntentGatewayAddress(chain2);
|
|
248508
|
-
if (!await supportsRateFills(this.ctx.dest.client, gateway)) {
|
|
248730
|
+
if (!await supportsRateFills(this.ctx.dest.client, gateway, chain2)) {
|
|
248509
248731
|
throw new Error("Fills are not supported by the destination gateway");
|
|
248510
248732
|
}
|
|
248511
248733
|
const chainId = BigInt(
|
|
@@ -248545,6 +248767,11 @@ query OrderStatus($commitment: String!) {
|
|
|
248545
248767
|
* silently dropped with a warning. The returned `Bid` instances are ready to
|
|
248546
248768
|
* be ranked, simulated, and executed by the consumer.
|
|
248547
248769
|
*
|
|
248770
|
+
* A bid signed for no known EntryPoint, or for one the destination gateway's
|
|
248771
|
+
* selection format does not pair with, is kept here and fails
|
|
248772
|
+
* {@link Bid.simulate} and {@link Bid.execute}, so {@link selectAndExecuteBest}
|
|
248773
|
+
* skips it.
|
|
248774
|
+
*
|
|
248548
248775
|
* @param order - The placed order the bids are competing to fill.
|
|
248549
248776
|
* @param bids - Raw filler bids fetched from the coprocessor.
|
|
248550
248777
|
* @param sessionPrivateKey - Optional session-key override; looked up from
|
|
@@ -248837,12 +249064,15 @@ query OrderStatus($commitment: String!) {
|
|
|
248837
249064
|
}
|
|
248838
249065
|
}
|
|
248839
249066
|
};
|
|
249067
|
+
UNSUPPORTED_REQUEST_CODES = /* @__PURE__ */ new Set([-32600, -32601, -32602]);
|
|
249068
|
+
bundlersWithoutRundlerFees = /* @__PURE__ */ new Set();
|
|
248840
249069
|
RELAYER_MESSAGE_GAS = 1000000n;
|
|
248841
249070
|
NO_BUNDLER_FILL_GAS_BASE = 700000n;
|
|
248842
249071
|
NO_BUNDLER_FILL_GAS_PER_OUTPUT = 150000n;
|
|
248843
249072
|
NO_BUNDLER_PAYMASTER_VERIFICATION_GAS = 250000n;
|
|
248844
249073
|
NO_BUNDLER_PAYMASTER_POST_OP_GAS = 100000n;
|
|
248845
249074
|
BID_PVG_ESTIMATION_ACCOUNT_CODE = "0x60003560e01c631626ba7e1460145760206000f35b631626ba7e60e01b60005260206000f3";
|
|
249075
|
+
BID_PVG_ESTIMATION_PAYMASTER_CODE = "0x604060005260606000f3";
|
|
248846
249076
|
SELECTED_BID_SIGNATURE_BYTES = 32 + 65 + 65;
|
|
248847
249077
|
BID_PVG_HEADROOM_PERCENT = 10n;
|
|
248848
249078
|
ESCROW_MAPPING_SLOT = 9n;
|
|
@@ -248856,8 +249086,6 @@ query OrderStatus($commitment: String!) {
|
|
|
248856
249086
|
constructor(ctx, crypto10) {
|
|
248857
249087
|
__publicField(this, "ctx");
|
|
248858
249088
|
__publicField(this, "crypto");
|
|
248859
|
-
/** Call dispatchers read from a gateway, for chains whose config carries none. */
|
|
248860
|
-
__publicField(this, "dispatchers", /* @__PURE__ */ new Map());
|
|
248861
249089
|
this.ctx = ctx;
|
|
248862
249090
|
this.crypto = crypto10;
|
|
248863
249091
|
}
|
|
@@ -248879,7 +249107,10 @@ query OrderStatus($commitment: String!) {
|
|
|
248879
249107
|
* ephemeral keypair, applies state overrides, and calls
|
|
248880
249108
|
* `eth_estimateUserOperationGas`. Gas limits are bumped by 5-10% for
|
|
248881
249109
|
* headroom. If the bundler is Pimlico, gas prices are refined with
|
|
248882
|
-
* `pimlico_getUserOperationGasPrice
|
|
249110
|
+
* `pimlico_getUserOperationGasPrice`, and if it is Alchemy, with
|
|
249111
|
+
* `rundler_maxPriorityFeePerGas`. For any other bundler that answers
|
|
249112
|
+
* `rundler_maxPriorityFeePerGas`, the fees are raised to at least that
|
|
249113
|
+
* priority fee (see {@link applyRundlerPriorityFee}). If the bundler rejects the estimate,
|
|
248883
249114
|
* fixed gas limits are returned in its place, or the call throws when
|
|
248884
249115
|
* `params.requireBundlerEstimate` is set.
|
|
248885
249116
|
*
|
|
@@ -248914,7 +249145,7 @@ query OrderStatus($commitment: String!) {
|
|
|
248914
249145
|
const souceStateMachineId = isHex3(order.source) ? hexToString2(order.source) : order.source;
|
|
248915
249146
|
const destStateMachineId = isHex3(order.destination) ? hexToString2(order.destination) : order.destination;
|
|
248916
249147
|
const intentGatewayV2Address = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachineId);
|
|
248917
|
-
const entryPointAddress = this.ctx.dest.configService.
|
|
249148
|
+
const entryPointAddress = this.ctx.dest.configService.getEntryPointAddress(destStateMachineId);
|
|
248918
249149
|
const chainId = BigInt(Number.parseInt(destStateMachineId.split("-")[1]));
|
|
248919
249150
|
const totalEthValue = quotedOutputs.filter((output3) => bytes32ToBytes20(output3.token) === ADDRESS_ZERO2).reduce((sum2, output3) => sum2 + output3.amount, 0n);
|
|
248920
249151
|
const [sourceFeeToken, destFeeToken, gasPrice, latestBlock] = await Promise.all([
|
|
@@ -248976,7 +249207,7 @@ query OrderStatus($commitment: String!) {
|
|
|
248976
249207
|
const maxFeeBumpPercent = params.maxFeePerGasBumpPercent ?? 10;
|
|
248977
249208
|
let maxPriorityFeePerGas = gasPrice + gasPrice * BigInt(priorityFeeBumpPercent) / 100n;
|
|
248978
249209
|
let maxFeePerGas = gasPrice + gasPrice * BigInt(maxFeeBumpPercent) / 100n;
|
|
248979
|
-
await assertGatewayRelease(this.ctx.dest.client, intentGatewayV2Address);
|
|
249210
|
+
await assertGatewayRelease(this.ctx.dest.client, intentGatewayV2Address, destStateMachineId);
|
|
248980
249211
|
const fillOrderCalldata = encodeFillOrder(transformOrderForContract(order), fillOptions);
|
|
248981
249212
|
let callGasLimit = 500000n;
|
|
248982
249213
|
let verificationGasLimit = 100000n;
|
|
@@ -248985,6 +249216,7 @@ query OrderStatus($commitment: String!) {
|
|
|
248985
249216
|
let paymasterPostOpGasLimit = 0n;
|
|
248986
249217
|
if (this.ctx.bundlerUrl) {
|
|
248987
249218
|
try {
|
|
249219
|
+
if (!entryPointAddress) throw new Error(`No EntryPoint configured for ${destStateMachineId}`);
|
|
248988
249220
|
const callData = this.crypto.encodeERC7821Execute([
|
|
248989
249221
|
...params.prependCalls ?? [],
|
|
248990
249222
|
{ target: intentGatewayV2Address, value: totalNativeValue, data: fillOrderCalldata }
|
|
@@ -249017,7 +249249,13 @@ query OrderStatus($commitment: String!) {
|
|
|
249017
249249
|
chainId,
|
|
249018
249250
|
intentGatewayV2Address
|
|
249019
249251
|
);
|
|
249020
|
-
const
|
|
249252
|
+
const selectionFormat = await readSelectionFormat(this.ctx.dest.client, chainId, intentGatewayV2Address);
|
|
249253
|
+
const sessionSignature = selectionFormat === "userOpHash" ? await CryptoUtils.signUserOpHashSelection(
|
|
249254
|
+
commitment,
|
|
249255
|
+
userOpHash,
|
|
249256
|
+
domainSeparator2,
|
|
249257
|
+
solverPrivateKey
|
|
249258
|
+
) : await CryptoUtils.signLegacySolverSelection(
|
|
249021
249259
|
commitment,
|
|
249022
249260
|
solverAccountAddress,
|
|
249023
249261
|
domainSeparator2,
|
|
@@ -249031,6 +249269,7 @@ query OrderStatus($commitment: String!) {
|
|
|
249031
249269
|
const bundlerUrlLower = this.ctx.bundlerUrl.toLowerCase();
|
|
249032
249270
|
const isPimlico = bundlerUrlLower.includes("pimlico.io");
|
|
249033
249271
|
const isAlchemy = bundlerUrlLower.includes("alchemy.com");
|
|
249272
|
+
const rundlerPriorityFeeRequest = isPimlico || isAlchemy ? Promise.resolve(null) : fetchRundlerPriorityFee(this.ctx.bundlerUrl);
|
|
249034
249273
|
const bundlerRequests = [
|
|
249035
249274
|
{
|
|
249036
249275
|
method: BundlerMethod.ETH_ESTIMATE_USER_OPERATION_GAS,
|
|
@@ -249086,13 +249325,27 @@ query OrderStatus($commitment: String!) {
|
|
|
249086
249325
|
}
|
|
249087
249326
|
}
|
|
249088
249327
|
if (alchemyMaxPriorityFee) {
|
|
249089
|
-
const
|
|
249328
|
+
const rundlerPriorityFee2 = BigInt(alchemyMaxPriorityFee);
|
|
249090
249329
|
const isArbitrum = chainId === 42161n;
|
|
249091
249330
|
const alchemyPrioBump = isArbitrum ? 0n : 25n;
|
|
249092
|
-
maxPriorityFeePerGas =
|
|
249331
|
+
maxPriorityFeePerGas = rundlerPriorityFee2 + rundlerPriorityFee2 * alchemyPrioBump / 100n;
|
|
249093
249332
|
const bufferedBaseFee = baseFeePerGas + baseFeePerGas * 50n / 100n;
|
|
249094
249333
|
maxFeePerGas = bufferedBaseFee + maxPriorityFeePerGas;
|
|
249095
249334
|
}
|
|
249335
|
+
const rundlerPriorityFee = await rundlerPriorityFeeRequest;
|
|
249336
|
+
if (rundlerPriorityFee !== null) {
|
|
249337
|
+
const rundlerFees = applyRundlerPriorityFee(
|
|
249338
|
+
{ maxFeePerGas, maxPriorityFeePerGas },
|
|
249339
|
+
{
|
|
249340
|
+
rundlerPriorityFee,
|
|
249341
|
+
baseFeePerGas,
|
|
249342
|
+
priorityFeeBumpPercent: BigInt(priorityFeeBumpPercent),
|
|
249343
|
+
maxFeeBumpPercent: BigInt(maxFeeBumpPercent)
|
|
249344
|
+
}
|
|
249345
|
+
);
|
|
249346
|
+
maxFeePerGas = rundlerFees.maxFeePerGas;
|
|
249347
|
+
maxPriorityFeePerGas = rundlerFees.maxPriorityFeePerGas;
|
|
249348
|
+
}
|
|
249096
249349
|
} catch (e4) {
|
|
249097
249350
|
if (params.requireBundlerEstimate) {
|
|
249098
249351
|
throw new Error(`Bundler gas estimation failed: ${e4 instanceof Error ? e4.message : String(e4)}`, {
|
|
@@ -249133,27 +249386,6 @@ query OrderStatus($commitment: String!) {
|
|
|
249133
249386
|
inputs
|
|
249134
249387
|
};
|
|
249135
249388
|
}
|
|
249136
|
-
/**
|
|
249137
|
-
* The call dispatcher the gateway on `chain` uses: the configured address, or the one
|
|
249138
|
-
* the gateway reports when the chain's config carries none.
|
|
249139
|
-
*
|
|
249140
|
-
* {@link buildStateOverride} writes it back into the gateway's params slot. Without an
|
|
249141
|
-
* address that value is 12 bytes instead of 32, and the bundler rejects the whole
|
|
249142
|
-
* estimate as `Invalid params`.
|
|
249143
|
-
*/
|
|
249144
|
-
async callDispatcher(chain2, gateway) {
|
|
249145
|
-
const configured = this.ctx.dest.configService.getCalldispatcherAddress(chain2);
|
|
249146
|
-
if (isAddress2(configured)) return configured;
|
|
249147
|
-
const known3 = this.dispatchers.get(chain2);
|
|
249148
|
-
if (known3) return known3;
|
|
249149
|
-
const params = await this.ctx.dest.client.readContract({
|
|
249150
|
-
abi: ABI3,
|
|
249151
|
-
address: gateway,
|
|
249152
|
-
functionName: "params"
|
|
249153
|
-
});
|
|
249154
|
-
this.dispatchers.set(chain2, params.dispatcher);
|
|
249155
|
-
return params.dispatcher;
|
|
249156
|
-
}
|
|
249157
249389
|
/**
|
|
249158
249390
|
* Asks the bundler for the `preVerificationGas` of the bid UserOperation that will
|
|
249159
249391
|
* actually be signed, with every funding call, approval and signature byte in it.
|
|
@@ -249167,7 +249399,9 @@ query OrderStatus($commitment: String!) {
|
|
|
249167
249399
|
* `maxFeePerGas`.
|
|
249168
249400
|
*
|
|
249169
249401
|
* The solver account's code is overridden with {@link BID_PVG_ESTIMATION_ACCOUNT_CODE}
|
|
249170
|
-
*
|
|
249402
|
+
* and the paymaster's, if the bid has one, with {@link BID_PVG_ESTIMATION_PAYMASTER_CODE}
|
|
249403
|
+
* for the call, so only the bytes are priced and neither the fill nor the paymaster's
|
|
249404
|
+
* validation is simulated.
|
|
249171
249405
|
*
|
|
249172
249406
|
* @param params - The bid's fields as they will be signed.
|
|
249173
249407
|
* @returns The `preVerificationGas` to sign, with {@link BID_PVG_HEADROOM_PERCENT} added.
|
|
@@ -249191,13 +249425,15 @@ query OrderStatus($commitment: String!) {
|
|
|
249191
249425
|
paymasterAndData: params.paymasterAndData ?? "0x",
|
|
249192
249426
|
signature: `0x${"ff".repeat(SELECTED_BID_SIGNATURE_BYTES)}`
|
|
249193
249427
|
};
|
|
249428
|
+
const stateOverride = {
|
|
249429
|
+
[solverAccount]: { code: BID_PVG_ESTIMATION_ACCOUNT_CODE }
|
|
249430
|
+
};
|
|
249431
|
+
if (userOp.paymasterAndData.length >= 42) {
|
|
249432
|
+
stateOverride[userOp.paymasterAndData.slice(0, 42)] = { code: BID_PVG_ESTIMATION_PAYMASTER_CODE };
|
|
249433
|
+
}
|
|
249194
249434
|
const estimate = await this.crypto.sendBundler(
|
|
249195
249435
|
BundlerMethod.ETH_ESTIMATE_USER_OPERATION_GAS,
|
|
249196
|
-
[
|
|
249197
|
-
CryptoUtils.prepareBundlerCall(userOp),
|
|
249198
|
-
params.entryPointAddress,
|
|
249199
|
-
{ [solverAccount]: { code: BID_PVG_ESTIMATION_ACCOUNT_CODE } }
|
|
249200
|
-
]
|
|
249436
|
+
[CryptoUtils.prepareBundlerCall(userOp), params.entryPointAddress, stateOverride]
|
|
249201
249437
|
);
|
|
249202
249438
|
return BigInt(estimate.preVerificationGas) * (100n + BID_PVG_HEADROOM_PERCENT) / 100n;
|
|
249203
249439
|
}
|
|
@@ -249245,9 +249481,8 @@ query OrderStatus($commitment: String!) {
|
|
|
249245
249481
|
* slots should be overridden.
|
|
249246
249482
|
* @param params.spenderAddress - Address that needs allowance from the solver
|
|
249247
249483
|
* account (i.e. the IntentGatewayV2 contract).
|
|
249248
|
-
* @param params.intentGatewayV2Address - If provided,
|
|
249249
|
-
*
|
|
249250
|
-
* succeed during estimation.
|
|
249484
|
+
* @param params.intentGatewayV2Address - If provided, turns the gateway's
|
|
249485
|
+
* solver selection off with {@link selectionOffStateDiff}.
|
|
249251
249486
|
* @param params.entryPointAddress - If provided, overrides the EntryPoint
|
|
249252
249487
|
* deposit mapping to give the solver account a large deposit.
|
|
249253
249488
|
* @returns An object with `viem` and `bundler` state-override collections.
|
|
@@ -249266,10 +249501,7 @@ query OrderStatus($commitment: String!) {
|
|
|
249266
249501
|
const viemOverrides = [];
|
|
249267
249502
|
const bundlerOverrides = {};
|
|
249268
249503
|
if (intentGatewayV2Address) {
|
|
249269
|
-
const
|
|
249270
|
-
const dispatcherAddress = await this.callDispatcher(chain2, intentGatewayV2Address);
|
|
249271
|
-
const newSlot5Value = "0x" + "0".repeat(22) + "00" + dispatcherAddress.slice(2).toLowerCase();
|
|
249272
|
-
const gatewayDiffs = [{ slot: paramsSlot5, value: newSlot5Value }];
|
|
249504
|
+
const gatewayDiffs = [await selectionOffStateDiff(this.ctx.dest.client, intentGatewayV2Address)];
|
|
249273
249505
|
for (const [leg, input] of (escrow?.inputs ?? []).entries()) {
|
|
249274
249506
|
gatewayDiffs.push({
|
|
249275
249507
|
slot: escrowSlot(escrow.commitment, leg),
|
|
@@ -250232,6 +250464,8 @@ query QuotePessimistic($route: RouteInput!, $amountIn: BigInt!) {
|
|
|
250232
250464
|
* order. Use `relayerFee` to approve the ERC-20 spend before submitting.
|
|
250233
250465
|
* Same-chain orders use the direct local route for either `from` option and
|
|
250234
250466
|
* return `{ nativeValue: 0n, relayerFee: 0n }`.
|
|
250467
|
+
* When the chain receiving the cancel transaction is a testnet, `nativeValue` is `0n` and the caller
|
|
250468
|
+
* approves `relayerFee` of that host's fee token to that chain's gateway.
|
|
250235
250469
|
*
|
|
250236
250470
|
* Delegates to {@link OrderCanceller.quoteCancelOrder}.
|
|
250237
250471
|
*
|
|
@@ -250928,7 +251162,7 @@ var init_FillerConfigService = __esm({
|
|
|
250928
251162
|
return this.fillerConfig?.substratePrivateKey;
|
|
250929
251163
|
}
|
|
250930
251164
|
getEntryPointAddress(chain2) {
|
|
250931
|
-
return this.chainConfigService.
|
|
251165
|
+
return this.chainConfigService.getEntryPointAddress(chain2);
|
|
250932
251166
|
}
|
|
250933
251167
|
getSolverAccountContractAddress(chain2) {
|
|
250934
251168
|
return this.chainConfigService.getSolverAccountAddress(chain2);
|
|
@@ -251380,7 +251614,7 @@ function chainByChainId(chainId) {
|
|
|
251380
251614
|
function chainByAlchemySubdomain(subdomain) {
|
|
251381
251615
|
return INIT_CHAINS.find((chain2) => chain2.alchemySubdomain === subdomain);
|
|
251382
251616
|
}
|
|
251383
|
-
var FREE_RPC_URLS, CHAIN_NATIVE_SYMBOLS, INIT_CHAINS, HYPERBRIDGE_WS_DEFAULTS;
|
|
251617
|
+
var FREE_RPC_URLS, HYPERBRIDGE_BUNDLER_URLS, CHAIN_NATIVE_SYMBOLS, INIT_CHAINS, HYPERBRIDGE_WS_DEFAULTS;
|
|
251384
251618
|
var init_chains2 = __esm({
|
|
251385
251619
|
"src/cli/init/chains.ts"() {
|
|
251386
251620
|
"use strict";
|
|
@@ -251432,6 +251666,13 @@ var init_chains2 = __esm({
|
|
|
251432
251666
|
"https://arb1.arbitrum.io/rpc"
|
|
251433
251667
|
]
|
|
251434
251668
|
};
|
|
251669
|
+
HYPERBRIDGE_BUNDLER_URLS = {
|
|
251670
|
+
1: "https://bundler.polytope.technology/ethereum",
|
|
251671
|
+
56: "https://bundler.polytope.technology/bsc",
|
|
251672
|
+
137: "https://bundler.polytope.technology/polygon",
|
|
251673
|
+
8453: "https://bundler.polytope.technology/base",
|
|
251674
|
+
42161: "https://bundler.polytope.technology/arbitrum"
|
|
251675
|
+
};
|
|
251435
251676
|
CHAIN_NATIVE_SYMBOLS = {
|
|
251436
251677
|
1: "ETH",
|
|
251437
251678
|
56: "BNB",
|
|
@@ -251457,7 +251698,8 @@ var init_chains2 = __esm({
|
|
|
251457
251698
|
network: "mainnet",
|
|
251458
251699
|
alchemySubdomain: "eth-mainnet",
|
|
251459
251700
|
explorerUrl: external_links_default.chainExplorers.ethereum,
|
|
251460
|
-
defaultRpcUrls: FREE_RPC_URLS[1]
|
|
251701
|
+
defaultRpcUrls: FREE_RPC_URLS[1],
|
|
251702
|
+
hyperbridgeBundlerUrl: HYPERBRIDGE_BUNDLER_URLS[1]
|
|
251461
251703
|
},
|
|
251462
251704
|
{
|
|
251463
251705
|
chainId: 42161,
|
|
@@ -251466,7 +251708,8 @@ var init_chains2 = __esm({
|
|
|
251466
251708
|
network: "mainnet",
|
|
251467
251709
|
alchemySubdomain: "arb-mainnet",
|
|
251468
251710
|
explorerUrl: external_links_default.chainExplorers.arbitrum,
|
|
251469
|
-
defaultRpcUrls: FREE_RPC_URLS[42161]
|
|
251711
|
+
defaultRpcUrls: FREE_RPC_URLS[42161],
|
|
251712
|
+
hyperbridgeBundlerUrl: HYPERBRIDGE_BUNDLER_URLS[42161]
|
|
251470
251713
|
},
|
|
251471
251714
|
{
|
|
251472
251715
|
chainId: 8453,
|
|
@@ -251475,7 +251718,8 @@ var init_chains2 = __esm({
|
|
|
251475
251718
|
network: "mainnet",
|
|
251476
251719
|
alchemySubdomain: "base-mainnet",
|
|
251477
251720
|
explorerUrl: external_links_default.chainExplorers.base,
|
|
251478
|
-
defaultRpcUrls: FREE_RPC_URLS[8453]
|
|
251721
|
+
defaultRpcUrls: FREE_RPC_URLS[8453],
|
|
251722
|
+
hyperbridgeBundlerUrl: HYPERBRIDGE_BUNDLER_URLS[8453]
|
|
251479
251723
|
},
|
|
251480
251724
|
{
|
|
251481
251725
|
chainId: 137,
|
|
@@ -251484,7 +251728,8 @@ var init_chains2 = __esm({
|
|
|
251484
251728
|
network: "mainnet",
|
|
251485
251729
|
alchemySubdomain: "polygon-mainnet",
|
|
251486
251730
|
explorerUrl: external_links_default.chainExplorers.polygon,
|
|
251487
|
-
defaultRpcUrls: FREE_RPC_URLS[137]
|
|
251731
|
+
defaultRpcUrls: FREE_RPC_URLS[137],
|
|
251732
|
+
hyperbridgeBundlerUrl: HYPERBRIDGE_BUNDLER_URLS[137]
|
|
251488
251733
|
},
|
|
251489
251734
|
{
|
|
251490
251735
|
chainId: 56,
|
|
@@ -251493,7 +251738,8 @@ var init_chains2 = __esm({
|
|
|
251493
251738
|
network: "mainnet",
|
|
251494
251739
|
alchemySubdomain: "bnb-mainnet",
|
|
251495
251740
|
explorerUrl: external_links_default.chainExplorers.bnb,
|
|
251496
|
-
defaultRpcUrls: FREE_RPC_URLS[56]
|
|
251741
|
+
defaultRpcUrls: FREE_RPC_URLS[56],
|
|
251742
|
+
hyperbridgeBundlerUrl: HYPERBRIDGE_BUNDLER_URLS[56]
|
|
251497
251743
|
},
|
|
251498
251744
|
{
|
|
251499
251745
|
chainId: 11155111,
|
|
@@ -254232,7 +254478,7 @@ var require_bn2 = __commonJS({
|
|
|
254232
254478
|
}
|
|
254233
254479
|
return this;
|
|
254234
254480
|
};
|
|
254235
|
-
BN3.prototype.add = function
|
|
254481
|
+
BN3.prototype.add = function add4(num2) {
|
|
254236
254482
|
var res;
|
|
254237
254483
|
if (num2.negative !== 0 && this.negative === 0) {
|
|
254238
254484
|
num2.negative = 0;
|
|
@@ -256059,7 +256305,7 @@ var require_bn2 = __commonJS({
|
|
|
256059
256305
|
}
|
|
256060
256306
|
return this.m.sub(a6)._forceRed(this);
|
|
256061
256307
|
};
|
|
256062
|
-
Red.prototype.add = function
|
|
256308
|
+
Red.prototype.add = function add4(a6, b5) {
|
|
256063
256309
|
this._verify2(a6, b5);
|
|
256064
256310
|
var res = a6.add(b5);
|
|
256065
256311
|
if (res.cmp(this.m) >= 0) {
|
|
@@ -267070,7 +267316,7 @@ var require_namespace = __commonJS({
|
|
|
267070
267316
|
return this.nested[name3].values;
|
|
267071
267317
|
throw Error("no such enum: " + name3);
|
|
267072
267318
|
};
|
|
267073
|
-
Namespace.prototype.add = function
|
|
267319
|
+
Namespace.prototype.add = function add4(object) {
|
|
267074
267320
|
if (!(object instanceof Field6 && object.extend !== void 0 || object instanceof Type2 || object instanceof OneOf || object instanceof Enum3 || object instanceof Service || object instanceof Namespace))
|
|
267075
267321
|
throw TypeError("object must be a valid nested object");
|
|
267076
267322
|
if (!this.nested)
|
|
@@ -267450,7 +267696,7 @@ var require_service2 = __commonJS({
|
|
|
267450
267696
|
});
|
|
267451
267697
|
return this;
|
|
267452
267698
|
};
|
|
267453
|
-
Service.prototype.add = function
|
|
267699
|
+
Service.prototype.add = function add4(object) {
|
|
267454
267700
|
if (this.get(object.name))
|
|
267455
267701
|
throw Error("duplicate name '" + object.name + "' in " + this);
|
|
267456
267702
|
if (object instanceof Method2) {
|
|
@@ -268155,7 +268401,7 @@ var require_type2 = __commonJS({
|
|
|
268155
268401
|
Type2.prototype.get = function get4(name3) {
|
|
268156
268402
|
return this.fields[name3] || this.oneofs && this.oneofs[name3] || this.nested && this.nested[name3] || null;
|
|
268157
268403
|
};
|
|
268158
|
-
Type2.prototype.add = function
|
|
268404
|
+
Type2.prototype.add = function add4(object) {
|
|
268159
268405
|
if (this.get(object.name))
|
|
268160
268406
|
throw Error("duplicate name '" + object.name + "' in " + this);
|
|
268161
268407
|
if (object instanceof Field6 && object.extend === void 0) {
|
|
@@ -269066,7 +269312,7 @@ var require_oneof = __commonJS({
|
|
|
269066
269312
|
oneof.parent.add(oneof.fieldsArray[i6]);
|
|
269067
269313
|
}
|
|
269068
269314
|
}
|
|
269069
|
-
OneOf.prototype.add = function
|
|
269315
|
+
OneOf.prototype.add = function add4(field) {
|
|
269070
269316
|
if (!(field instanceof Field6))
|
|
269071
269317
|
throw TypeError("field must be a Field");
|
|
269072
269318
|
if (field.parent && field.parent !== this.parent)
|
|
@@ -269395,7 +269641,7 @@ var require_enum = __commonJS({
|
|
|
269395
269641
|
keepComments ? this.comments : void 0
|
|
269396
269642
|
]);
|
|
269397
269643
|
};
|
|
269398
|
-
Enum3.prototype.add = function
|
|
269644
|
+
Enum3.prototype.add = function add4(name3, id2, comment, options) {
|
|
269399
269645
|
if (!util7.isString(name3))
|
|
269400
269646
|
throw TypeError("name must be a string");
|
|
269401
269647
|
if (!util7.isInteger(id2))
|
|
@@ -273872,7 +274118,7 @@ var require_umd = __commonJS({
|
|
|
273872
274118
|
return this.not().add(ONE2);
|
|
273873
274119
|
};
|
|
273874
274120
|
LongPrototype.neg = LongPrototype.negate;
|
|
273875
|
-
LongPrototype.add = function
|
|
274121
|
+
LongPrototype.add = function add4(addend) {
|
|
273876
274122
|
if (!isLong(addend)) addend = fromValue(addend);
|
|
273877
274123
|
var a48 = this.high >>> 16;
|
|
273878
274124
|
var a32 = this.high & 65535;
|
|
@@ -337563,7 +337809,7 @@ var init_help_text = __esm({
|
|
|
337563
337809
|
chains: "Simplex listens for orders and fills only on the chains you pick. Each chain needs its own RPC, an ERC-4337 bundler, and funded balances (native gas + stablecoins).",
|
|
337564
337810
|
rpc: "The RPC is used to scan order events, read balances and simulate fills. Use a premium endpoint with archive access (Alchemy, Infura, QuickNode) \u2014 free tiers rate-limit and break event scanning.",
|
|
337565
337811
|
quorum: "Listing a second, organisationally independent RPC enables quorum log scanning: every event batch must match across providers, so one lying or compromised RPC can't feed you fake orders.",
|
|
337566
|
-
bundler: "Fills execute as ERC-4337 UserOperations; the bundler submits them on-chain.
|
|
337812
|
+
bundler: "Fills execute as ERC-4337 UserOperations; the bundler submits them on-chain. Hyperbridge runs no bundler for these chains, so use a provider such as Pimlico.",
|
|
337567
337813
|
signer: "This wallet signs every fill and holds your stablecoin float on each chain. It's the identity of your filler.",
|
|
337568
337814
|
secretPhrase: "A secret phrase is a BIP-39 mnemonic of 12 to 24 English words. The filler signs with the wallet at m/44'/60'/0'/0/0 unless you pick another account index. The phrase is written to the config file in plain text, protected only by the file's permissions, the same as a private key.",
|
|
337569
337815
|
substrateKey: "Solver-selection orders are won by submitting signed bids to Hyperbridge. This Substrate account signs those bid extrinsics and must hold BRIDGE tokens for fees \u2014 the fees are claimed back automatically after fills.",
|
|
@@ -337850,6 +338096,10 @@ var init_pimlico = __esm({
|
|
|
337850
338096
|
|
|
337851
338097
|
// src/cli/init/steps/bundlers.ts
|
|
337852
338098
|
async function stepBundlers(state, prefill) {
|
|
338099
|
+
for (const chain2 of state.chains) {
|
|
338100
|
+
if (chain2.meta.hyperbridgeBundlerUrl) chain2.bundlerUrl = chain2.meta.hyperbridgeBundlerUrl;
|
|
338101
|
+
}
|
|
338102
|
+
if (state.chains.every((chain2) => chain2.bundlerUrl)) return;
|
|
337853
338103
|
why(WHY.bundler);
|
|
337854
338104
|
const alchemyChains = state.chains.filter((chain2) => {
|
|
337855
338105
|
if (chain2.bundlerUrl || !isAlchemyUrl(chain2.rpcUrls[0])) return false;
|
|
@@ -338435,9 +338685,9 @@ function chainComments(state) {
|
|
|
338435
338685
|
function showSummary(state, outputPath) {
|
|
338436
338686
|
const lines = [];
|
|
338437
338687
|
for (const chain2 of state.chains) {
|
|
338438
|
-
const
|
|
338688
|
+
const bundlerHost2 = chain2.bundlerUrl ? new URL(chain2.bundlerUrl).hostname : "?";
|
|
338439
338689
|
lines.push(
|
|
338440
|
-
`${chain2.meta.label}: ${chain2.rpcUrls.length} RPC${chain2.rpcUrls.length > 1 ? "s (quorum)" : ""}, bundler ${
|
|
338690
|
+
`${chain2.meta.label}: ${chain2.rpcUrls.length} RPC${chain2.rpcUrls.length > 1 ? "s (quorum)" : ""}, bundler ${bundlerHost2}`
|
|
338441
338691
|
);
|
|
338442
338692
|
}
|
|
338443
338693
|
if (state.passthroughChains.length > 0) {
|
|
@@ -340232,6 +340482,35 @@ var LIMITS_QUERY = `
|
|
|
340232
340482
|
chains { id name tokens { symbol decimals } }
|
|
340233
340483
|
}
|
|
340234
340484
|
`;
|
|
340485
|
+
var LEVEL_FIELDS = "fillChain priceBucket price worstPrice baseSize quoteSize orderCount solverCount";
|
|
340486
|
+
var SNAPSHOT_QUERY = `
|
|
340487
|
+
query OrderbookSnapshot($id: ID!, $sourceChain: String, $fillChain: String) {
|
|
340488
|
+
book(id: $id) {
|
|
340489
|
+
id base quote
|
|
340490
|
+
bids: levels(side: BID, sourceChain: $sourceChain, fillChain: $fillChain) { ${LEVEL_FIELDS} }
|
|
340491
|
+
asks: levels(side: ASK, sourceChain: $sourceChain, fillChain: $fillChain) { ${LEVEL_FIELDS} }
|
|
340492
|
+
bidLiquidity: availableLiquidity(side: BID, sourceChain: $sourceChain, fillChain: $fillChain)
|
|
340493
|
+
askLiquidity: availableLiquidity(side: ASK, sourceChain: $sourceChain, fillChain: $fillChain)
|
|
340494
|
+
}
|
|
340495
|
+
serverInfo { priceGranularities { book granularity } }
|
|
340496
|
+
}
|
|
340497
|
+
`;
|
|
340498
|
+
var LEVEL_ORDERS_QUERY = `
|
|
340499
|
+
query OrderbookLevelOrders($id: ID!, $side: Side!, $fillChain: String, $sourceChain: String, $after: String) {
|
|
340500
|
+
book(id: $id) {
|
|
340501
|
+
orders(side: $side, fillChain: $fillChain, sourceChain: $sourceChain, first: 50, after: $after) {
|
|
340502
|
+
edges {
|
|
340503
|
+
node {
|
|
340504
|
+
solver { address }
|
|
340505
|
+
commitment fillChain price priceBucket advertisedSize quotedAmount resized expiresAt acceptedSources
|
|
340506
|
+
}
|
|
340507
|
+
}
|
|
340508
|
+
pageInfo { hasNextPage endCursor }
|
|
340509
|
+
}
|
|
340510
|
+
}
|
|
340511
|
+
}
|
|
340512
|
+
`;
|
|
340513
|
+
var LEVEL_ORDER_PAGES = 20;
|
|
340235
340514
|
var POSTED_ORDER_FIELDS = "commitment side status price quotedAmount advertisedSize expiresAt acceptedSources";
|
|
340236
340515
|
var SUBMIT_ORDER_MUTATION = `
|
|
340237
340516
|
mutation SubmitOrder($userOp: Bytes!) {
|
|
@@ -340296,6 +340575,44 @@ var OrderbookClient = class {
|
|
|
340296
340575
|
async limits() {
|
|
340297
340576
|
return this.request(LIMITS_QUERY, {});
|
|
340298
340577
|
}
|
|
340578
|
+
/** The public book across all solvers, restricted to the selected route. */
|
|
340579
|
+
async snapshot(id2, filters = {}) {
|
|
340580
|
+
const { book, serverInfo } = await this.request(SNAPSHOT_QUERY, {
|
|
340581
|
+
id: id2,
|
|
340582
|
+
sourceChain: filters.sourceChain || null,
|
|
340583
|
+
fillChain: filters.fillChain || null
|
|
340584
|
+
});
|
|
340585
|
+
if (!book) return null;
|
|
340586
|
+
const granularity = serverInfo.priceGranularities.find((entry) => entry.book === book.id)?.granularity ?? null;
|
|
340587
|
+
return { ...book, granularity };
|
|
340588
|
+
}
|
|
340589
|
+
/**
|
|
340590
|
+
* The orders behind one price level. The orderbook filters orders by side and route but not by
|
|
340591
|
+
* price bucket, so this walks the side's orders on the level's fill chain and keeps the bucket.
|
|
340592
|
+
* Null when the book does not exist.
|
|
340593
|
+
*/
|
|
340594
|
+
async levelOrders(id2, level) {
|
|
340595
|
+
const found = [];
|
|
340596
|
+
let after = null;
|
|
340597
|
+
for (let page = 0; page < LEVEL_ORDER_PAGES; page++) {
|
|
340598
|
+
const { book } = await this.request(LEVEL_ORDERS_QUERY, {
|
|
340599
|
+
id: id2,
|
|
340600
|
+
side: level.side,
|
|
340601
|
+
fillChain: level.fillChain,
|
|
340602
|
+
sourceChain: level.sourceChain || null,
|
|
340603
|
+
after
|
|
340604
|
+
});
|
|
340605
|
+
if (!book) return null;
|
|
340606
|
+
for (const { node } of book.orders.edges) {
|
|
340607
|
+
if (node.priceBucket !== level.priceBucket) continue;
|
|
340608
|
+
const { solver, priceBucket: _bucket, ...order } = node;
|
|
340609
|
+
found.push({ ...order, solver: solver.address });
|
|
340610
|
+
}
|
|
340611
|
+
if (!book.orders.pageInfo.hasNextPage || !book.orders.pageInfo.endCursor) break;
|
|
340612
|
+
after = book.orders.pageInfo.endCursor;
|
|
340613
|
+
}
|
|
340614
|
+
return found;
|
|
340615
|
+
}
|
|
340299
340616
|
async submitOrder(userOp) {
|
|
340300
340617
|
const { submitOrder } = await this.request(SUBMIT_ORDER_MUTATION, { userOp });
|
|
340301
340618
|
switch (submitOrder.__typename) {
|
|
@@ -340484,16 +340801,16 @@ function signedAmounts(params) {
|
|
|
340484
340801
|
function offerFor(params) {
|
|
340485
340802
|
const { side, inputAmount, price, outputDecimals } = params;
|
|
340486
340803
|
if (price <= 0n) throw new Error("A limit order's price must be greater than zero");
|
|
340487
|
-
const
|
|
340804
|
+
const scaled2 = side === "BID" ? inputAmount * price / ORDERBOOK_SCALE2 : inputAmount * ORDERBOOK_SCALE2 / price;
|
|
340488
340805
|
const unit = outputDecimals >= 18 ? 1n : 10n ** BigInt(18 - outputDecimals);
|
|
340489
|
-
return
|
|
340806
|
+
return scaled2 / unit * unit;
|
|
340490
340807
|
}
|
|
340491
340808
|
function inputFor(params) {
|
|
340492
340809
|
const { side, outputAmount, price, inputDecimals } = params;
|
|
340493
340810
|
if (price <= 0n) throw new Error("A limit order's price must be greater than zero");
|
|
340494
|
-
const
|
|
340811
|
+
const scaled2 = side === "BID" ? divCeil2(outputAmount * ORDERBOOK_SCALE2, price) : divCeil2(outputAmount * price, ORDERBOOK_SCALE2);
|
|
340495
340812
|
const unit = inputDecimals >= 18 ? 1n : 10n ** BigInt(18 - inputDecimals);
|
|
340496
|
-
return divCeil2(
|
|
340813
|
+
return divCeil2(scaled2, unit) * unit;
|
|
340497
340814
|
}
|
|
340498
340815
|
|
|
340499
340816
|
// src/orderbook/matching.ts
|
|
@@ -340616,6 +340933,8 @@ var LimitOrderService = class {
|
|
|
340616
340933
|
this.delegationService = delegationService;
|
|
340617
340934
|
this.startingNonce = startingNonce;
|
|
340618
340935
|
this.vaultBalances = vaultBalances;
|
|
340936
|
+
/** Re-signs in flight, by order id. A fill's resize waits one out rather than reposting alongside it. */
|
|
340937
|
+
this.resigning = /* @__PURE__ */ new Map();
|
|
340619
340938
|
this.logger = loggers.get("limit-orders");
|
|
340620
340939
|
}
|
|
340621
340940
|
/**
|
|
@@ -340709,6 +341028,7 @@ var LimitOrderService = class {
|
|
|
340709
341028
|
bookExpiresAt: null,
|
|
340710
341029
|
bookPrice: null,
|
|
340711
341030
|
orderNonce: order.orderNonce,
|
|
341031
|
+
entryPoint: null,
|
|
340712
341032
|
status: "cancelled",
|
|
340713
341033
|
lastError: null
|
|
340714
341034
|
}),
|
|
@@ -340751,6 +341071,14 @@ var LimitOrderService = class {
|
|
|
340751
341071
|
throw err;
|
|
340752
341072
|
}
|
|
340753
341073
|
}
|
|
341074
|
+
/** Public market levels read through the configured orderbook client. */
|
|
341075
|
+
orderbookSnapshot(book, filters = {}) {
|
|
341076
|
+
return this.client.snapshot(book, filters);
|
|
341077
|
+
}
|
|
341078
|
+
/** Every solver's order behind one public price level. */
|
|
341079
|
+
orderbookLevelOrders(book, level) {
|
|
341080
|
+
return this.client.levelOrders(book, level);
|
|
341081
|
+
}
|
|
340754
341082
|
/**
|
|
340755
341083
|
* The pairs an order can be written against, the smallest payout each token may carry, and
|
|
340756
341084
|
* the tokens the orderbook registers on each chain.
|
|
@@ -340805,16 +341133,16 @@ var LimitOrderService = class {
|
|
|
340805
341133
|
if (!this.configService.getConfiguredChainIds().includes(getChainId3(request3.fillChain) ?? -1)) {
|
|
340806
341134
|
throw new LimitOrderValidationError(`'${request3.fillChain}' is not a chain this filler is configured for`);
|
|
340807
341135
|
}
|
|
340808
|
-
const
|
|
341136
|
+
const scaled2 = { amountIn: 0n, amountOut: 0n };
|
|
340809
341137
|
for (const name3 of ["amountIn", "amountOut"]) {
|
|
340810
341138
|
try {
|
|
340811
|
-
|
|
341139
|
+
scaled2[name3] = fromHuman(request3[name3] ?? "");
|
|
340812
341140
|
} catch (err) {
|
|
340813
341141
|
throw new LimitOrderValidationError(
|
|
340814
341142
|
`${name3} must be an amount in whole tokens, like "1000" or "1500.25"; ${err.message}`
|
|
340815
341143
|
);
|
|
340816
341144
|
}
|
|
340817
|
-
if (
|
|
341145
|
+
if (scaled2[name3] <= 0n) throw new LimitOrderValidationError(`${name3} must be greater than zero`);
|
|
340818
341146
|
}
|
|
340819
341147
|
const sources = request3.acceptedSources ?? [];
|
|
340820
341148
|
if (sources.length === 0) {
|
|
@@ -340861,7 +341189,7 @@ var LimitOrderService = class {
|
|
|
340861
341189
|
);
|
|
340862
341190
|
}
|
|
340863
341191
|
const floor2 = limits.serverInfo.minOrderSizes.find((entry) => entry.symbol === request3.tokenOut);
|
|
340864
|
-
if (floor2 &&
|
|
341192
|
+
if (floor2 && scaled2.amountOut < BigInt(floor2.size)) {
|
|
340865
341193
|
throw new LimitOrderValidationError(
|
|
340866
341194
|
`amountOut is below the orderbook's dust floor for ${request3.tokenOut} (${toHuman(BigInt(floor2.size))})`
|
|
340867
341195
|
);
|
|
@@ -340871,7 +341199,7 @@ var LimitOrderService = class {
|
|
|
340871
341199
|
throw new LimitOrderValidationError(`'${symbol3}' does not resolve to a token address on ${request3.fillChain}`);
|
|
340872
341200
|
}
|
|
340873
341201
|
}
|
|
340874
|
-
return { amountIn:
|
|
341202
|
+
return { amountIn: scaled2.amountIn, amountOut: scaled2.amountOut };
|
|
340875
341203
|
}
|
|
340876
341204
|
/**
|
|
340877
341205
|
* Refuses an order the wallet cannot pay out.
|
|
@@ -340967,24 +341295,32 @@ var LimitOrderService = class {
|
|
|
340967
341295
|
async resize(remaining, delivered) {
|
|
340968
341296
|
const id2 = remaining.id;
|
|
340969
341297
|
const floor2 = await this.dustFloor(remaining);
|
|
340970
|
-
|
|
341298
|
+
for (let resigning = this.resigning.get(id2); resigning; resigning = this.resigning.get(id2)) await resigning;
|
|
341299
|
+
const order = await this.store.setStatus(id2, "resizing", null, POSTABLE);
|
|
341300
|
+
if (!order) return null;
|
|
341301
|
+
if (BigInt(order.remaining) < floor2) {
|
|
340971
341302
|
this.logger.info(
|
|
340972
|
-
{ id: id2, remaining:
|
|
341303
|
+
{ id: id2, remaining: order.remaining, floor: floor2.toString() },
|
|
340973
341304
|
"Limit order worked down past the dust floor; closing it"
|
|
340974
341305
|
);
|
|
340975
|
-
if (
|
|
340976
|
-
const closed = await this.store.setPosting(
|
|
340977
|
-
|
|
340978
|
-
|
|
340979
|
-
|
|
340980
|
-
|
|
340981
|
-
|
|
340982
|
-
|
|
340983
|
-
|
|
341306
|
+
if (order.commitment) await this.withdraw(order.commitment);
|
|
341307
|
+
const closed = await this.store.setPosting(
|
|
341308
|
+
id2,
|
|
341309
|
+
{
|
|
341310
|
+
commitment: null,
|
|
341311
|
+
bookExpiresAt: null,
|
|
341312
|
+
bookPrice: null,
|
|
341313
|
+
orderNonce: order.orderNonce,
|
|
341314
|
+
entryPoint: null,
|
|
341315
|
+
status: "filled",
|
|
341316
|
+
lastError: null
|
|
341317
|
+
},
|
|
341318
|
+
POSTABLE
|
|
341319
|
+
);
|
|
340984
341320
|
if (closed) this.report({ kind: "filled", order: closed });
|
|
340985
341321
|
return closed;
|
|
340986
341322
|
}
|
|
340987
|
-
const resized = await this.repost(
|
|
341323
|
+
const resized = await this.repost(order);
|
|
340988
341324
|
if (resized) this.report({ kind: "resized", order: resized, delivered });
|
|
340989
341325
|
return resized;
|
|
340990
341326
|
}
|
|
@@ -340997,7 +341333,7 @@ var LimitOrderService = class {
|
|
|
340997
341333
|
*/
|
|
340998
341334
|
async repost(order) {
|
|
340999
341335
|
if (!order) return null;
|
|
341000
|
-
if (isLocal(order)) return this.store.setStatus(order.id, "open");
|
|
341336
|
+
if (isLocal(order)) return this.store.setStatus(order.id, "open", null, POSTABLE);
|
|
341001
341337
|
if (hasExpired(order.expiresAt, /* @__PURE__ */ new Date())) return this.retire(order);
|
|
341002
341338
|
if (order.commitment) {
|
|
341003
341339
|
const withdrawn = await this.withdraw(order.commitment);
|
|
@@ -341008,10 +341344,13 @@ var LimitOrderService = class {
|
|
|
341008
341344
|
{ id: order.id, commitment: order.commitment, err: message },
|
|
341009
341345
|
"Could not clear the old entry; leaving the posting alone rather than adding a second"
|
|
341010
341346
|
);
|
|
341011
|
-
return this.store.setStatus(order.id, "open", message);
|
|
341347
|
+
return this.store.setStatus(order.id, "open", message, POSTABLE);
|
|
341012
341348
|
}
|
|
341013
341349
|
}
|
|
341014
|
-
await this.store.setStatus(order.id, "resizing")
|
|
341350
|
+
if (!await this.store.setStatus(order.id, "resizing", null, POSTABLE)) {
|
|
341351
|
+
this.logger.info({ id: order.id }, "Limit order closed while it was being reposted; leaving it closed");
|
|
341352
|
+
return null;
|
|
341353
|
+
}
|
|
341015
341354
|
const nonce = (BigInt(order.orderNonce) + 1n).toString();
|
|
341016
341355
|
return (await this.post({ ...order, commitment: null, orderNonce: nonce })).order;
|
|
341017
341356
|
}
|
|
@@ -341054,7 +341393,9 @@ var LimitOrderService = class {
|
|
|
341054
341393
|
* They drift apart when a request never got an answer or the process died
|
|
341055
341394
|
* between two of them: an entry the orderbook still lists that nothing here
|
|
341056
341395
|
* owns, an order here whose entry has gone, or an entry the orderbook has cut
|
|
341057
|
-
* down because the solver cannot cover what it quoted.
|
|
341396
|
+
* down because the solver cannot cover what it quoted. A posted op is also
|
|
341397
|
+
* signed over one EntryPoint, so when the fill chain moves to another, every
|
|
341398
|
+
* entry signed before the move is withdrawn and posted again.
|
|
341058
341399
|
*/
|
|
341059
341400
|
async reconcile(now = /* @__PURE__ */ new Date()) {
|
|
341060
341401
|
const [entries, live] = await Promise.all([this.postedOrders(), this.live()]);
|
|
@@ -341081,7 +341422,17 @@ var LimitOrderService = class {
|
|
|
341081
341422
|
}
|
|
341082
341423
|
for (const order of live) {
|
|
341083
341424
|
if (isLocal(order)) continue;
|
|
341084
|
-
if (order.commitment && found.has(order.commitment.toLowerCase()))
|
|
341425
|
+
if (order.commitment && found.has(order.commitment.toLowerCase())) {
|
|
341426
|
+
try {
|
|
341427
|
+
if (await this.resign(order)) report.reposted++;
|
|
341428
|
+
} catch (err) {
|
|
341429
|
+
this.logger.error(
|
|
341430
|
+
{ id: order.id, err },
|
|
341431
|
+
"Could not sign the limit order again for its chain's EntryPoint"
|
|
341432
|
+
);
|
|
341433
|
+
}
|
|
341434
|
+
continue;
|
|
341435
|
+
}
|
|
341085
341436
|
if (sinceMs(order.updatedAt, now) < POST_GRACE_MS) continue;
|
|
341086
341437
|
this.logger.warn({ id: order.id }, "Limit order has no entry on the orderbook; posting it again");
|
|
341087
341438
|
try {
|
|
@@ -341093,6 +341444,45 @@ var LimitOrderService = class {
|
|
|
341093
341444
|
}
|
|
341094
341445
|
return report;
|
|
341095
341446
|
}
|
|
341447
|
+
/**
|
|
341448
|
+
* Withdraws a posting signed for an EntryPoint its fill chain no longer uses,
|
|
341449
|
+
* and posts it again signed for the one it uses now. Answers whether a new
|
|
341450
|
+
* posting landed.
|
|
341451
|
+
*
|
|
341452
|
+
* The row is read again and claimed out of `open` first: a fill can have worked
|
|
341453
|
+
* it down or started its own repost since reconciliation listed it, and that
|
|
341454
|
+
* write is the one to follow. A fill that lands once the claim is taken waits
|
|
341455
|
+
* in `resize` for this to finish. The EntryPoint is only written with a posting
|
|
341456
|
+
* that landed, so a pass cut short anywhere leaves a row the next pass still
|
|
341457
|
+
* reads as stale, or as having no entry, and finishes the job.
|
|
341458
|
+
*/
|
|
341459
|
+
async resign(listed) {
|
|
341460
|
+
const entryPoint = this.configService.getEntryPointAddress(listed.fillChain);
|
|
341461
|
+
if (!entryPoint || sameAddress(signedFor(listed), entryPoint)) return false;
|
|
341462
|
+
const order = await this.store.get(listed.id);
|
|
341463
|
+
if (!order || order.status !== "open" || order.commitment !== listed.commitment) return false;
|
|
341464
|
+
if (sameAddress(signedFor(order), entryPoint) || this.resigning.has(order.id)) return false;
|
|
341465
|
+
const resigned = this.signAgain(order, entryPoint);
|
|
341466
|
+
this.resigning.set(
|
|
341467
|
+
order.id,
|
|
341468
|
+
resigned.catch(() => false)
|
|
341469
|
+
);
|
|
341470
|
+
try {
|
|
341471
|
+
return await resigned;
|
|
341472
|
+
} finally {
|
|
341473
|
+
this.resigning.delete(order.id);
|
|
341474
|
+
}
|
|
341475
|
+
}
|
|
341476
|
+
async signAgain(order, entryPoint) {
|
|
341477
|
+
const claimed = await this.store.setStatus(order.id, "resizing", null, ["open"]);
|
|
341478
|
+
if (!claimed) return false;
|
|
341479
|
+
this.logger.warn(
|
|
341480
|
+
{ id: order.id, commitment: order.commitment, signedFor: signedFor(order), entryPoint },
|
|
341481
|
+
"Limit order was signed for an EntryPoint its chain no longer uses; signing it again"
|
|
341482
|
+
);
|
|
341483
|
+
const posted = await this.repost(claimed);
|
|
341484
|
+
return !!posted?.commitment && sameAddress(signedFor(posted), entryPoint);
|
|
341485
|
+
}
|
|
341096
341486
|
/**
|
|
341097
341487
|
* Lowers every open order's `remaining` to what the solver's account will still
|
|
341098
341488
|
* pay for it, and puts the order back on the book at that size.
|
|
@@ -341174,6 +341564,7 @@ var LimitOrderService = class {
|
|
|
341174
341564
|
bookExpiresAt: null,
|
|
341175
341565
|
bookPrice: null,
|
|
341176
341566
|
orderNonce: order.orderNonce,
|
|
341567
|
+
entryPoint: null,
|
|
341177
341568
|
status: "expired",
|
|
341178
341569
|
lastError: null
|
|
341179
341570
|
});
|
|
@@ -341230,11 +341621,11 @@ var LimitOrderService = class {
|
|
|
341230
341621
|
}
|
|
341231
341622
|
/** Builds and submits the posting, then writes the orderbook's answer onto the row. */
|
|
341232
341623
|
async post(order) {
|
|
341233
|
-
const { result, orderNonce } = await this.submit(order);
|
|
341624
|
+
const { result, orderNonce, entryPoint } = await this.submit(order);
|
|
341234
341625
|
if (result.kind === "accepted" || result.kind === "unchanged") {
|
|
341235
341626
|
const posted = result.order;
|
|
341236
341627
|
this.logger.info(
|
|
341237
|
-
{ id: order.id, commitment: posted.commitment, price: posted.price },
|
|
341628
|
+
{ id: order.id, commitment: posted.commitment, price: posted.price, entryPoint },
|
|
341238
341629
|
"Limit order posted to the orderbook"
|
|
341239
341630
|
);
|
|
341240
341631
|
const stored = await this.store.setPosting(
|
|
@@ -341244,6 +341635,10 @@ var LimitOrderService = class {
|
|
|
341244
341635
|
bookExpiresAt: posted.expiresAt,
|
|
341245
341636
|
bookPrice: posted.price,
|
|
341246
341637
|
orderNonce: orderNonce.toString(),
|
|
341638
|
+
// An entry the orderbook already held was signed by an earlier attempt,
|
|
341639
|
+
// for whichever EntryPoint was current then. Recorded as unknown, which
|
|
341640
|
+
// reconciliation reads as v0.8 and signs again once the chain is past it.
|
|
341641
|
+
entryPoint: result.kind === "accepted" ? entryPoint : null,
|
|
341247
341642
|
status: "open",
|
|
341248
341643
|
lastError: null
|
|
341249
341644
|
},
|
|
@@ -341273,6 +341668,7 @@ var LimitOrderService = class {
|
|
|
341273
341668
|
bookExpiresAt: null,
|
|
341274
341669
|
bookPrice: null,
|
|
341275
341670
|
orderNonce: orderNonce.toString(),
|
|
341671
|
+
entryPoint: null,
|
|
341276
341672
|
status: "open",
|
|
341277
341673
|
lastError: message
|
|
341278
341674
|
}),
|
|
@@ -341295,22 +341691,30 @@ var LimitOrderService = class {
|
|
|
341295
341691
|
* only the second one.
|
|
341296
341692
|
*/
|
|
341297
341693
|
async submit(order) {
|
|
341694
|
+
const entryPoint = this.entryPointFor(order.fillChain);
|
|
341298
341695
|
const orderNonce = BigInt(order.orderNonce);
|
|
341299
|
-
const attempt = await this.buildAndSubmit(order, orderNonce);
|
|
341696
|
+
const attempt = await this.buildAndSubmit(order, orderNonce, entryPoint);
|
|
341300
341697
|
const first3 = attempt.result;
|
|
341301
341698
|
if (first3.kind !== "rejected" || first3.code !== "REPLAYED" && first3.code !== "ORDER_EXISTS") {
|
|
341302
|
-
return { result: first3, orderNonce };
|
|
341699
|
+
return { result: first3, orderNonce, entryPoint };
|
|
341303
341700
|
}
|
|
341304
341701
|
if (first3.code === "ORDER_EXISTS" && attempt.commitment) {
|
|
341305
341702
|
const live = await this.entryAt(order, attempt.commitment);
|
|
341306
341703
|
if (live) {
|
|
341307
341704
|
this.logger.info({ id: order.id, commitment: live.commitment }, "This posting is already on the orderbook");
|
|
341308
|
-
return { result: { kind: "unchanged", order: live }, orderNonce };
|
|
341705
|
+
return { result: { kind: "unchanged", order: live }, orderNonce, entryPoint };
|
|
341309
341706
|
}
|
|
341310
341707
|
}
|
|
341311
341708
|
this.logger.warn({ id: order.id, code: first3.code }, "Orderbook has seen this op before; reposting on a new nonce");
|
|
341312
341709
|
const retried = orderNonce + 1n;
|
|
341313
|
-
|
|
341710
|
+
const { result } = await this.buildAndSubmit(order, retried, entryPoint);
|
|
341711
|
+
return { result, orderNonce: retried, entryPoint };
|
|
341712
|
+
}
|
|
341713
|
+
/** The EntryPoint a posting on `chain` is signed for now. */
|
|
341714
|
+
entryPointFor(chain2) {
|
|
341715
|
+
const entryPoint = this.configService.getEntryPointAddress(chain2);
|
|
341716
|
+
if (!entryPoint) throw new LimitOrderValidationError(`No EntryPoint is configured for ${chain2}`);
|
|
341717
|
+
return entryPoint;
|
|
341314
341718
|
}
|
|
341315
341719
|
/**
|
|
341316
341720
|
* The entry the orderbook holds at `commitment`, if it holds one. A lookup that
|
|
@@ -341326,8 +341730,8 @@ var LimitOrderService = class {
|
|
|
341326
341730
|
}
|
|
341327
341731
|
}
|
|
341328
341732
|
/** The orderbook's answer, and the commitment the op we sent hashes to. */
|
|
341329
|
-
async buildAndSubmit(order, orderNonce) {
|
|
341330
|
-
const { commitment, userOp } = await this.buildUserOp(order, orderNonce);
|
|
341733
|
+
async buildAndSubmit(order, orderNonce, entryPoint) {
|
|
341734
|
+
const { commitment, userOp } = await this.buildUserOp(order, orderNonce, entryPoint);
|
|
341331
341735
|
try {
|
|
341332
341736
|
return { result: await this.client.submitOrder(userOp), commitment };
|
|
341333
341737
|
} catch (err) {
|
|
@@ -341337,7 +341741,7 @@ var LimitOrderService = class {
|
|
|
341337
341741
|
throw err;
|
|
341338
341742
|
}
|
|
341339
341743
|
}
|
|
341340
|
-
async buildUserOp(order, orderNonce) {
|
|
341744
|
+
async buildUserOp(order, orderNonce, entryPointAddress) {
|
|
341341
341745
|
const baseToken = this.assetRegistry.getAddress(order.base, order.fillChain);
|
|
341342
341746
|
const quoteToken = this.assetRegistry.getAddress(order.quote, order.fillChain);
|
|
341343
341747
|
const [baseDecimals, quoteDecimals] = await Promise.all([
|
|
@@ -341352,10 +341756,6 @@ var LimitOrderService = class {
|
|
|
341352
341756
|
baseDecimals,
|
|
341353
341757
|
quoteDecimals
|
|
341354
341758
|
});
|
|
341355
|
-
const entryPointAddress = this.configService.getEntryPointAddress(order.fillChain);
|
|
341356
|
-
if (!entryPointAddress) {
|
|
341357
|
-
throw new LimitOrderValidationError(`No EntryPoint is configured for ${order.fillChain}`);
|
|
341358
|
-
}
|
|
341359
341759
|
return this.contractService.prepareLimitOrderUserOp({
|
|
341360
341760
|
fillChain: order.fillChain,
|
|
341361
341761
|
entryPointAddress,
|
|
@@ -341386,6 +341786,12 @@ function hasExpired(expiresAt, now) {
|
|
|
341386
341786
|
const at = Date.parse(expiresAt);
|
|
341387
341787
|
return !Number.isNaN(at) && at <= now.getTime();
|
|
341388
341788
|
}
|
|
341789
|
+
function signedFor(order) {
|
|
341790
|
+
return order.entryPoint ?? ENTRY_POINT_V08;
|
|
341791
|
+
}
|
|
341792
|
+
function sameAddress(a6, b5) {
|
|
341793
|
+
return a6.toLowerCase() === b5.toLowerCase();
|
|
341794
|
+
}
|
|
341389
341795
|
function sinceMs(updatedAt, now) {
|
|
341390
341796
|
const written = Date.parse(`${updatedAt.replace(" ", "T")}Z`);
|
|
341391
341797
|
return Number.isNaN(written) ? Number.POSITIVE_INFINITY : now.getTime() - written;
|
|
@@ -341397,6 +341803,459 @@ function underFunded(entry) {
|
|
|
341397
341803
|
return entry.resized ? `UNDER_FUNDED: the orderbook is advertising ${entry.advertisedSize} of the ${entry.quotedAmount} quoted` : "UNDER_FUNDED: the solver's balance does not cover this posting";
|
|
341398
341804
|
}
|
|
341399
341805
|
|
|
341806
|
+
// src/orderbook/profitability.ts
|
|
341807
|
+
init_esm_shims();
|
|
341808
|
+
init_decimal();
|
|
341809
|
+
init_asset_registry();
|
|
341810
|
+
|
|
341811
|
+
// src/data/inventory.ts
|
|
341812
|
+
init_esm_shims();
|
|
341813
|
+
var INVENTORY_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
341814
|
+
function inventoryOf(snapshot) {
|
|
341815
|
+
if (snapshot.status !== "fresh") return null;
|
|
341816
|
+
const held = {};
|
|
341817
|
+
for (const chain2 of snapshot.chains) {
|
|
341818
|
+
for (const asset of chain2.assets) {
|
|
341819
|
+
if (asset.total === null) return null;
|
|
341820
|
+
held[asset.symbol] = (held[asset.symbol] ?? 0) + asset.total;
|
|
341821
|
+
}
|
|
341822
|
+
}
|
|
341823
|
+
return Object.keys(held).length > 0 ? held : null;
|
|
341824
|
+
}
|
|
341825
|
+
function parseUtc(value) {
|
|
341826
|
+
return Date.parse(`${value.replace(" ", "T")}Z`);
|
|
341827
|
+
}
|
|
341828
|
+
var InventoryRecorder = class {
|
|
341829
|
+
constructor(store, balances, logger8, now = Date.now) {
|
|
341830
|
+
this.store = store;
|
|
341831
|
+
this.balances = balances;
|
|
341832
|
+
this.logger = logger8;
|
|
341833
|
+
this.now = now;
|
|
341834
|
+
this.recording = false;
|
|
341835
|
+
this.onSnapshot = (snapshot) => void this.consider(snapshot);
|
|
341836
|
+
}
|
|
341837
|
+
start() {
|
|
341838
|
+
this.balances.on("snapshot", this.onSnapshot);
|
|
341839
|
+
void this.consider(this.balances.getSnapshot());
|
|
341840
|
+
}
|
|
341841
|
+
stop() {
|
|
341842
|
+
this.balances.off("snapshot", this.onSnapshot);
|
|
341843
|
+
}
|
|
341844
|
+
/** Takes a snapshot from `snapshot` if one is due and the read is complete. Never rejects. */
|
|
341845
|
+
async consider(snapshot) {
|
|
341846
|
+
if (this.recording) return;
|
|
341847
|
+
const held = inventoryOf(snapshot);
|
|
341848
|
+
if (!held) return;
|
|
341849
|
+
this.recording = true;
|
|
341850
|
+
try {
|
|
341851
|
+
if (this.lastTakenAt === void 0) {
|
|
341852
|
+
const latest2 = await this.store.latest();
|
|
341853
|
+
this.lastTakenAt = latest2 ? parseUtc(latest2.takenAt) : 0;
|
|
341854
|
+
}
|
|
341855
|
+
if (this.now() - this.lastTakenAt < INVENTORY_INTERVAL_MS) return;
|
|
341856
|
+
await this.store.record(held);
|
|
341857
|
+
this.lastTakenAt = this.now();
|
|
341858
|
+
this.logger.info({ tokens: Object.keys(held).length }, "Recorded an inventory snapshot");
|
|
341859
|
+
} catch (err) {
|
|
341860
|
+
this.logger.warn({ err }, "Could not record an inventory snapshot");
|
|
341861
|
+
} finally {
|
|
341862
|
+
this.recording = false;
|
|
341863
|
+
}
|
|
341864
|
+
}
|
|
341865
|
+
};
|
|
341866
|
+
|
|
341867
|
+
// src/orderbook/usd.ts
|
|
341868
|
+
init_esm_shims();
|
|
341869
|
+
init_decimal();
|
|
341870
|
+
init_asset_registry();
|
|
341871
|
+
function limitOrderUsdEdges(orders) {
|
|
341872
|
+
return orders.filter((order) => normalizeSymbol(order.base) !== normalizeSymbol(order.quote)).map((order) => ({
|
|
341873
|
+
base: normalizeSymbol(order.base),
|
|
341874
|
+
quote: normalizeSymbol(order.quote),
|
|
341875
|
+
rate: new Decimal(order.price).div(ORDERBOOK_SCALE2.toString())
|
|
341876
|
+
})).filter((edge) => edge.rate.isFinite() && edge.rate.gt(0));
|
|
341877
|
+
}
|
|
341878
|
+
function usdFactorsFrom(edges) {
|
|
341879
|
+
const factors = /* @__PURE__ */ new Map();
|
|
341880
|
+
for (const symbol3 of USD_STABLE_SYMBOLS) factors.set(symbol3, new Decimal(1));
|
|
341881
|
+
const ordered = [...edges].sort((a6, b5) => a6.base.localeCompare(b5.base) || a6.quote.localeCompare(b5.quote));
|
|
341882
|
+
let grew = true;
|
|
341883
|
+
while (grew) {
|
|
341884
|
+
grew = false;
|
|
341885
|
+
for (const edge of ordered) {
|
|
341886
|
+
const usdBase = factors.get(edge.base);
|
|
341887
|
+
const usdQuote = factors.get(edge.quote);
|
|
341888
|
+
if (usdBase && !usdQuote) {
|
|
341889
|
+
factors.set(edge.quote, usdBase.div(edge.rate));
|
|
341890
|
+
grew = true;
|
|
341891
|
+
} else if (usdQuote && !usdBase) {
|
|
341892
|
+
factors.set(edge.base, usdQuote.mul(edge.rate));
|
|
341893
|
+
grew = true;
|
|
341894
|
+
}
|
|
341895
|
+
}
|
|
341896
|
+
}
|
|
341897
|
+
return factors;
|
|
341898
|
+
}
|
|
341899
|
+
function usdValueOf(factors, symbol3, amount) {
|
|
341900
|
+
const factor = factors.get(normalizeSymbol(symbol3));
|
|
341901
|
+
return factor ? amount.mul(factor) : null;
|
|
341902
|
+
}
|
|
341903
|
+
|
|
341904
|
+
// src/orderbook/profitability.ts
|
|
341905
|
+
var Decimal2 = Decimal.clone({ precision: 40 });
|
|
341906
|
+
var PROFIT_PERIODS = {
|
|
341907
|
+
"7d": { bucket: "day", count: 7 },
|
|
341908
|
+
"30d": { bucket: "day", count: 30 },
|
|
341909
|
+
"12w": { bucket: "week", count: 12 },
|
|
341910
|
+
"12m": { bucket: "month", count: 12 },
|
|
341911
|
+
all: { bucket: "year", count: null }
|
|
341912
|
+
};
|
|
341913
|
+
function isProfitPeriod(value) {
|
|
341914
|
+
return value in PROFIT_PERIODS;
|
|
341915
|
+
}
|
|
341916
|
+
var MINUTE = 6e4;
|
|
341917
|
+
var DAY = 864e5;
|
|
341918
|
+
var BALANCES_REACH_MS = 7 * DAY;
|
|
341919
|
+
function bucketStart(local, bucket) {
|
|
341920
|
+
const date = new Date(local);
|
|
341921
|
+
const year = date.getUTCFullYear();
|
|
341922
|
+
const month = date.getUTCMonth();
|
|
341923
|
+
if (bucket === "year") return Date.UTC(year, 0, 1);
|
|
341924
|
+
if (bucket === "month") return Date.UTC(year, month, 1);
|
|
341925
|
+
const day = Date.UTC(year, month, date.getUTCDate());
|
|
341926
|
+
return bucket === "day" ? day : day - (date.getUTCDay() + 6) % 7 * DAY;
|
|
341927
|
+
}
|
|
341928
|
+
function shiftBucket(start, bucket, steps) {
|
|
341929
|
+
if (bucket === "day") return start + steps * DAY;
|
|
341930
|
+
if (bucket === "week") return start + steps * 7 * DAY;
|
|
341931
|
+
const date = new Date(start);
|
|
341932
|
+
return bucket === "month" ? Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + steps, 1) : Date.UTC(date.getUTCFullYear() + steps, 0, 1);
|
|
341933
|
+
}
|
|
341934
|
+
function scaled(value) {
|
|
341935
|
+
return new Decimal2(value).div(ORDERBOOK_SCALE2.toString());
|
|
341936
|
+
}
|
|
341937
|
+
function tradeOf(fill, at) {
|
|
341938
|
+
try {
|
|
341939
|
+
const paid = scaled(fill.amount);
|
|
341940
|
+
const taken = fill.amountIn === null ? null : scaled(fill.amountIn);
|
|
341941
|
+
const price = scaled(fill.price);
|
|
341942
|
+
if (!paid.gt(0) || !price.gt(0) || taken !== null && !taken.gt(0)) return null;
|
|
341943
|
+
const buying = fill.side === "BID";
|
|
341944
|
+
const [baseAmount, quoteAmount] = buying ? [taken ?? paid.div(price), paid] : [paid, taken ?? paid.mul(price)];
|
|
341945
|
+
return {
|
|
341946
|
+
at,
|
|
341947
|
+
book: fill.book,
|
|
341948
|
+
base: normalizeSymbol(fill.base),
|
|
341949
|
+
quote: normalizeSymbol(fill.quote),
|
|
341950
|
+
buying,
|
|
341951
|
+
baseAmount,
|
|
341952
|
+
quoteAmount,
|
|
341953
|
+
estimated: taken === null
|
|
341954
|
+
};
|
|
341955
|
+
} catch {
|
|
341956
|
+
return null;
|
|
341957
|
+
}
|
|
341958
|
+
}
|
|
341959
|
+
function add3(holdings, symbol3, amount) {
|
|
341960
|
+
holdings.set(symbol3, (holdings.get(symbol3) ?? new Decimal2(0)).add(amount));
|
|
341961
|
+
}
|
|
341962
|
+
function apply3(holdings, trade, sign6) {
|
|
341963
|
+
const base4 = trade.buying ? trade.baseAmount : trade.baseAmount.neg();
|
|
341964
|
+
const quote = trade.buying ? trade.quoteAmount.neg() : trade.quoteAmount;
|
|
341965
|
+
add3(holdings, trade.base, base4.mul(sign6));
|
|
341966
|
+
add3(holdings, trade.quote, quote.mul(sign6));
|
|
341967
|
+
}
|
|
341968
|
+
var Sums = class {
|
|
341969
|
+
constructor() {
|
|
341970
|
+
this.change = /* @__PURE__ */ new Map();
|
|
341971
|
+
this.boughtUsd = new Decimal2(0);
|
|
341972
|
+
this.soldUsd = new Decimal2(0);
|
|
341973
|
+
this.buys = 0;
|
|
341974
|
+
this.sells = 0;
|
|
341975
|
+
}
|
|
341976
|
+
};
|
|
341977
|
+
var BookLedger = class {
|
|
341978
|
+
constructor(id2, base4, quote) {
|
|
341979
|
+
this.id = id2;
|
|
341980
|
+
this.base = base4;
|
|
341981
|
+
this.quote = quote;
|
|
341982
|
+
this.bought = new Decimal2(0);
|
|
341983
|
+
this.boughtQuote = new Decimal2(0);
|
|
341984
|
+
this.sold = new Decimal2(0);
|
|
341985
|
+
this.soldQuote = new Decimal2(0);
|
|
341986
|
+
/** The rates of the book's latest buy and latest sell, over all of its history. */
|
|
341987
|
+
this.latestBuy = null;
|
|
341988
|
+
this.latestSell = null;
|
|
341989
|
+
this.inPeriod = false;
|
|
341990
|
+
}
|
|
341991
|
+
/**
|
|
341992
|
+
* The rate the book is valued at. Midway between the latest buy and the latest sell, because
|
|
341993
|
+
* either alone sits half a spread to one side and would price open volume against whichever
|
|
341994
|
+
* way the book happened to trade last.
|
|
341995
|
+
*/
|
|
341996
|
+
rate() {
|
|
341997
|
+
if (this.latestBuy && this.latestSell) return this.latestBuy.add(this.latestSell).div(2);
|
|
341998
|
+
return this.latestBuy ?? this.latestSell;
|
|
341999
|
+
}
|
|
342000
|
+
};
|
|
342001
|
+
function readingOf(reading) {
|
|
342002
|
+
const held = /* @__PURE__ */ new Map();
|
|
342003
|
+
const cover = /* @__PURE__ */ new Map();
|
|
342004
|
+
for (const [symbol3, amount] of Object.entries(reading.balances)) {
|
|
342005
|
+
const chains2 = reading.chains[symbol3];
|
|
342006
|
+
if (!Number.isFinite(amount) || !chains2?.length) continue;
|
|
342007
|
+
add3(held, normalizeSymbol(symbol3), new Decimal2(amount));
|
|
342008
|
+
cover.set(normalizeSymbol(symbol3), [...chains2].sort().join(","));
|
|
342009
|
+
}
|
|
342010
|
+
return { held, cover };
|
|
342011
|
+
}
|
|
342012
|
+
function movedBetween(earlier, later) {
|
|
342013
|
+
if (!earlier || !later) return null;
|
|
342014
|
+
const moved = /* @__PURE__ */ new Map();
|
|
342015
|
+
for (const [symbol3, cover] of later.cover) {
|
|
342016
|
+
if (earlier.cover.get(symbol3) !== cover) continue;
|
|
342017
|
+
const before = earlier.held.get(symbol3) ?? new Decimal2(0);
|
|
342018
|
+
moved.set(symbol3, (later.held.get(symbol3) ?? new Decimal2(0)).sub(before));
|
|
342019
|
+
}
|
|
342020
|
+
return moved;
|
|
342021
|
+
}
|
|
342022
|
+
function nearestRecord(instant, records) {
|
|
342023
|
+
let record;
|
|
342024
|
+
let gap = Number.POSITIVE_INFINITY;
|
|
342025
|
+
for (const candidate of records) {
|
|
342026
|
+
const distance = Math.abs(candidate.at - instant);
|
|
342027
|
+
if (candidate.live && distance > BALANCES_REACH_MS) continue;
|
|
342028
|
+
if (distance < gap || distance === gap && record?.live && !candidate.live) {
|
|
342029
|
+
record = candidate;
|
|
342030
|
+
gap = distance;
|
|
342031
|
+
}
|
|
342032
|
+
}
|
|
342033
|
+
return record;
|
|
342034
|
+
}
|
|
342035
|
+
function inventoryAt(instant, records, trades, outflows, readings) {
|
|
342036
|
+
const record = nearestRecord(instant, records);
|
|
342037
|
+
if (!record) return null;
|
|
342038
|
+
const recorded = /* @__PURE__ */ new Map();
|
|
342039
|
+
for (const [symbol3, amount] of Object.entries(record.balances)) {
|
|
342040
|
+
if (Number.isFinite(amount)) add3(recorded, normalizeSymbol(symbol3), new Decimal2(amount));
|
|
342041
|
+
}
|
|
342042
|
+
const held = new Map(recorded);
|
|
342043
|
+
const after = record.at >= instant;
|
|
342044
|
+
const [from32, to] = after ? [instant, record.at] : [record.at, instant];
|
|
342045
|
+
const sign6 = after ? -1 : 1;
|
|
342046
|
+
for (const trade of trades) {
|
|
342047
|
+
if (trade.at >= from32 && trade.at < to) apply3(held, trade, sign6);
|
|
342048
|
+
}
|
|
342049
|
+
for (const outflow of outflows) {
|
|
342050
|
+
if (outflow.at >= from32 && outflow.at < to) {
|
|
342051
|
+
add3(held, normalizeSymbol(outflow.symbol), new Decimal2(outflow.amount).mul(-sign6));
|
|
342052
|
+
}
|
|
342053
|
+
}
|
|
342054
|
+
const moved = movedBetween(readings.get(from32), readings.get(to));
|
|
342055
|
+
if (moved) {
|
|
342056
|
+
for (const [symbol3, amount] of moved) {
|
|
342057
|
+
held.set(symbol3, (recorded.get(symbol3) ?? new Decimal2(0)).add(amount.mul(sign6)));
|
|
342058
|
+
}
|
|
342059
|
+
}
|
|
342060
|
+
for (const [symbol3, amount] of held) if (amount.isNegative()) held.set(symbol3, new Decimal2(0));
|
|
342061
|
+
return { held, record };
|
|
342062
|
+
}
|
|
342063
|
+
function tradesOf(fills, now) {
|
|
342064
|
+
const trades = [];
|
|
342065
|
+
for (const fill of fills) {
|
|
342066
|
+
const at = parseUtc(fill.filledAt);
|
|
342067
|
+
if (!Number.isFinite(at) || at > now) continue;
|
|
342068
|
+
const trade = tradeOf(fill, at);
|
|
342069
|
+
if (trade) trades.push(trade);
|
|
342070
|
+
}
|
|
342071
|
+
return trades.sort((a6, b5) => a6.at - b5.at);
|
|
342072
|
+
}
|
|
342073
|
+
function bucketStarts(period, now, offset, firstAt) {
|
|
342074
|
+
const { bucket, count } = PROFIT_PERIODS[period];
|
|
342075
|
+
const last = bucketStart(now - offset, bucket);
|
|
342076
|
+
const first3 = count === null ? bucketStart((firstAt ?? now) - offset, bucket) : shiftBucket(last, bucket, 1 - count);
|
|
342077
|
+
const starts = [];
|
|
342078
|
+
for (let start = first3; start <= last; start = shiftBucket(start, bucket, 1)) starts.push(start);
|
|
342079
|
+
return starts;
|
|
342080
|
+
}
|
|
342081
|
+
function inventoryInstants(fills, options) {
|
|
342082
|
+
const { period, now } = options;
|
|
342083
|
+
const offset = (options.tzOffsetMinutes ?? 0) * MINUTE;
|
|
342084
|
+
const records = (options.inventory ?? []).filter((record) => record.at <= now);
|
|
342085
|
+
const instants = /* @__PURE__ */ new Set([now]);
|
|
342086
|
+
for (const start of bucketStarts(period, now, offset, tradesOf(fills, now)[0]?.at)) {
|
|
342087
|
+
instants.add(start + offset);
|
|
342088
|
+
const record = nearestRecord(start + offset, records);
|
|
342089
|
+
if (record) instants.add(record.at);
|
|
342090
|
+
}
|
|
342091
|
+
return [...instants].sort((a6, b5) => a6 - b5);
|
|
342092
|
+
}
|
|
342093
|
+
function summarizeProfit(fills, options) {
|
|
342094
|
+
const { period, now } = options;
|
|
342095
|
+
const offset = (options.tzOffsetMinutes ?? 0) * MINUTE;
|
|
342096
|
+
const { bucket } = PROFIT_PERIODS[period];
|
|
342097
|
+
const records = (options.inventory ?? []).filter((record) => record.at <= now);
|
|
342098
|
+
const outflows = options.outflows ?? [];
|
|
342099
|
+
const readings = new Map((options.readings ?? []).map((reading) => [reading.at, readingOf(reading)]));
|
|
342100
|
+
const trades = tradesOf(fills, now);
|
|
342101
|
+
const starts = bucketStarts(period, now, offset, trades[0]?.at);
|
|
342102
|
+
const first3 = starts[0];
|
|
342103
|
+
const books = /* @__PURE__ */ new Map();
|
|
342104
|
+
const spelling2 = /* @__PURE__ */ new Map();
|
|
342105
|
+
for (const record of records) {
|
|
342106
|
+
for (const symbol3 of Object.keys(record.balances)) {
|
|
342107
|
+
if (!spelling2.has(normalizeSymbol(symbol3))) spelling2.set(normalizeSymbol(symbol3), symbol3);
|
|
342108
|
+
}
|
|
342109
|
+
}
|
|
342110
|
+
for (const fill of fills) {
|
|
342111
|
+
for (const symbol3 of [fill.base, fill.quote]) {
|
|
342112
|
+
if (!spelling2.has(normalizeSymbol(symbol3))) spelling2.set(normalizeSymbol(symbol3), symbol3);
|
|
342113
|
+
}
|
|
342114
|
+
}
|
|
342115
|
+
for (const trade of trades) {
|
|
342116
|
+
let book = books.get(trade.book);
|
|
342117
|
+
if (!book) {
|
|
342118
|
+
book = new BookLedger(trade.book, trade.base, trade.quote);
|
|
342119
|
+
books.set(trade.book, book);
|
|
342120
|
+
}
|
|
342121
|
+
const rate = trade.quoteAmount.div(trade.baseAmount);
|
|
342122
|
+
if (trade.buying) book.latestBuy = rate;
|
|
342123
|
+
else book.latestSell = rate;
|
|
342124
|
+
}
|
|
342125
|
+
const edges = [];
|
|
342126
|
+
for (const book of books.values()) {
|
|
342127
|
+
const rate = book.rate();
|
|
342128
|
+
if (rate && book.base !== book.quote) {
|
|
342129
|
+
edges.push({ base: book.base, quote: book.quote, rate: new Decimal(rate.toString()) });
|
|
342130
|
+
}
|
|
342131
|
+
}
|
|
342132
|
+
const factors = usdFactorsFrom(edges);
|
|
342133
|
+
const priceOf = (symbol3) => {
|
|
342134
|
+
const factor = factors.get(symbol3);
|
|
342135
|
+
return factor ? new Decimal2(factor.toString()) : null;
|
|
342136
|
+
};
|
|
342137
|
+
const unpriced = /* @__PURE__ */ new Set();
|
|
342138
|
+
const valueOf = (holdings) => {
|
|
342139
|
+
let total = new Decimal2(0);
|
|
342140
|
+
for (const [symbol3, amount] of holdings) {
|
|
342141
|
+
if (amount.isZero()) continue;
|
|
342142
|
+
const price = priceOf(symbol3);
|
|
342143
|
+
if (price) total = total.add(amount.mul(price));
|
|
342144
|
+
else unpriced.add(symbol3);
|
|
342145
|
+
}
|
|
342146
|
+
return total;
|
|
342147
|
+
};
|
|
342148
|
+
const totals = new Sums();
|
|
342149
|
+
const buckets = new Map(starts.map((start) => [start, new Sums()]));
|
|
342150
|
+
let estimatedFills = 0;
|
|
342151
|
+
for (const trade of trades) {
|
|
342152
|
+
const sums = buckets.get(bucketStart(trade.at - offset, bucket));
|
|
342153
|
+
if (!sums) continue;
|
|
342154
|
+
const book = books.get(trade.book);
|
|
342155
|
+
if (!book) continue;
|
|
342156
|
+
book.inPeriod = true;
|
|
342157
|
+
if (trade.estimated) estimatedFills += 1;
|
|
342158
|
+
if (trade.buying) {
|
|
342159
|
+
book.bought = book.bought.add(trade.baseAmount);
|
|
342160
|
+
book.boughtQuote = book.boughtQuote.add(trade.quoteAmount);
|
|
342161
|
+
} else {
|
|
342162
|
+
book.sold = book.sold.add(trade.baseAmount);
|
|
342163
|
+
book.soldQuote = book.soldQuote.add(trade.quoteAmount);
|
|
342164
|
+
}
|
|
342165
|
+
const basePrice = priceOf(trade.base);
|
|
342166
|
+
const quotePrice = priceOf(trade.quote);
|
|
342167
|
+
const volume = basePrice ? trade.baseAmount.mul(basePrice) : quotePrice ? trade.quoteAmount.mul(quotePrice) : new Decimal2(0);
|
|
342168
|
+
for (const sum2 of [totals, sums]) {
|
|
342169
|
+
apply3(sum2.change, trade, 1);
|
|
342170
|
+
if (trade.buying) {
|
|
342171
|
+
sum2.buys += 1;
|
|
342172
|
+
sum2.boughtUsd = sum2.boughtUsd.add(volume);
|
|
342173
|
+
} else {
|
|
342174
|
+
sum2.sells += 1;
|
|
342175
|
+
sum2.soldUsd = sum2.soldUsd.add(volume);
|
|
342176
|
+
}
|
|
342177
|
+
}
|
|
342178
|
+
}
|
|
342179
|
+
const figures = (sums, startsAt, endsAt) => {
|
|
342180
|
+
const profit = valueOf(sums.change);
|
|
342181
|
+
const began2 = inventoryAt(startsAt, records, trades, outflows, readings);
|
|
342182
|
+
const inventory = began2 ? valueOf(began2.held) : null;
|
|
342183
|
+
const moved = movedBetween(readings.get(startsAt), readings.get(endsAt));
|
|
342184
|
+
if (moved) {
|
|
342185
|
+
for (const [symbol3, amount] of sums.change) {
|
|
342186
|
+
if (moved.has(symbol3)) moved.set(symbol3, (moved.get(symbol3) ?? new Decimal2(0)).sub(amount));
|
|
342187
|
+
}
|
|
342188
|
+
}
|
|
342189
|
+
return {
|
|
342190
|
+
profitUsd: profit.toNumber(),
|
|
342191
|
+
startInventoryUsd: inventory ? inventory.toNumber() : null,
|
|
342192
|
+
returnPct: inventory?.gt(0) ? profit.div(inventory).mul(100).toNumber() : null,
|
|
342193
|
+
transfersUsd: moved && moved.size > 0 ? valueOf(moved).toNumber() : null,
|
|
342194
|
+
boughtUsd: sums.boughtUsd.toNumber(),
|
|
342195
|
+
soldUsd: sums.soldUsd.toNumber(),
|
|
342196
|
+
buys: sums.buys,
|
|
342197
|
+
sells: sums.sells
|
|
342198
|
+
};
|
|
342199
|
+
};
|
|
342200
|
+
const from32 = first3 + offset;
|
|
342201
|
+
const began = inventoryAt(from32, records, trades, outflows, readings);
|
|
342202
|
+
const startInventory = began && {
|
|
342203
|
+
at: from32,
|
|
342204
|
+
source: began.record.live ? "balances" : "snapshot",
|
|
342205
|
+
recordedAt: began.record.at,
|
|
342206
|
+
usd: valueOf(began.held).toNumber(),
|
|
342207
|
+
tokens: [...began.held].filter(([, amount]) => amount.gt(0)).map(([symbol3, amount]) => {
|
|
342208
|
+
const price = priceOf(symbol3);
|
|
342209
|
+
return {
|
|
342210
|
+
symbol: spelling2.get(symbol3) ?? symbol3,
|
|
342211
|
+
amount: amount.toNumber(),
|
|
342212
|
+
usd: price ? amount.mul(price).toNumber() : null
|
|
342213
|
+
};
|
|
342214
|
+
}).sort((a6, b5) => (b5.usd ?? 0) - (a6.usd ?? 0) || a6.symbol.localeCompare(b5.symbol))
|
|
342215
|
+
};
|
|
342216
|
+
const rows = [];
|
|
342217
|
+
for (const book of books.values()) {
|
|
342218
|
+
if (!book.inPeriod) continue;
|
|
342219
|
+
const averageBuy = book.bought.gt(0) ? book.boughtQuote.div(book.bought) : null;
|
|
342220
|
+
const averageSell = book.sold.gt(0) ? book.soldQuote.div(book.sold) : null;
|
|
342221
|
+
const baseChange = book.bought.sub(book.sold);
|
|
342222
|
+
const quoteChange = book.soldQuote.sub(book.boughtQuote);
|
|
342223
|
+
const basePrice = priceOf(book.base);
|
|
342224
|
+
const quotePrice = priceOf(book.quote);
|
|
342225
|
+
rows.push({
|
|
342226
|
+
book: book.id,
|
|
342227
|
+
base: spelling2.get(book.base) ?? book.base,
|
|
342228
|
+
quote: spelling2.get(book.quote) ?? book.quote,
|
|
342229
|
+
bought: book.bought.toNumber(),
|
|
342230
|
+
sold: book.sold.toNumber(),
|
|
342231
|
+
averageBuy: averageBuy ? averageBuy.toNumber() : null,
|
|
342232
|
+
averageSell: averageSell ? averageSell.toNumber() : null,
|
|
342233
|
+
spreadPct: averageBuy && averageSell ? averageSell.div(averageBuy).sub(1).mul(100).toNumber() : null,
|
|
342234
|
+
baseChange: baseChange.toNumber(),
|
|
342235
|
+
quoteChange: quoteChange.toNumber(),
|
|
342236
|
+
rate: book.rate()?.toNumber() ?? null,
|
|
342237
|
+
profitUsd: basePrice && quotePrice ? baseChange.mul(basePrice).add(quoteChange.mul(quotePrice)).toNumber() : null
|
|
342238
|
+
});
|
|
342239
|
+
}
|
|
342240
|
+
rows.sort((a6, b5) => (b5.profitUsd ?? 0) - (a6.profitUsd ?? 0) || a6.book.localeCompare(b5.book));
|
|
342241
|
+
return {
|
|
342242
|
+
period,
|
|
342243
|
+
bucket,
|
|
342244
|
+
from: from32,
|
|
342245
|
+
to: now,
|
|
342246
|
+
totals: figures(totals, from32, now),
|
|
342247
|
+
series: starts.map((start, index3) => {
|
|
342248
|
+
const sums = buckets.get(start) ?? new Sums();
|
|
342249
|
+
const endsAt = index3 + 1 < starts.length ? starts[index3 + 1] + offset : now;
|
|
342250
|
+
return { start: start + offset, ...figures(sums, start + offset, endsAt) };
|
|
342251
|
+
}),
|
|
342252
|
+
books: rows,
|
|
342253
|
+
startInventory,
|
|
342254
|
+
estimatedFills,
|
|
342255
|
+
unpricedTokens: [...unpriced].map((symbol3) => spelling2.get(symbol3) ?? symbol3).sort()
|
|
342256
|
+
};
|
|
342257
|
+
}
|
|
342258
|
+
|
|
341400
342259
|
// src/services/server/UiServer.ts
|
|
341401
342260
|
init_Logger();
|
|
341402
342261
|
|
|
@@ -342727,6 +343586,86 @@ init_pairs();
|
|
|
342727
343586
|
init_interpolated_curve();
|
|
342728
343587
|
init_asset_registry();
|
|
342729
343588
|
init_FillerConfigService();
|
|
343589
|
+
|
|
343590
|
+
// src/services/bundler-preflight.ts
|
|
343591
|
+
init_esm_shims();
|
|
343592
|
+
init_chains2();
|
|
343593
|
+
init_interpolated_curve();
|
|
343594
|
+
init_Logger();
|
|
343595
|
+
var BUNDLER_PREFLIGHT_TIMEOUT_MS = 1e4;
|
|
343596
|
+
async function assertBundlersServeEntryPoint(chains2, configService, options = {}) {
|
|
343597
|
+
const timeoutMs = options.timeoutMs ?? BUNDLER_PREFLIGHT_TIMEOUT_MS;
|
|
343598
|
+
const logger8 = moduleLogger(configService.loggers, "bundler-preflight");
|
|
343599
|
+
const failures = await Promise.all(
|
|
343600
|
+
chains2.map(async ({ chainId, bundlerUrl }) => {
|
|
343601
|
+
if (options.watchOnly?.[chainId] === true) return void 0;
|
|
343602
|
+
if (!bundlerUrl?.trim()) return void 0;
|
|
343603
|
+
const entryPoint = configService.getEntryPointAddress(formatChainKey(chainId));
|
|
343604
|
+
if (!entryPoint) return void 0;
|
|
343605
|
+
return checkBundler(chainId, bundlerUrl.trim(), entryPoint, timeoutMs, logger8);
|
|
343606
|
+
})
|
|
343607
|
+
);
|
|
343608
|
+
const messages = failures.filter((failure) => failure !== void 0);
|
|
343609
|
+
if (messages.length > 0) throw new Error(messages.join("; "));
|
|
343610
|
+
}
|
|
343611
|
+
function servesEntryPoint(listed, entryPoint) {
|
|
343612
|
+
return Array.isArray(listed) && listed.some((address) => String(address).toLowerCase() === entryPoint.toLowerCase());
|
|
343613
|
+
}
|
|
343614
|
+
function describeEntryPoints(listed) {
|
|
343615
|
+
return Array.isArray(listed) && listed.length > 0 ? listed.map(String).join(", ") : "none";
|
|
343616
|
+
}
|
|
343617
|
+
function bundlerHost(url2) {
|
|
343618
|
+
try {
|
|
343619
|
+
return new URL(url2).host || "an unparseable URL";
|
|
343620
|
+
} catch {
|
|
343621
|
+
return "an unparseable URL";
|
|
343622
|
+
}
|
|
343623
|
+
}
|
|
343624
|
+
function chainName(chainId) {
|
|
343625
|
+
const label = chainByChainId(chainId)?.label;
|
|
343626
|
+
return label ? `${label} (${formatChainKey(chainId)})` : formatChainKey(chainId);
|
|
343627
|
+
}
|
|
343628
|
+
async function checkBundler(chainId, bundlerUrl, entryPoint, timeoutMs, logger8) {
|
|
343629
|
+
const host = bundlerHost(bundlerUrl);
|
|
343630
|
+
const subject = `Bundler ${host} for ${chainName(chainId)}`;
|
|
343631
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
343632
|
+
let listed;
|
|
343633
|
+
try {
|
|
343634
|
+
listed = await supportedEntryPoints(bundlerUrl, signal);
|
|
343635
|
+
} catch (err) {
|
|
343636
|
+
const reason = signal.aborted ? `timed out after ${timeoutMs}ms` : errorReason(err);
|
|
343637
|
+
logger8.warn(
|
|
343638
|
+
{ chain: formatChainKey(chainId), bundler: host },
|
|
343639
|
+
`${subject} did not answer eth_supportedEntryPoints: ${reason.split(bundlerUrl).join(host)}. Continuing without confirming it serves EntryPoint ${entryPoint}`
|
|
343640
|
+
);
|
|
343641
|
+
return void 0;
|
|
343642
|
+
}
|
|
343643
|
+
if (servesEntryPoint(listed, entryPoint)) return void 0;
|
|
343644
|
+
return `${subject} does not support EntryPoint ${entryPoint}; it lists ${describeEntryPoints(listed)}`;
|
|
343645
|
+
}
|
|
343646
|
+
async function supportedEntryPoints(bundlerUrl, signal) {
|
|
343647
|
+
const response = await fetch(bundlerUrl, {
|
|
343648
|
+
method: "POST",
|
|
343649
|
+
headers: { "Content-Type": "application/json" },
|
|
343650
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_supportedEntryPoints", params: [] }),
|
|
343651
|
+
signal
|
|
343652
|
+
});
|
|
343653
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
343654
|
+
const json = await response.json();
|
|
343655
|
+
if (json.error) throw new Error(json.error.message ?? JSON.stringify(json.error));
|
|
343656
|
+
const { result } = json;
|
|
343657
|
+
if (!Array.isArray(result) || !result.every((address) => typeof address === "string")) {
|
|
343658
|
+
throw new Error("the result is not a list of addresses");
|
|
343659
|
+
}
|
|
343660
|
+
return result;
|
|
343661
|
+
}
|
|
343662
|
+
function errorReason(err) {
|
|
343663
|
+
if (!(err instanceof Error)) return String(err);
|
|
343664
|
+
const { cause } = err;
|
|
343665
|
+
return cause instanceof Error ? `${err.message} (${cause.message})` : err.message;
|
|
343666
|
+
}
|
|
343667
|
+
|
|
343668
|
+
// src/services/server/setup-api.ts
|
|
342730
343669
|
init_wallet3();
|
|
342731
343670
|
|
|
342732
343671
|
// src/services/substrate-key.ts
|
|
@@ -342925,6 +343864,23 @@ async function validateBundler(body, deps) {
|
|
|
342925
343864
|
PROBE_TIMEOUT_MS,
|
|
342926
343865
|
"Bundler probe"
|
|
342927
343866
|
);
|
|
343867
|
+
const chainId = Number(body.chainId);
|
|
343868
|
+
const required2 = Number.isInteger(chainId) ? new ChainConfigService({}).getEntryPointAddress(formatChainKey(chainId)) : void 0;
|
|
343869
|
+
if (!required2) return { ok: true, entryPoints };
|
|
343870
|
+
if (!Array.isArray(entryPoints) || !entryPoints.every((address) => typeof address === "string")) {
|
|
343871
|
+
return {
|
|
343872
|
+
ok: true,
|
|
343873
|
+
entryPoints,
|
|
343874
|
+
warning: `Bundler's eth_supportedEntryPoints answer is not a list of addresses, so it could not be confirmed to support EntryPoint ${required2}, which this chain's solver account uses. Simplex will use it and warn.`
|
|
343875
|
+
};
|
|
343876
|
+
}
|
|
343877
|
+
if (!servesEntryPoint(entryPoints, required2)) {
|
|
343878
|
+
return {
|
|
343879
|
+
ok: true,
|
|
343880
|
+
entryPoints,
|
|
343881
|
+
warning: `Bundler does not support EntryPoint ${required2}, which this chain's solver account uses; it lists ${describeEntryPoints(entryPoints)}. Simplex will refuse to use it.`
|
|
343882
|
+
};
|
|
343883
|
+
}
|
|
342928
343884
|
return { ok: true, entryPoints };
|
|
342929
343885
|
} catch (err) {
|
|
342930
343886
|
return {
|
|
@@ -343639,6 +344595,55 @@ var UiServer = class {
|
|
|
343639
344595
|
if (method !== "GET") return sendJson(res, 405, { error: "Method not allowed" });
|
|
343640
344596
|
return this.handleLimitOrders(res, () => this.operator.limitOrders.books());
|
|
343641
344597
|
}
|
|
344598
|
+
if (path2 === "/api/analytics/profitability") {
|
|
344599
|
+
if (this.mode !== "operator") return sendJson(res, 409, { error: "Filler is not running" });
|
|
344600
|
+
if (method !== "GET") return sendJson(res, 405, { error: "Method not allowed" });
|
|
344601
|
+
const params = new URL(req.url ?? "/", "http://localhost").searchParams;
|
|
344602
|
+
const period = params.get("period") ?? "7d";
|
|
344603
|
+
if (!isProfitPeriod(period)) return sendJson(res, 400, { error: "period must be 7d, 30d, 12w, 12m or all" });
|
|
344604
|
+
const tz = Number(params.get("tz") ?? 0);
|
|
344605
|
+
if (!Number.isInteger(tz) || Math.abs(tz) > 14 * 60) {
|
|
344606
|
+
return sendJson(res, 400, { error: "tz must be a whole number of minutes" });
|
|
344607
|
+
}
|
|
344608
|
+
return this.handleLimitOrders(res, () => this.operator.limitOrders.profitability(period, tz));
|
|
344609
|
+
}
|
|
344610
|
+
if (path2 === "/api/orderbook/snapshot") {
|
|
344611
|
+
if (this.mode !== "operator") return sendJson(res, 409, { error: "Filler is not running" });
|
|
344612
|
+
if (method !== "GET") return sendJson(res, 405, { error: "Method not allowed" });
|
|
344613
|
+
const params = new URL(req.url ?? "/", "http://localhost").searchParams;
|
|
344614
|
+
const book = params.get("book")?.trim();
|
|
344615
|
+
if (!book) return sendJson(res, 400, { error: "A book is required" });
|
|
344616
|
+
return this.handleLimitOrders(
|
|
344617
|
+
res,
|
|
344618
|
+
() => this.operator.limitOrders.orderbookSnapshot(book, {
|
|
344619
|
+
sourceChain: params.get("sourceChain") || void 0,
|
|
344620
|
+
fillChain: params.get("fillChain") || void 0
|
|
344621
|
+
})
|
|
344622
|
+
);
|
|
344623
|
+
}
|
|
344624
|
+
if (path2 === "/api/orderbook/level-orders") {
|
|
344625
|
+
if (this.mode !== "operator") return sendJson(res, 409, { error: "Filler is not running" });
|
|
344626
|
+
if (method !== "GET") return sendJson(res, 405, { error: "Method not allowed" });
|
|
344627
|
+
const params = new URL(req.url ?? "/", "http://localhost").searchParams;
|
|
344628
|
+
const book = params.get("book")?.trim();
|
|
344629
|
+
const side = params.get("side");
|
|
344630
|
+
const fillChain = params.get("fillChain")?.trim();
|
|
344631
|
+
const priceBucket = params.get("priceBucket")?.trim();
|
|
344632
|
+
if (!book) return sendJson(res, 400, { error: "A book is required" });
|
|
344633
|
+
if (side !== "BID" && side !== "ASK") return sendJson(res, 400, { error: "side must be BID or ASK" });
|
|
344634
|
+
if (!fillChain) return sendJson(res, 400, { error: "A fill chain is required" });
|
|
344635
|
+
if (!priceBucket || !/^\d+$/.test(priceBucket))
|
|
344636
|
+
return sendJson(res, 400, { error: "priceBucket must be an integer" });
|
|
344637
|
+
return this.handleLimitOrders(
|
|
344638
|
+
res,
|
|
344639
|
+
() => this.operator.limitOrders.orderbookLevelOrders(book, {
|
|
344640
|
+
side,
|
|
344641
|
+
fillChain,
|
|
344642
|
+
priceBucket,
|
|
344643
|
+
sourceChain: params.get("sourceChain") || void 0
|
|
344644
|
+
})
|
|
344645
|
+
);
|
|
344646
|
+
}
|
|
343642
344647
|
const limitOrderMatch = path2.match(/^\/api\/limit-orders\/([\w-]+)$/);
|
|
343643
344648
|
if (limitOrderMatch) {
|
|
343644
344649
|
if (this.mode !== "operator") return sendJson(res, 409, { error: "Filler is not running" });
|
|
@@ -345000,6 +346005,7 @@ var CacheService = class {
|
|
|
345000
346005
|
})),
|
|
345001
346006
|
partialFill: plan.partialFill,
|
|
345002
346007
|
profit: plan.profit,
|
|
346008
|
+
...plan.inputDecimals !== void 0 ? { inputDecimals: plan.inputDecimals } : {},
|
|
345003
346009
|
...plan.budget ? { budget: budgetFromCache(plan.budget) } : {}
|
|
345004
346010
|
}));
|
|
345005
346011
|
} catch (error) {
|
|
@@ -345030,6 +346036,7 @@ var CacheService = class {
|
|
|
345030
346036
|
})),
|
|
345031
346037
|
partialFill: plan.partialFill,
|
|
345032
346038
|
profit: plan.profit,
|
|
346039
|
+
...plan.inputDecimals !== void 0 ? { inputDecimals: plan.inputDecimals } : {},
|
|
345033
346040
|
...plan.budget ? { budget: budgetToCache(plan.budget) } : {}
|
|
345034
346041
|
})),
|
|
345035
346042
|
timestamp: Date.now()
|
|
@@ -348917,9 +349924,9 @@ var INTENT_GATEWAY_V2_ABI = [
|
|
|
348917
349924
|
internalType: "bytes32"
|
|
348918
349925
|
},
|
|
348919
349926
|
{
|
|
348920
|
-
name: "
|
|
348921
|
-
type: "
|
|
348922
|
-
internalType: "
|
|
349927
|
+
name: "userOpHash",
|
|
349928
|
+
type: "bytes32",
|
|
349929
|
+
internalType: "bytes32"
|
|
348923
349930
|
},
|
|
348924
349931
|
{
|
|
348925
349932
|
name: "signature",
|
|
@@ -350307,10 +351314,13 @@ var LIMIT_ORDER_CALL_GAS_LIMIT = 500000n;
|
|
|
350307
351314
|
var LIMIT_ORDER_VERIFICATION_GAS_LIMIT = 150000n;
|
|
350308
351315
|
var LIMIT_ORDER_PRE_VERIFICATION_GAS = 50000n;
|
|
350309
351316
|
var BID_DISCOVERY_PAD_SECONDS = 30;
|
|
351317
|
+
var BLOCK_TIME_SAMPLE_BLOCKS = 1000n;
|
|
351318
|
+
var FALLBACK_BLOCK_TIME_SECONDS = 2;
|
|
350310
351319
|
var ContractInteractionService = class {
|
|
350311
351320
|
constructor(clientManager, configService, signer, sharedCacheService) {
|
|
350312
351321
|
this.clientManager = clientManager;
|
|
350313
351322
|
this.sdkHelperCache = /* @__PURE__ */ new Map();
|
|
351323
|
+
this.blockTimes = /* @__PURE__ */ new Map();
|
|
350314
351324
|
this.logger = moduleLogger(configService.loggers, "contract-service");
|
|
350315
351325
|
this.configService = configService;
|
|
350316
351326
|
this.cacheService = sharedCacheService || new CacheService();
|
|
@@ -350370,11 +351380,20 @@ var ContractInteractionService = class {
|
|
|
350370
351380
|
try {
|
|
350371
351381
|
const chainIds = this.configService.getConfiguredChainIds();
|
|
350372
351382
|
const chainNames = chainIds.map((id2) => `EVM-${id2}`);
|
|
350373
|
-
|
|
351383
|
+
await Promise.all(
|
|
351384
|
+
chainNames.map(async (chainName2) => {
|
|
351385
|
+
try {
|
|
351386
|
+
await this.blockTimeSeconds(chainName2);
|
|
351387
|
+
} catch (err) {
|
|
351388
|
+
this.logger.warn({ err, chain: chainName2 }, "Could not measure the block time at startup");
|
|
351389
|
+
}
|
|
351390
|
+
})
|
|
351391
|
+
);
|
|
351392
|
+
for (const chainName2 of chainNames) {
|
|
350374
351393
|
try {
|
|
350375
|
-
await this.getFeeTokenWithDecimals(
|
|
351394
|
+
await this.getFeeTokenWithDecimals(chainName2);
|
|
350376
351395
|
} catch (err) {
|
|
350377
|
-
this.logger.warn({ err, chain:
|
|
351396
|
+
this.logger.warn({ err, chain: chainName2 }, "Could not prewarm fee token decimals");
|
|
350378
351397
|
}
|
|
350379
351398
|
}
|
|
350380
351399
|
for (const destChain of chainNames) {
|
|
@@ -350959,18 +351978,59 @@ var ContractInteractionService = class {
|
|
|
350959
351978
|
*
|
|
350960
351979
|
* Operators configure seconds because that is the unit the risk is actually in, but the
|
|
350961
351980
|
* contract compares against block numbers so `order.deadline` and this read the same
|
|
350962
|
-
* clock. The conversion uses the chain's
|
|
350963
|
-
* up, since erring long costs a slightly stale quote while erring
|
|
350964
|
-
* winnable bids.
|
|
351981
|
+
* clock. The conversion uses the chain's block time from {@link blockTimeSeconds}; it is
|
|
351982
|
+
* deliberately rounded up, since erring long costs a slightly stale quote while erring
|
|
351983
|
+
* short silently drops winnable bids.
|
|
350965
351984
|
*/
|
|
350966
351985
|
async bidValidUntilBlock(chain2) {
|
|
350967
351986
|
const client = this.clientManager.getPublicClient(chain2);
|
|
350968
|
-
const currentBlock = await client.getBlockNumber();
|
|
350969
|
-
const blockTimeMs = client.chain?.blockTime;
|
|
350970
|
-
const blockTimeSec = blockTimeMs ? blockTimeMs / 1e3 : 2;
|
|
351987
|
+
const [currentBlock, blockTimeSec] = await Promise.all([client.getBlockNumber(), this.blockTimeSeconds(chain2)]);
|
|
350971
351988
|
const windowSec = this.configService.getBidValiditySeconds() + BID_DISCOVERY_PAD_SECONDS;
|
|
350972
351989
|
return currentBlock + BigInt(Math.ceil(windowSec / blockTimeSec));
|
|
350973
351990
|
}
|
|
351991
|
+
/**
|
|
351992
|
+
* Seconds per block on `chain`. Measured once, when simplex starts ({@link initCache}), and
|
|
351993
|
+
* kept until it stops. A chain with no measurement yet, because it was added later or its
|
|
351994
|
+
* blocks could not be read at startup, is measured at its first bid.
|
|
351995
|
+
*
|
|
351996
|
+
* The nominal `Chain.blockTime` cannot be relied on alone: it goes stale when a chain
|
|
351997
|
+
* speeds up (BSC makes a block every 0.45s against a declared 0.75s) and some chains
|
|
351998
|
+
* declare none. Converting at a slower block time than the chain's ends a bid early, so
|
|
351999
|
+
* the faster of the measured and the declared figure is used, and a stalled or idle
|
|
352000
|
+
* stretch in the sample never shortens a bid.
|
|
352001
|
+
*
|
|
352002
|
+
* Blocks that cannot be read fall back to the declared figure, then to
|
|
352003
|
+
* {@link FALLBACK_BLOCK_TIME_SECONDS}. That answer is not kept.
|
|
352004
|
+
*/
|
|
352005
|
+
blockTimeSeconds(chain2) {
|
|
352006
|
+
const known3 = this.blockTimes.get(chain2);
|
|
352007
|
+
if (known3) return known3;
|
|
352008
|
+
const client = this.clientManager.getPublicClient(chain2);
|
|
352009
|
+
const declaredMs = client.chain?.blockTime;
|
|
352010
|
+
const declared = declaredMs ? declaredMs / 1e3 : void 0;
|
|
352011
|
+
const seconds = this.measureBlockTimeSeconds(client).then((measured) => declared ? Math.min(measured, declared) : measured).catch((err) => {
|
|
352012
|
+
this.blockTimes.delete(chain2);
|
|
352013
|
+
const fallback2 = declared ?? FALLBACK_BLOCK_TIME_SECONDS;
|
|
352014
|
+
this.logger.warn(
|
|
352015
|
+
{ err, chain: chain2, seconds: fallback2 },
|
|
352016
|
+
"Could not measure the block time; using the declared one"
|
|
352017
|
+
);
|
|
352018
|
+
return fallback2;
|
|
352019
|
+
});
|
|
352020
|
+
this.blockTimes.set(chain2, seconds);
|
|
352021
|
+
return seconds;
|
|
352022
|
+
}
|
|
352023
|
+
/** The average block time over the chain's last {@link BLOCK_TIME_SAMPLE_BLOCKS} blocks, in seconds. */
|
|
352024
|
+
async measureBlockTimeSeconds(client) {
|
|
352025
|
+
const head = await client.getBlock({ blockTag: "latest" });
|
|
352026
|
+
const span = head.number < BLOCK_TIME_SAMPLE_BLOCKS ? head.number : BLOCK_TIME_SAMPLE_BLOCKS;
|
|
352027
|
+
const tail = await client.getBlock({ blockNumber: head.number - span });
|
|
352028
|
+
const measured = Number(head.timestamp - tail.timestamp) / Number(span);
|
|
352029
|
+
if (!Number.isFinite(measured) || measured <= 0) {
|
|
352030
|
+
throw new Error(`${span} blocks span ${head.timestamp - tail.timestamp}s`);
|
|
352031
|
+
}
|
|
352032
|
+
return measured;
|
|
352033
|
+
}
|
|
350974
352034
|
/**
|
|
350975
352035
|
* Builds the signed, never-executed UserOperation that carries one limit order
|
|
350976
352036
|
* to the HyperFX orderbook.
|
|
@@ -351154,6 +352214,8 @@ init_Logger();
|
|
|
351154
352214
|
var FALLBACK_VERIFICATION_GAS_LIMIT = 250000n;
|
|
351155
352215
|
var FALLBACK_CALL_GAS_LIMIT = 1500000n;
|
|
351156
352216
|
var FALLBACK_PRE_VERIFICATION_GAS = 150000n;
|
|
352217
|
+
var PRIORITY_FEE_BUMP_PERCENT = 8n;
|
|
352218
|
+
var MAX_FEE_BUMP_PERCENT = 10n;
|
|
351157
352219
|
var UserOpSender = class {
|
|
351158
352220
|
constructor(clientManager, configService, signer) {
|
|
351159
352221
|
this.clientManager = clientManager;
|
|
@@ -351334,7 +352396,11 @@ var UserOpSender = class {
|
|
|
351334
352396
|
);
|
|
351335
352397
|
return userOp;
|
|
351336
352398
|
}
|
|
351337
|
-
/**
|
|
352399
|
+
/**
|
|
352400
|
+
* Mirrors the gas-price selection used by the delegation and fill paths: Pimlico's and
|
|
352401
|
+
* Alchemy's own pricing, otherwise the chain's gas price raised to the priority fee a
|
|
352402
|
+
* rundler bundler requires, when the bundler gives one.
|
|
352403
|
+
*/
|
|
351338
352404
|
async getGasPrice(bundlerUrl, publicClient, chainId) {
|
|
351339
352405
|
const lower2 = bundlerUrl.toLowerCase();
|
|
351340
352406
|
if (lower2.includes("pimlico.io")) {
|
|
@@ -351346,19 +352412,33 @@ var UserOpSender = class {
|
|
|
351346
352412
|
return { maxFeePerGas: BigInt(res.fast.maxFeePerGas), maxPriorityFeePerGas: BigInt(res.fast.maxPriorityFeePerGas) };
|
|
351347
352413
|
}
|
|
351348
352414
|
if (lower2.includes("alchemy.com")) {
|
|
351349
|
-
const [
|
|
352415
|
+
const [rundlerPriorityFee2, latestBlock2] = await Promise.all([
|
|
351350
352416
|
this.sendBundlerRpc(bundlerUrl, BundlerMethod.RUNDLER_MAX_PRIORITY_FEE_PER_GAS, []),
|
|
351351
352417
|
publicClient.getBlock({ blockTag: "latest" })
|
|
351352
352418
|
]);
|
|
351353
|
-
const baseFeePerGas =
|
|
352419
|
+
const baseFeePerGas = latestBlock2.baseFeePerGas ?? await publicClient.getGasPrice();
|
|
351354
352420
|
const isArbitrum = BigInt(chainId) === 42161n;
|
|
351355
352421
|
const prioBump = isArbitrum ? 0n : 25n;
|
|
351356
|
-
const maxPriorityFeePerGas = BigInt(
|
|
352422
|
+
const maxPriorityFeePerGas = BigInt(rundlerPriorityFee2) + BigInt(rundlerPriorityFee2) * prioBump / 100n;
|
|
351357
352423
|
const bufferedBaseFee = baseFeePerGas + baseFeePerGas * 50n / 100n;
|
|
351358
352424
|
return { maxFeePerGas: bufferedBaseFee + maxPriorityFeePerGas, maxPriorityFeePerGas };
|
|
351359
352425
|
}
|
|
351360
|
-
const gasPrice = await
|
|
351361
|
-
|
|
352426
|
+
const [gasPrice, rundlerPriorityFee] = await Promise.all([
|
|
352427
|
+
publicClient.getGasPrice(),
|
|
352428
|
+
fetchRundlerPriorityFee(bundlerUrl)
|
|
352429
|
+
]);
|
|
352430
|
+
const fees4 = {
|
|
352431
|
+
maxFeePerGas: gasPrice + gasPrice * MAX_FEE_BUMP_PERCENT / 100n,
|
|
352432
|
+
maxPriorityFeePerGas: gasPrice + gasPrice * PRIORITY_FEE_BUMP_PERCENT / 100n
|
|
352433
|
+
};
|
|
352434
|
+
if (rundlerPriorityFee === null) return fees4;
|
|
352435
|
+
const latestBlock = await publicClient.getBlock({ blockTag: "latest" });
|
|
352436
|
+
return applyRundlerPriorityFee(fees4, {
|
|
352437
|
+
rundlerPriorityFee,
|
|
352438
|
+
baseFeePerGas: latestBlock.baseFeePerGas ?? gasPrice,
|
|
352439
|
+
priorityFeeBumpPercent: PRIORITY_FEE_BUMP_PERCENT,
|
|
352440
|
+
maxFeeBumpPercent: MAX_FEE_BUMP_PERCENT
|
|
352441
|
+
});
|
|
351362
352442
|
}
|
|
351363
352443
|
async sendBundlerRpc(bundlerUrl, method, params) {
|
|
351364
352444
|
const response = await fetch(bundlerUrl, {
|
|
@@ -366777,8 +367857,8 @@ var validateBalanceForTransaction = async (params) => {
|
|
|
366777
367857
|
}, operationContext);
|
|
366778
367858
|
const balance = await balancePrepared.execute();
|
|
366779
367859
|
if (BigInt(balance) < BigInt(amount)) {
|
|
366780
|
-
const
|
|
366781
|
-
throw createInsufficientTokenBalanceError(
|
|
367860
|
+
const chainName2 = extractChainInfo(operationContext.chain).name;
|
|
367861
|
+
throw createInsufficientTokenBalanceError(chainName2, token, {
|
|
366782
367862
|
balance: balance.toString(),
|
|
366783
367863
|
amount,
|
|
366784
367864
|
tokenAddress,
|
|
@@ -366793,8 +367873,8 @@ var validateNativeBalanceForTransaction = async (params) => {
|
|
|
366793
367873
|
}, operationContext);
|
|
366794
367874
|
const balance = await balancePrepared.execute();
|
|
366795
367875
|
if (BigInt(balance) === 0n) {
|
|
366796
|
-
const
|
|
366797
|
-
throw createInsufficientGasError(
|
|
367876
|
+
const chainName2 = extractChainInfo(operationContext.chain).name;
|
|
367877
|
+
throw createInsufficientGasError(chainName2, {
|
|
366798
367878
|
balance: "0",
|
|
366799
367879
|
walletAddress: operationContext.address
|
|
366800
367880
|
});
|
|
@@ -384432,7 +385512,12 @@ var IntentFiller = class {
|
|
|
384432
385512
|
else cache.clearFundingPrepends(order.id);
|
|
384433
385513
|
}
|
|
384434
385514
|
reservation = await this.holdAll([
|
|
384435
|
-
{
|
|
385515
|
+
{
|
|
385516
|
+
limitOrderId: plan.limitOrderId,
|
|
385517
|
+
payout: plan.payout,
|
|
385518
|
+
take: plan.fillerInputs[plan.leg]?.amount,
|
|
385519
|
+
takeDecimals: plan.inputDecimals
|
|
385520
|
+
}
|
|
384436
385521
|
]);
|
|
384437
385522
|
if (reservation.length === 0) {
|
|
384438
385523
|
this.logger.info(
|
|
@@ -384602,7 +385687,8 @@ var IntentFiller = class {
|
|
|
384602
385687
|
taken.push({
|
|
384603
385688
|
limitOrderId: hold.limitOrderId,
|
|
384604
385689
|
amount,
|
|
384605
|
-
...hold.take !== void 0 ? { take: hold.take.toString() } : {}
|
|
385690
|
+
...hold.take !== void 0 ? { take: hold.take.toString() } : {},
|
|
385691
|
+
...hold.takeDecimals !== void 0 ? { takeDecimals: hold.takeDecimals } : {}
|
|
384606
385692
|
});
|
|
384607
385693
|
}
|
|
384608
385694
|
return taken;
|
|
@@ -384629,6 +385715,7 @@ var IntentFiller = class {
|
|
|
384629
385715
|
}
|
|
384630
385716
|
const settled = executedHold(claimed, delivered.scaled, released);
|
|
384631
385717
|
const charged = chargedFor(settled, delivered, released);
|
|
385718
|
+
const takenIn = released > 0n && settled.takeDecimals !== void 0 ? toScaled(released, settled.takeDecimals) : null;
|
|
384632
385719
|
const settledBid = rows.find(
|
|
384633
385720
|
(row) => row.reservations.some(
|
|
384634
385721
|
(hold) => hold.limitOrderId === settled.limitOrderId && hold.amount === settled.amount && hold.take === settled.take
|
|
@@ -384647,6 +385734,7 @@ var IntentFiller = class {
|
|
|
384647
385734
|
commitment,
|
|
384648
385735
|
bid: settledBid,
|
|
384649
385736
|
amount: share.toString(),
|
|
385737
|
+
amountIn: takenIn?.toString() ?? null,
|
|
384650
385738
|
transactionHash: transactionHash ?? null
|
|
384651
385739
|
});
|
|
384652
385740
|
}
|
|
@@ -384799,45 +385887,6 @@ init_esm();
|
|
|
384799
385887
|
init_Logger();
|
|
384800
385888
|
init_asset_registry();
|
|
384801
385889
|
init_decimal();
|
|
384802
|
-
|
|
384803
|
-
// src/orderbook/usd.ts
|
|
384804
|
-
init_esm_shims();
|
|
384805
|
-
init_decimal();
|
|
384806
|
-
init_asset_registry();
|
|
384807
|
-
function limitOrderUsdEdges(orders) {
|
|
384808
|
-
return orders.filter((order) => normalizeSymbol(order.base) !== normalizeSymbol(order.quote)).map((order) => ({
|
|
384809
|
-
base: normalizeSymbol(order.base),
|
|
384810
|
-
quote: normalizeSymbol(order.quote),
|
|
384811
|
-
rate: new Decimal(order.price).div(ORDERBOOK_SCALE2.toString())
|
|
384812
|
-
})).filter((edge) => edge.rate.isFinite() && edge.rate.gt(0));
|
|
384813
|
-
}
|
|
384814
|
-
function usdFactorsFrom(edges) {
|
|
384815
|
-
const factors = /* @__PURE__ */ new Map();
|
|
384816
|
-
for (const symbol3 of USD_STABLE_SYMBOLS) factors.set(symbol3, new Decimal(1));
|
|
384817
|
-
const ordered = [...edges].sort((a6, b5) => a6.base.localeCompare(b5.base) || a6.quote.localeCompare(b5.quote));
|
|
384818
|
-
let grew = true;
|
|
384819
|
-
while (grew) {
|
|
384820
|
-
grew = false;
|
|
384821
|
-
for (const edge of ordered) {
|
|
384822
|
-
const usdBase = factors.get(edge.base);
|
|
384823
|
-
const usdQuote = factors.get(edge.quote);
|
|
384824
|
-
if (usdBase && !usdQuote) {
|
|
384825
|
-
factors.set(edge.quote, usdBase.div(edge.rate));
|
|
384826
|
-
grew = true;
|
|
384827
|
-
} else if (usdQuote && !usdBase) {
|
|
384828
|
-
factors.set(edge.base, usdQuote.mul(edge.rate));
|
|
384829
|
-
grew = true;
|
|
384830
|
-
}
|
|
384831
|
-
}
|
|
384832
|
-
}
|
|
384833
|
-
return factors;
|
|
384834
|
-
}
|
|
384835
|
-
function usdValueOf(factors, symbol3, amount) {
|
|
384836
|
-
const factor = factors.get(normalizeSymbol(symbol3));
|
|
384837
|
-
return factor ? amount.mul(factor) : null;
|
|
384838
|
-
}
|
|
384839
|
-
|
|
384840
|
-
// src/strategies/fx.ts
|
|
384841
385890
|
function adjustDecimalsFloor(amount, fromDecimals, toDecimals) {
|
|
384842
385891
|
if (fromDecimals === toDecimals) return amount;
|
|
384843
385892
|
if (fromDecimals < toDecimals) return amount * BigInt(10 ** (toDecimals - fromDecimals));
|
|
@@ -385318,6 +386367,7 @@ var FXFiller = class _FXFiller {
|
|
|
385318
386367
|
payout: toScaled(finalOutputAmount, outputDecimals),
|
|
385319
386368
|
fillerOutputs,
|
|
385320
386369
|
fillerInputs,
|
|
386370
|
+
inputDecimals,
|
|
385321
386371
|
fundingCalls: [...fundingCalls],
|
|
385322
386372
|
partialFill,
|
|
385323
386373
|
profit: totalProfit,
|
|
@@ -386611,8 +387661,8 @@ async function bootFiller(config5, options) {
|
|
|
386611
387661
|
};
|
|
386612
387662
|
const configService = new FillerConfigService(resolvedChains, fillerConfigForService, options.loggers);
|
|
386613
387663
|
const chainConfigs2 = resolvedChains.map((chain2) => {
|
|
386614
|
-
const
|
|
386615
|
-
return configService.getChainConfig(
|
|
387664
|
+
const chainName2 = `EVM-${chain2.chainId}`;
|
|
387665
|
+
return configService.getChainConfig(chainName2);
|
|
386616
387666
|
});
|
|
386617
387667
|
let watchOnlyConfig;
|
|
386618
387668
|
const globalWatchOnly = options.watchOnlyOverride === true || config5.simplex.watchOnly === true;
|
|
@@ -386650,6 +387700,8 @@ async function bootFiller(config5, options) {
|
|
|
386650
387700
|
"A signer is required unless every chain is watch-only: pass `signer` to Simplex.start (privateKeySigner, secretPhraseSigner, turnkeySigner, mpcVaultSigner, viemSigner, or your own Signer implementation). Running the binary? Configure it under [simplex.signer]."
|
|
386651
387701
|
);
|
|
386652
387702
|
}
|
|
387703
|
+
logger8.info("Checking each bundler serves its chain's EntryPoint...");
|
|
387704
|
+
await assertBundlersServeEntryPoint(resolvedChains, configService, { watchOnly: watchOnlyConfig });
|
|
386653
387705
|
const chainClientManager = new ChainClientManager(configService, options.signer);
|
|
386654
387706
|
const runtimeSigner = chainClientManager.getSigner();
|
|
386655
387707
|
if (options.signer) {
|
|
@@ -386812,9 +387864,10 @@ async function bootFiller(config5, options) {
|
|
|
386812
387864
|
const activity = new ActivityRecorder(options.data.activity, options.loggers, { describeToken });
|
|
386813
387865
|
activity.attach(intentFiller.monitor);
|
|
386814
387866
|
const network = resolvedChains.some((chain2) => chainByChainId(chain2.chainId)?.network === "testnet") ? "testnet" : "mainnet";
|
|
387867
|
+
const indexerUrl = config5.simplex.indexerUrl ?? DEFAULT_INDEXER_URLS[network];
|
|
386815
387868
|
void backfillOrderSummaries({
|
|
386816
387869
|
store: options.data.activity,
|
|
386817
|
-
indexerUrl
|
|
387870
|
+
indexerUrl,
|
|
386818
387871
|
fillerAddress: runtimeSigner.address,
|
|
386819
387872
|
describeToken,
|
|
386820
387873
|
onUpdated: (rows) => {
|
|
@@ -386839,10 +387892,10 @@ async function bootFiller(config5, options) {
|
|
|
386839
387892
|
const token1 = {};
|
|
386840
387893
|
for (const pair of config5.pairs ?? []) {
|
|
386841
387894
|
if (normalizeSymbol(pair.token0) === normalizeSymbol(pair.token1)) continue;
|
|
386842
|
-
for (const
|
|
386843
|
-
const address = assetRegistry.getAddress(pair.token1,
|
|
387895
|
+
for (const chainName2 of configuredChainNames) {
|
|
387896
|
+
const address = assetRegistry.getAddress(pair.token1, chainName2);
|
|
386844
387897
|
if (!address) continue;
|
|
386845
|
-
const list = token1[
|
|
387898
|
+
const list = token1[chainName2] ?? (token1[chainName2] = []);
|
|
386846
387899
|
if (!list.includes(address)) list.push(address);
|
|
386847
387900
|
}
|
|
386848
387901
|
}
|
|
@@ -386880,6 +387933,15 @@ async function bootFiller(config5, options) {
|
|
|
386880
387933
|
vaultVenue?.startSweeping();
|
|
386881
387934
|
started.push(() => balanceProvider.stop());
|
|
386882
387935
|
await balanceProvider.start();
|
|
387936
|
+
if (options.signer) {
|
|
387937
|
+
const inventoryRecorder = new InventoryRecorder(
|
|
387938
|
+
options.data.inventory,
|
|
387939
|
+
balanceProvider,
|
|
387940
|
+
moduleLogger(options.loggers, "inventory")
|
|
387941
|
+
);
|
|
387942
|
+
started.push(() => inventoryRecorder.stop());
|
|
387943
|
+
inventoryRecorder.start();
|
|
387944
|
+
}
|
|
386883
387945
|
const watchOnlyChains = watchOnlyConfig ? Object.entries(watchOnlyConfig).filter(([, value]) => value === true).map(([chainId]) => Number.parseInt(chainId, 10)) : [];
|
|
386884
387946
|
logger8.info(
|
|
386885
387947
|
{
|
|
@@ -386925,6 +387987,8 @@ async function bootFiller(config5, options) {
|
|
|
386925
387987
|
rebalancingService,
|
|
386926
387988
|
resolvedChains,
|
|
386927
387989
|
fillerAddress: runtimeSigner.address,
|
|
387990
|
+
indexerUrl,
|
|
387991
|
+
describeToken,
|
|
386928
387992
|
watchOnly: watchOnlyConfig,
|
|
386929
387993
|
config: config5,
|
|
386930
387994
|
configPath: options.configPath,
|
|
@@ -387208,10 +388272,20 @@ var MemoryLimitOrderStore = class {
|
|
|
387208
388272
|
commitment: fill.commitment,
|
|
387209
388273
|
bid: fill.bid ?? null,
|
|
387210
388274
|
amount: fill.amount,
|
|
388275
|
+
amountIn: fill.amountIn ?? null,
|
|
387211
388276
|
transactionHash: fill.transactionHash ?? null,
|
|
387212
388277
|
filledAt: sqliteDatetime(/* @__PURE__ */ new Date())
|
|
387213
388278
|
});
|
|
387214
388279
|
}
|
|
388280
|
+
async fillHistory() {
|
|
388281
|
+
return this.fillRows.flatMap((fill) => {
|
|
388282
|
+
const order = this.orders.get(fill.limitOrderId);
|
|
388283
|
+
if (!order) return [];
|
|
388284
|
+
const { id: id2, limitOrderId, amount, amountIn, filledAt } = fill;
|
|
388285
|
+
const { book, base: base4, quote, side, price } = order;
|
|
388286
|
+
return [{ id: id2, limitOrderId, book, base: base4, quote, side, price, amount, amountIn, filledAt }];
|
|
388287
|
+
});
|
|
388288
|
+
}
|
|
387215
388289
|
async fills(limitOrderId, limit = 100) {
|
|
387216
388290
|
return this.fillRows.filter((fill) => fill.limitOrderId === limitOrderId).slice(-capLimit(limit)).reverse().map((fill) => ({ ...fill }));
|
|
387217
388291
|
}
|
|
@@ -387226,6 +388300,7 @@ var MemoryLimitOrderStore = class {
|
|
|
387226
388300
|
status: "open",
|
|
387227
388301
|
commitment: null,
|
|
387228
388302
|
orderNonce: order.orderNonce ?? "0",
|
|
388303
|
+
entryPoint: null,
|
|
387229
388304
|
bookExpiresAt: null,
|
|
387230
388305
|
bookPrice: null,
|
|
387231
388306
|
lastError: null,
|
|
@@ -387318,12 +388393,29 @@ var MemoryStateStore = class {
|
|
|
387318
388393
|
this.state = { ...state };
|
|
387319
388394
|
}
|
|
387320
388395
|
};
|
|
388396
|
+
var MemoryInventoryStore = class {
|
|
388397
|
+
constructor() {
|
|
388398
|
+
this.rows = [];
|
|
388399
|
+
}
|
|
388400
|
+
async record(balances) {
|
|
388401
|
+
this.rows.push({ id: this.rows.length + 1, takenAt: sqliteDatetime(/* @__PURE__ */ new Date()), balances: { ...balances } });
|
|
388402
|
+
}
|
|
388403
|
+
async latest() {
|
|
388404
|
+
const last = this.rows[this.rows.length - 1];
|
|
388405
|
+
return last ? { ...last, balances: { ...last.balances } } : null;
|
|
388406
|
+
}
|
|
388407
|
+
async since(from32) {
|
|
388408
|
+
const cutoff = sqliteDatetime(from32);
|
|
388409
|
+
return this.rows.filter((row) => row.takenAt >= cutoff).map((row) => ({ ...row, balances: { ...row.balances } }));
|
|
388410
|
+
}
|
|
388411
|
+
};
|
|
387321
388412
|
var MemoryDataStore = class {
|
|
387322
388413
|
constructor() {
|
|
387323
388414
|
this.bids = new MemoryBidStore();
|
|
387324
388415
|
this.activity = new MemoryActivityStore();
|
|
387325
388416
|
this.state = new MemoryStateStore();
|
|
387326
388417
|
this.limitOrders = new MemoryLimitOrderStore();
|
|
388418
|
+
this.inventory = new MemoryInventoryStore();
|
|
387327
388419
|
}
|
|
387328
388420
|
};
|
|
387329
388421
|
|
|
@@ -387935,6 +389027,107 @@ var OrderScanner = class _OrderScanner {
|
|
|
387935
389027
|
}
|
|
387936
389028
|
};
|
|
387937
389029
|
|
|
389030
|
+
// src/data/indexer-inventory.ts
|
|
389031
|
+
init_esm_shims();
|
|
389032
|
+
init_esm();
|
|
389033
|
+
var READ_TIMEOUT_MS = 1e4;
|
|
389034
|
+
var SETTLED_AFTER_MS = 10 * 6e4;
|
|
389035
|
+
var BATCH = 40;
|
|
389036
|
+
var MAX_KEPT = 2e3;
|
|
389037
|
+
var IndexerInventory = class {
|
|
389038
|
+
constructor(options) {
|
|
389039
|
+
this.options = options;
|
|
389040
|
+
this.kept = /* @__PURE__ */ new Map();
|
|
389041
|
+
this.described = /* @__PURE__ */ new Map();
|
|
389042
|
+
this.fetch = options.fetch ?? fetch;
|
|
389043
|
+
}
|
|
389044
|
+
/**
|
|
389045
|
+
* A reading for each of `instants` the indexer could answer for. Never rejects: an instant it
|
|
389046
|
+
* could not be asked about is simply missing from the answer.
|
|
389047
|
+
*/
|
|
389048
|
+
async at(instants, now) {
|
|
389049
|
+
const readings = [];
|
|
389050
|
+
const wanted = [];
|
|
389051
|
+
for (const instant of new Set(instants)) {
|
|
389052
|
+
const kept = this.kept.get(instant);
|
|
389053
|
+
if (kept) readings.push(kept);
|
|
389054
|
+
else wanted.push(instant);
|
|
389055
|
+
}
|
|
389056
|
+
try {
|
|
389057
|
+
for (let index3 = 0; index3 < wanted.length; index3 += BATCH) {
|
|
389058
|
+
for (const reading of await this.read(wanted.slice(index3, index3 + BATCH))) {
|
|
389059
|
+
readings.push(reading);
|
|
389060
|
+
if (reading.at <= now - SETTLED_AFTER_MS) this.keep(reading);
|
|
389061
|
+
}
|
|
389062
|
+
}
|
|
389063
|
+
} catch (err) {
|
|
389064
|
+
this.options.logger.warn(
|
|
389065
|
+
{ err: err instanceof Error ? err.message : String(err) },
|
|
389066
|
+
"Could not read inventory from the indexer; carrying records by fills and sends alone"
|
|
389067
|
+
);
|
|
389068
|
+
}
|
|
389069
|
+
return readings;
|
|
389070
|
+
}
|
|
389071
|
+
keep(reading) {
|
|
389072
|
+
if (this.kept.size >= MAX_KEPT) this.kept.clear();
|
|
389073
|
+
this.kept.set(reading.at, reading);
|
|
389074
|
+
}
|
|
389075
|
+
/** One request for several instants, each its own aliased query at that moment in history. */
|
|
389076
|
+
async read(instants) {
|
|
389077
|
+
const queries = instants.map(
|
|
389078
|
+
(instant, index3) => `r${index3}: solverInventories(filter: { solver: { equalTo: $solver } }, blockHeight: "${Math.floor(instant)}", first: 1000) { nodes { chain tokenAddress balance } }`
|
|
389079
|
+
);
|
|
389080
|
+
const response = await this.fetch(this.options.indexerUrl, {
|
|
389081
|
+
method: "POST",
|
|
389082
|
+
headers: { "content-type": "application/json" },
|
|
389083
|
+
body: JSON.stringify({
|
|
389084
|
+
query: `query SolverInventory($solver: String!) {
|
|
389085
|
+
${queries.join("\n")}
|
|
389086
|
+
}`,
|
|
389087
|
+
variables: { solver: this.options.solver.toLowerCase() }
|
|
389088
|
+
}),
|
|
389089
|
+
signal: AbortSignal.timeout(READ_TIMEOUT_MS)
|
|
389090
|
+
});
|
|
389091
|
+
if (!response.ok) throw new Error(`Indexer responded ${response.status}`);
|
|
389092
|
+
const body = await response.json();
|
|
389093
|
+
if (body.errors?.length) throw new Error(body.errors.map((error) => error.message).join("; "));
|
|
389094
|
+
const readings = [];
|
|
389095
|
+
for (const [index3, instant] of instants.entries()) {
|
|
389096
|
+
const rows = body.data?.[`r${index3}`]?.nodes;
|
|
389097
|
+
if (rows) readings.push(await this.readingOf(instant, rows));
|
|
389098
|
+
}
|
|
389099
|
+
return readings;
|
|
389100
|
+
}
|
|
389101
|
+
async readingOf(at, rows) {
|
|
389102
|
+
const balances = {};
|
|
389103
|
+
const chains2 = {};
|
|
389104
|
+
for (const row of rows) {
|
|
389105
|
+
const token = await this.describe(row.chain, row.tokenAddress);
|
|
389106
|
+
if (!token) continue;
|
|
389107
|
+
let amount;
|
|
389108
|
+
try {
|
|
389109
|
+
amount = Number(formatUnits(BigInt(row.balance), token.decimals));
|
|
389110
|
+
} catch {
|
|
389111
|
+
continue;
|
|
389112
|
+
}
|
|
389113
|
+
balances[token.symbol] = (balances[token.symbol] ?? 0) + amount;
|
|
389114
|
+
chains2[token.symbol] = [...chains2[token.symbol] ?? [], row.chain];
|
|
389115
|
+
}
|
|
389116
|
+
return { at, balances, chains: chains2 };
|
|
389117
|
+
}
|
|
389118
|
+
/** A token's symbol and decimals, remembered once both are known. */
|
|
389119
|
+
async describe(chain2, token) {
|
|
389120
|
+
const key = `${chain2}:${token.toLowerCase()}`;
|
|
389121
|
+
const known3 = this.described.get(key);
|
|
389122
|
+
if (known3) return known3;
|
|
389123
|
+
const { symbol: symbol3, decimals } = await this.options.describeToken(chain2, token);
|
|
389124
|
+
if (!symbol3 || decimals === null) return null;
|
|
389125
|
+
const description = { symbol: symbol3, decimals };
|
|
389126
|
+
this.described.set(key, description);
|
|
389127
|
+
return description;
|
|
389128
|
+
}
|
|
389129
|
+
};
|
|
389130
|
+
|
|
387938
389131
|
// src/simplex.ts
|
|
387939
389132
|
var EVENT_MAP = {
|
|
387940
389133
|
newOrder: "order:detected",
|
|
@@ -387980,10 +389173,66 @@ var LimitOrderController = class {
|
|
|
387980
389173
|
]);
|
|
387981
389174
|
return { order, fills, bids };
|
|
387982
389175
|
}
|
|
389176
|
+
/**
|
|
389177
|
+
* What the operator's buys and sells earned over `period`, bucketed on a clock
|
|
389178
|
+
* `tzOffsetMinutes` behind UTC.
|
|
389179
|
+
*
|
|
389180
|
+
* Profit is the change the period's fills made to what the solver holds, and
|
|
389181
|
+
* it is compared with the inventory the period began with. That inventory
|
|
389182
|
+
* comes from the stored snapshots and, when the balances have been read in
|
|
389183
|
+
* full, from what is held now, each carried to the period's start by what
|
|
389184
|
+
* moved between. The indexer says what moved, deposits and withdrawals
|
|
389185
|
+
* included, wherever it has followed the solver; elsewhere the fills and
|
|
389186
|
+
* sends on record stand in. It answers whether or not an orderbook is
|
|
389187
|
+
* configured, and whether or not the indexer does.
|
|
389188
|
+
*/
|
|
389189
|
+
async profitability(period, tzOffsetMinutes = 0) {
|
|
389190
|
+
const now = Date.now();
|
|
389191
|
+
const { data: data4, balanceProvider } = this.runtime;
|
|
389192
|
+
const [fills, snapshots, ledger] = await Promise.all([
|
|
389193
|
+
data4.limitOrders.fillHistory(),
|
|
389194
|
+
data4.inventory.since(/* @__PURE__ */ new Date(0)),
|
|
389195
|
+
data4.activity.walletTxs(500)
|
|
389196
|
+
]);
|
|
389197
|
+
const inventory = snapshots.map((snapshot) => ({
|
|
389198
|
+
at: parseUtc(snapshot.takenAt),
|
|
389199
|
+
balances: snapshot.balances
|
|
389200
|
+
}));
|
|
389201
|
+
const held = inventoryOf(balanceProvider.getSnapshot());
|
|
389202
|
+
if (held) inventory.push({ at: now, balances: held, live: true });
|
|
389203
|
+
const outflows = [];
|
|
389204
|
+
for (const tx of ledger) {
|
|
389205
|
+
const amount = Number(tx.amount);
|
|
389206
|
+
if (tx.kind === "send" && tx.token && Number.isFinite(amount) && amount > 0) {
|
|
389207
|
+
outflows.push({ at: tx.ts, symbol: tx.token, amount });
|
|
389208
|
+
}
|
|
389209
|
+
}
|
|
389210
|
+
const instants = inventoryInstants(fills, { period, now, tzOffsetMinutes, inventory });
|
|
389211
|
+
const readings = await this.indexerInventory().at(instants, now);
|
|
389212
|
+
return summarizeProfit(fills, { period, now, tzOffsetMinutes, inventory, outflows, readings });
|
|
389213
|
+
}
|
|
389214
|
+
/** One reader for the life of the filler, so the readings it has already fetched are kept. */
|
|
389215
|
+
indexerInventory() {
|
|
389216
|
+
this.indexed ?? (this.indexed = new IndexerInventory({
|
|
389217
|
+
indexerUrl: this.runtime.indexerUrl,
|
|
389218
|
+
solver: this.runtime.fillerAddress,
|
|
389219
|
+
describeToken: this.runtime.describeToken,
|
|
389220
|
+
logger: this.runtime.loggers.get("inventory")
|
|
389221
|
+
}));
|
|
389222
|
+
return this.indexed;
|
|
389223
|
+
}
|
|
387983
389224
|
/** The pairs the orderbook lists, the smallest payout each token may carry, and its tokens per chain. */
|
|
387984
389225
|
books() {
|
|
387985
389226
|
return this.service.books();
|
|
387986
389227
|
}
|
|
389228
|
+
/** Public bids and asks across solvers, optionally restricted to a route. */
|
|
389229
|
+
orderbookSnapshot(book, filters = {}) {
|
|
389230
|
+
return this.service.orderbookSnapshot(book, filters);
|
|
389231
|
+
}
|
|
389232
|
+
/** Every solver's order behind one public price level. */
|
|
389233
|
+
orderbookLevelOrders(book, level) {
|
|
389234
|
+
return this.service.orderbookLevelOrders(book, level);
|
|
389235
|
+
}
|
|
387987
389236
|
/** Creates the order, posts it, and reports what the orderbook made of it. */
|
|
387988
389237
|
async create(request3) {
|
|
387989
389238
|
const posted = await this.service.create(request3);
|
|
@@ -388045,10 +389294,10 @@ var PairController = class {
|
|
|
388045
389294
|
if (assets && Object.keys(assets).length > 0) config5.assets = nextAssets;
|
|
388046
389295
|
if (normalizeSymbol(pair.token0) !== normalizeSymbol(pair.token1)) {
|
|
388047
389296
|
for (const chain2 of this.runtime.resolvedChains) {
|
|
388048
|
-
const
|
|
388049
|
-
const address = assetRegistry.getAddress(pair.token1,
|
|
389297
|
+
const chainName2 = formatChainKey(chain2.chainId);
|
|
389298
|
+
const address = assetRegistry.getAddress(pair.token1, chainName2);
|
|
388050
389299
|
if (!address) continue;
|
|
388051
|
-
const list = balanceTokens[
|
|
389300
|
+
const list = balanceTokens[chainName2] ?? (balanceTokens[chainName2] = []);
|
|
388052
389301
|
if (!list.includes(address)) list.push(address);
|
|
388053
389302
|
}
|
|
388054
389303
|
}
|
|
@@ -388153,8 +389402,9 @@ var ChainController = class {
|
|
|
388153
389402
|
`Chain ${chainId} cannot be added as filling: this solver was started without a signer. Restart with \`signer\` to fill.`
|
|
388154
389403
|
);
|
|
388155
389404
|
}
|
|
388156
|
-
configService.addChain(resolved);
|
|
388157
389405
|
const watchOnly = chain2.watchOnly ?? (this.runtime.signerless || this.runtime.globalWatchOnly);
|
|
389406
|
+
await assertBundlersServeEntryPoint([resolved], configService, { watchOnly: { [chainId]: watchOnly } });
|
|
389407
|
+
configService.addChain(resolved);
|
|
388158
389408
|
if (watchOnly) intentFiller.setWatchOnly(chainId, true);
|
|
388159
389409
|
try {
|
|
388160
389410
|
if (!inScanner) {
|
|
@@ -388246,6 +389496,9 @@ var ChainController = class {
|
|
|
388246
389496
|
if (!bundlerUrl?.trim()) throw new Error("A bundler URL is required");
|
|
388247
389497
|
const index3 = this.runtime.resolvedChains.findIndex((chain2) => chain2.chainId === chainId);
|
|
388248
389498
|
if (index3 < 0) throw new Error(`Chain ${chainId} is not configured`);
|
|
389499
|
+
await assertBundlersServeEntryPoint([{ chainId, bundlerUrl }], this.runtime.configService, {
|
|
389500
|
+
watchOnly: this.runtime.intentFiller.getWatchOnly()
|
|
389501
|
+
});
|
|
388249
389502
|
this.runtime.configService.setBundlerUrl(chainId, bundlerUrl);
|
|
388250
389503
|
this.runtime.resolvedChains[index3].bundlerUrl = bundlerUrl;
|
|
388251
389504
|
this.runtime.config.chains[index3].bundlerUrl = bundlerUrl;
|
|
@@ -388260,6 +389513,10 @@ var ChainController = class {
|
|
|
388260
389513
|
"Watch-only cannot be disabled: this solver was started without a signer. Restart with `signer` to fill."
|
|
388261
389514
|
);
|
|
388262
389515
|
}
|
|
389516
|
+
if (!watchOnly) {
|
|
389517
|
+
const chain2 = this.runtime.resolvedChains.find((resolved) => resolved.chainId === chainId);
|
|
389518
|
+
if (chain2) await assertBundlersServeEntryPoint([chain2], this.runtime.configService);
|
|
389519
|
+
}
|
|
388263
389520
|
this.runtime.intentFiller.setWatchOnly(chainId, watchOnly);
|
|
388264
389521
|
this.syncWatchOnlyToConfig();
|
|
388265
389522
|
await this.persist();
|
|
@@ -389074,6 +390331,40 @@ var SqliteBidStore = class {
|
|
|
389074
390331
|
}
|
|
389075
390332
|
};
|
|
389076
390333
|
|
|
390334
|
+
// src/data/sqlite/inventory.ts
|
|
390335
|
+
init_esm_shims();
|
|
390336
|
+
var SqliteInventoryStore = class {
|
|
390337
|
+
constructor(db) {
|
|
390338
|
+
this.db = db;
|
|
390339
|
+
this.db.exec(`
|
|
390340
|
+
CREATE TABLE IF NOT EXISTS inventory_snapshots (
|
|
390341
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
390342
|
+
taken_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
390343
|
+
balances TEXT NOT NULL
|
|
390344
|
+
);
|
|
390345
|
+
|
|
390346
|
+
CREATE INDEX IF NOT EXISTS idx_inventory_snapshots_taken_at ON inventory_snapshots(taken_at);
|
|
390347
|
+
`);
|
|
390348
|
+
}
|
|
390349
|
+
toSnapshot(row) {
|
|
390350
|
+
return { id: row.id, takenAt: row.takenAt, balances: JSON.parse(row.balances) };
|
|
390351
|
+
}
|
|
390352
|
+
async record(balances) {
|
|
390353
|
+
this.db.prepare("INSERT INTO inventory_snapshots (balances) VALUES (?)").run(JSON.stringify(balances));
|
|
390354
|
+
}
|
|
390355
|
+
async latest() {
|
|
390356
|
+
const row = this.db.prepare("SELECT id, taken_at as takenAt, balances FROM inventory_snapshots ORDER BY id DESC LIMIT 1").get();
|
|
390357
|
+
return row ? this.toSnapshot(row) : null;
|
|
390358
|
+
}
|
|
390359
|
+
async since(from32) {
|
|
390360
|
+
const cutoff = from32.toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "");
|
|
390361
|
+
const rows = this.db.prepare(
|
|
390362
|
+
"SELECT id, taken_at as takenAt, balances FROM inventory_snapshots WHERE taken_at >= ? ORDER BY taken_at, id"
|
|
390363
|
+
).all(cutoff);
|
|
390364
|
+
return rows.map((row) => this.toSnapshot(row));
|
|
390365
|
+
}
|
|
390366
|
+
};
|
|
390367
|
+
|
|
389077
390368
|
// src/data/sqlite/limit-orders.ts
|
|
389078
390369
|
init_esm_shims();
|
|
389079
390370
|
init_Logger();
|
|
@@ -389094,6 +390385,7 @@ var LIMIT_ORDER_COLUMNS = `
|
|
|
389094
390385
|
status,
|
|
389095
390386
|
commitment,
|
|
389096
390387
|
order_nonce as orderNonce,
|
|
390388
|
+
entry_point as entryPoint,
|
|
389097
390389
|
book_expires_at as bookExpiresAt,
|
|
389098
390390
|
book_price as bookPrice,
|
|
389099
390391
|
last_error as lastError,
|
|
@@ -389130,6 +390422,7 @@ var SqliteLimitOrderStore = class {
|
|
|
389130
390422
|
status TEXT NOT NULL,
|
|
389131
390423
|
commitment TEXT,
|
|
389132
390424
|
order_nonce TEXT NOT NULL DEFAULT '0',
|
|
390425
|
+
entry_point TEXT,
|
|
389133
390426
|
book_expires_at TEXT,
|
|
389134
390427
|
book_price TEXT,
|
|
389135
390428
|
last_error TEXT,
|
|
@@ -389147,12 +390440,21 @@ var SqliteLimitOrderStore = class {
|
|
|
389147
390440
|
commitment TEXT NOT NULL,
|
|
389148
390441
|
bid TEXT,
|
|
389149
390442
|
amount TEXT NOT NULL,
|
|
390443
|
+
amount_in TEXT,
|
|
389150
390444
|
transaction_hash TEXT,
|
|
389151
390445
|
filled_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
389152
390446
|
);
|
|
389153
390447
|
|
|
389154
390448
|
CREATE INDEX IF NOT EXISTS idx_limit_order_fills_order ON limit_order_fills(limit_order_id);
|
|
389155
390449
|
`);
|
|
390450
|
+
if (!columnNames(this.db, "limit_orders").has("entry_point")) {
|
|
390451
|
+
this.db.exec("ALTER TABLE limit_orders ADD COLUMN entry_point TEXT");
|
|
390452
|
+
this.logger.info({ column: "entry_point" }, "Migrated limit order storage schema");
|
|
390453
|
+
}
|
|
390454
|
+
if (!columnNames(this.db, "limit_order_fills").has("amount_in")) {
|
|
390455
|
+
this.db.exec("ALTER TABLE limit_order_fills ADD COLUMN amount_in TEXT");
|
|
390456
|
+
this.logger.info({ column: "amount_in" }, "Migrated limit order fill schema");
|
|
390457
|
+
}
|
|
389156
390458
|
}
|
|
389157
390459
|
// biome-ignore lint/suspicious/noExplicitAny: raw sqlite row
|
|
389158
390460
|
toLimitOrder(row) {
|
|
@@ -389213,13 +390515,14 @@ var SqliteLimitOrderStore = class {
|
|
|
389213
390515
|
const result = this.db.prepare(`
|
|
389214
390516
|
UPDATE limit_orders
|
|
389215
390517
|
SET commitment = ?, book_expires_at = ?, book_price = ?, order_nonce = ?,
|
|
389216
|
-
status = ?, last_error = ?, updated_at = datetime('now')
|
|
390518
|
+
entry_point = ?, status = ?, last_error = ?, updated_at = datetime('now')
|
|
389217
390519
|
WHERE id = ?${statusGuard(only)}
|
|
389218
390520
|
`).run(
|
|
389219
390521
|
posting.commitment,
|
|
389220
390522
|
posting.bookExpiresAt,
|
|
389221
390523
|
posting.bookPrice,
|
|
389222
390524
|
posting.orderNonce,
|
|
390525
|
+
posting.entryPoint,
|
|
389223
390526
|
posting.status,
|
|
389224
390527
|
posting.lastError,
|
|
389225
390528
|
id2,
|
|
@@ -389262,12 +390565,27 @@ var SqliteLimitOrderStore = class {
|
|
|
389262
390565
|
}
|
|
389263
390566
|
async recordFill(fill) {
|
|
389264
390567
|
this.db.prepare(
|
|
389265
|
-
"INSERT INTO limit_order_fills (limit_order_id, commitment, bid, amount, transaction_hash) VALUES (?, ?, ?, ?, ?)"
|
|
389266
|
-
).run(
|
|
390568
|
+
"INSERT INTO limit_order_fills (limit_order_id, commitment, bid, amount, amount_in, transaction_hash) VALUES (?, ?, ?, ?, ?, ?)"
|
|
390569
|
+
).run(
|
|
390570
|
+
fill.limitOrderId,
|
|
390571
|
+
fill.commitment,
|
|
390572
|
+
fill.bid ?? null,
|
|
390573
|
+
fill.amount,
|
|
390574
|
+
fill.amountIn ?? null,
|
|
390575
|
+
fill.transactionHash ?? null
|
|
390576
|
+
);
|
|
390577
|
+
}
|
|
390578
|
+
async fillHistory() {
|
|
390579
|
+
return this.db.prepare(
|
|
390580
|
+
`SELECT f.id, f.limit_order_id as limitOrderId, o.book, o.base, o.quote, o.side, o.price,
|
|
390581
|
+
f.amount, f.amount_in as amountIn, f.filled_at as filledAt
|
|
390582
|
+
FROM limit_order_fills f JOIN limit_orders o ON o.id = f.limit_order_id
|
|
390583
|
+
ORDER BY f.filled_at, f.id`
|
|
390584
|
+
).all();
|
|
389267
390585
|
}
|
|
389268
390586
|
async fills(limitOrderId, limit = 100) {
|
|
389269
390587
|
return this.db.prepare(
|
|
389270
|
-
`SELECT id, limit_order_id as limitOrderId, commitment, bid, amount, transaction_hash as transactionHash,
|
|
390588
|
+
`SELECT id, limit_order_id as limitOrderId, commitment, bid, amount, amount_in as amountIn, transaction_hash as transactionHash,
|
|
389271
390589
|
filled_at as filledAt
|
|
389272
390590
|
FROM limit_order_fills WHERE limit_order_id = ? ORDER BY id DESC LIMIT ?`
|
|
389273
390591
|
).all(limitOrderId, Math.min(Math.max(limit, 1), 500));
|
|
@@ -389456,6 +390774,7 @@ var SqliteDataStore = class {
|
|
|
389456
390774
|
this.activity = new SqliteActivityStore(activityDb, loggers);
|
|
389457
390775
|
this.state = new SqliteStateStore(bidsDb, dataDir, loggers);
|
|
389458
390776
|
this.limitOrders = new SqliteLimitOrderStore(bidsDb, loggers);
|
|
390777
|
+
this.inventory = new SqliteInventoryStore(activityDb);
|
|
389459
390778
|
this.logger.info({ dataDir }, "SQLite data store opened");
|
|
389460
390779
|
}
|
|
389461
390780
|
/**
|