@xyo-network/chain-bridge 1.22.0 → 1.23.2
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/node/index.mjs +1251 -1083
- package/dist/node/index.mjs.map +7 -1
- package/dist/node/server/routes/bridge/routeDefinitions/getRouteDefinitions.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeFromRemoteEstimate.d.ts +93 -0
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeFromRemoteEstimate.d.ts.map +1 -0
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeFromRemoteStatus.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteEstimate.d.ts +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteMaxEstimate.d.ts +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/index.d.ts +1 -0
- package/dist/node/server/routes/bridge/routeDefinitions/routes/index.d.ts.map +1 -1
- package/dist/node/services/BridgeFulfillmentState.d.ts +1 -1
- package/dist/node/services/IBridgeServiceCollection.d.ts +4 -0
- package/dist/node/services/IBridgeServiceCollection.d.ts.map +1 -1
- package/dist/node/services/evm/getRemoteConfirmationDepth.d.ts.map +1 -1
- package/dist/node/services/getServices.d.ts.map +1 -1
- package/dist/node/services/queue/flows/createEthToXl1BridgeJob/createEthToXl1BridgeJob.d.ts +1 -1
- package/dist/node/services/queue/workers/Xl1ReserveTxFulfillment.d.ts.map +1 -1
- package/dist/node/services/queue/workers/util/buildEthToXl1BridgePayloads.d.ts +44 -0
- package/dist/node/services/queue/workers/util/buildEthToXl1BridgePayloads.d.ts.map +1 -0
- package/dist/node/services/queue/workers/util/buildEthToXl1ReserveTx.d.ts +22 -6
- package/dist/node/services/queue/workers/util/buildEthToXl1ReserveTx.d.ts.map +1 -1
- package/dist/node/services/queue/workers/util/index.d.ts +1 -0
- package/dist/node/services/queue/workers/util/index.d.ts.map +1 -1
- package/dist/node/services/queue/workers/util/resolveEvmBlockTagAtDepth.d.ts +18 -7
- package/dist/node/services/queue/workers/util/resolveEvmBlockTagAtDepth.d.ts.map +1 -1
- package/dist/node/services/validation/index.d.ts +1 -0
- package/dist/node/services/validation/index.d.ts.map +1 -1
- package/dist/node/services/validation/validateAmountMeetsMinBridgeAmount.d.ts +20 -0
- package/dist/node/services/validation/validateAmountMeetsMinBridgeAmount.d.ts.map +1 -0
- package/package.json +34 -43
package/dist/node/index.mjs
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
-
var
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
5
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
6
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
7
|
+
if (decorator = decorators[i])
|
|
8
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
9
|
+
if (kind && result) __defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3
13
|
|
|
4
14
|
// src/BridgeActor.ts
|
|
5
15
|
import { creatable } from "@xylabs/sdk-js";
|
|
@@ -16,7 +26,7 @@ import { isDefined } from "@xylabs/sdk-js";
|
|
|
16
26
|
import { Redis } from "ioredis";
|
|
17
27
|
var connection;
|
|
18
28
|
var maxRetriesPerRequest = null;
|
|
19
|
-
var getConnection =
|
|
29
|
+
var getConnection = (config) => {
|
|
20
30
|
if (isDefined(connection)) return connection;
|
|
21
31
|
const { redisHost: host, redisPort: port } = config;
|
|
22
32
|
connection = new Redis({
|
|
@@ -25,7 +35,7 @@ var getConnection = /* @__PURE__ */ __name((config) => {
|
|
|
25
35
|
maxRetriesPerRequest
|
|
26
36
|
});
|
|
27
37
|
return connection;
|
|
28
|
-
}
|
|
38
|
+
};
|
|
29
39
|
|
|
30
40
|
// src/services/queue/flowProducer.ts
|
|
31
41
|
import { isDefined as isDefined2 } from "@xylabs/sdk-js";
|
|
@@ -36,7 +46,7 @@ var prefix = "xl1-bridge";
|
|
|
36
46
|
|
|
37
47
|
// src/services/queue/flowProducer.ts
|
|
38
48
|
var flowProducer;
|
|
39
|
-
var getFlowProducer =
|
|
49
|
+
var getFlowProducer = (connection2, telemetry2) => {
|
|
40
50
|
if (isDefined2(flowProducer)) return flowProducer;
|
|
41
51
|
flowProducer = new FlowProducer({
|
|
42
52
|
connection: connection2,
|
|
@@ -44,100 +54,152 @@ var getFlowProducer = /* @__PURE__ */ __name((connection2, telemetry2) => {
|
|
|
44
54
|
prefix
|
|
45
55
|
});
|
|
46
56
|
return flowProducer;
|
|
47
|
-
}
|
|
57
|
+
};
|
|
48
58
|
|
|
49
59
|
// src/services/queue/workers/EthEventVerification.ts
|
|
50
|
-
import { assertEx as
|
|
60
|
+
import { assertEx as assertEx3, isNull } from "@xylabs/sdk-js";
|
|
51
61
|
import { UnrecoverableError, Worker } from "bullmq";
|
|
52
62
|
|
|
53
|
-
// src/services/queue/workers/util/
|
|
54
|
-
import { toHex } from "@xylabs/sdk-js";
|
|
63
|
+
// src/services/queue/workers/util/buildEthToXl1BridgePayloads.ts
|
|
64
|
+
import { assertEx, toHex } from "@xylabs/sdk-js";
|
|
55
65
|
import { PayloadBuilder } from "@xyo-network/sdk-js";
|
|
56
|
-
import { BridgeIntentSchema,
|
|
57
|
-
|
|
58
|
-
const {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
import { BridgeIntentSchema, createTransferPayload } from "@xyo-network/xl1-sdk";
|
|
67
|
+
function buildEthToXl1BridgePayloads(options2) {
|
|
68
|
+
const {
|
|
69
|
+
amount,
|
|
70
|
+
bridgeAccountAddress,
|
|
71
|
+
bridgeId,
|
|
72
|
+
destAddress,
|
|
73
|
+
evmChainId,
|
|
74
|
+
evmContractAddress,
|
|
75
|
+
evmSrcAddress,
|
|
76
|
+
evmTokenAddress,
|
|
77
|
+
feesAddress,
|
|
78
|
+
feesAmount,
|
|
79
|
+
xl1ChainId,
|
|
80
|
+
xl1TokenAddress
|
|
81
|
+
} = options2;
|
|
82
|
+
assertEx(amount >= feesAmount, () => `buildEthToXl1BridgePayloads: amount (${amount}) < feesAmount (${feesAmount})`);
|
|
83
|
+
const destAmount = amount - feesAmount;
|
|
84
|
+
const srcAmountHex = toHex(amount);
|
|
85
|
+
const destAmountHex = toHex(destAmount);
|
|
86
|
+
const nonce = `evm-${evmChainId.toLowerCase()}-${evmContractAddress.toLowerCase()}-${bridgeId.toString()}`;
|
|
87
|
+
const transfers = feesAmount === 0n || destAddress === feesAddress ? { [destAddress]: amount } : { [destAddress]: destAmount, [feesAddress]: feesAmount };
|
|
88
|
+
const transfer = createTransferPayload(bridgeAccountAddress, transfers);
|
|
89
|
+
const intent = new PayloadBuilder({ schema: BridgeIntentSchema }).fields({
|
|
67
90
|
dest: xl1ChainId,
|
|
68
91
|
destAddress,
|
|
69
|
-
destAmount:
|
|
92
|
+
destAmount: destAmountHex,
|
|
70
93
|
destToken: xl1TokenAddress,
|
|
71
94
|
nonce,
|
|
72
95
|
src: evmChainId,
|
|
73
96
|
srcAddress: evmSrcAddress,
|
|
74
|
-
srcAmount:
|
|
97
|
+
srcAmount: srcAmountHex,
|
|
75
98
|
srcToken: evmTokenAddress
|
|
76
99
|
}).build();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
100
|
+
return { intent, transfer };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// src/services/queue/workers/util/buildEthToXl1ReserveTx.ts
|
|
104
|
+
import { toHex as toHex2 } from "@xylabs/sdk-js";
|
|
105
|
+
import { PayloadBuilder as PayloadBuilder2 } from "@xyo-network/sdk-js";
|
|
106
|
+
import { BridgeSourceObservationSchema, buildTransaction } from "@xyo-network/xl1-sdk";
|
|
107
|
+
async function buildEthToXl1ReserveTx(options2) {
|
|
108
|
+
const {
|
|
109
|
+
amount,
|
|
110
|
+
bridgeAccount,
|
|
111
|
+
bridgeId,
|
|
112
|
+
destAddress,
|
|
113
|
+
evmChainId,
|
|
114
|
+
evmContractAddress,
|
|
115
|
+
evmSrcAddress,
|
|
116
|
+
evmTokenAddress,
|
|
117
|
+
evmTxHash,
|
|
118
|
+
exp,
|
|
119
|
+
feesAddress,
|
|
120
|
+
feesAmount,
|
|
121
|
+
nbf,
|
|
122
|
+
xl1ChainId,
|
|
123
|
+
xl1TokenAddress
|
|
124
|
+
} = options2;
|
|
125
|
+
const { intent, transfer } = buildEthToXl1BridgePayloads({
|
|
126
|
+
amount,
|
|
127
|
+
bridgeAccountAddress: bridgeAccount.address,
|
|
128
|
+
bridgeId,
|
|
129
|
+
destAddress,
|
|
130
|
+
evmChainId,
|
|
131
|
+
evmContractAddress,
|
|
132
|
+
evmSrcAddress,
|
|
133
|
+
evmTokenAddress,
|
|
134
|
+
feesAddress,
|
|
135
|
+
feesAmount,
|
|
136
|
+
xl1ChainId,
|
|
137
|
+
xl1TokenAddress
|
|
138
|
+
});
|
|
139
|
+
const destAmountHex = toHex2(amount - feesAmount);
|
|
140
|
+
const srcAmountHex = toHex2(amount);
|
|
141
|
+
const sourceObservation = new PayloadBuilder2({ schema: BridgeSourceObservationSchema }).fields({
|
|
80
142
|
dest: xl1ChainId,
|
|
81
143
|
destAddress,
|
|
82
|
-
destAmount:
|
|
144
|
+
destAmount: destAmountHex,
|
|
83
145
|
destToken: xl1TokenAddress,
|
|
84
146
|
src: evmChainId,
|
|
85
147
|
srcAddress: evmSrcAddress,
|
|
86
|
-
srcAmount:
|
|
148
|
+
srcAmount: srcAmountHex,
|
|
87
149
|
srcConfirmation: evmTxHash,
|
|
88
150
|
srcToken: evmTokenAddress
|
|
89
151
|
}).build();
|
|
90
|
-
return buildTransaction(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
intent,
|
|
94
|
-
|
|
95
|
-
|
|
152
|
+
return buildTransaction(
|
|
153
|
+
xl1ChainId,
|
|
154
|
+
[transfer],
|
|
155
|
+
[intent, sourceObservation],
|
|
156
|
+
bridgeAccount,
|
|
157
|
+
nbf,
|
|
158
|
+
exp
|
|
159
|
+
);
|
|
96
160
|
}
|
|
97
|
-
__name(buildEthToXl1ReserveTx, "buildEthToXl1ReserveTx");
|
|
98
161
|
|
|
99
162
|
// src/services/queue/workers/util/resolveEvmBlockTagAtDepth.ts
|
|
100
163
|
async function resolveEvmBlockTagAtDepth(provider, depth) {
|
|
101
164
|
if (depth === "finalized") return "finalized";
|
|
165
|
+
if (depth === 0) return "latest";
|
|
102
166
|
const head = await provider.getBlockNumber();
|
|
103
167
|
return Math.max(head - depth, 0);
|
|
104
168
|
}
|
|
105
|
-
__name(resolveEvmBlockTagAtDepth, "resolveEvmBlockTagAtDepth");
|
|
106
169
|
|
|
107
170
|
// src/services/queue/workers/util/submitEthTransaction.ts
|
|
108
|
-
import {
|
|
109
|
-
|
|
171
|
+
import {
|
|
172
|
+
assertEx as assertEx2,
|
|
173
|
+
hexToBigInt,
|
|
174
|
+
toEthAddress
|
|
175
|
+
} from "@xylabs/sdk-js";
|
|
176
|
+
import { PayloadBuilder as PayloadBuilder3 } from "@xyo-network/sdk-js";
|
|
110
177
|
import { isBridgeIntent } from "@xyo-network/xl1-sdk";
|
|
111
|
-
var submitEthTransaction =
|
|
112
|
-
const xl1Transaction =
|
|
113
|
-
const allPayloads = [
|
|
114
|
-
|
|
115
|
-
...offChainPayloads
|
|
116
|
-
];
|
|
117
|
-
const bridgeIntent = assertEx(allPayloads.find(isBridgeIntent), () => "No bridge intent found");
|
|
178
|
+
var submitEthTransaction = async (tx, offChainPayloads, bridge, wallet) => {
|
|
179
|
+
const xl1Transaction = assertEx2(tx[0], () => "No corresponding XL1 transaction found");
|
|
180
|
+
const allPayloads = [...tx[1], ...offChainPayloads];
|
|
181
|
+
const bridgeIntent = assertEx2(allPayloads.find(isBridgeIntent), () => "No bridge intent found");
|
|
118
182
|
const srcAddress = toEthAddress(bridgeIntent.srcAddress);
|
|
119
183
|
const destAddress = toEthAddress(bridgeIntent.destAddress);
|
|
120
184
|
const amount = hexToBigInt(bridgeIntent.destAmount);
|
|
121
|
-
const nonce = hexToBigInt(await
|
|
185
|
+
const nonce = hexToBigInt(await PayloadBuilder3.hash(xl1Transaction));
|
|
122
186
|
const bridgeTx = await bridge.connect(wallet).bridgeFromRemote(srcAddress, destAddress, amount, nonce);
|
|
123
187
|
const receipt = await bridgeTx.wait(1);
|
|
124
188
|
return receipt?.hash;
|
|
125
|
-
}
|
|
189
|
+
};
|
|
126
190
|
|
|
127
191
|
// src/services/queue/workers/util/submitXl1Transaction.ts
|
|
128
|
-
var submitXl1Transaction =
|
|
192
|
+
var submitXl1Transaction = async (preparedTx, offChain = [], gateway) => {
|
|
129
193
|
const result = await gateway.addTransactionToChain(preparedTx, offChain);
|
|
130
194
|
return result;
|
|
131
|
-
}
|
|
195
|
+
};
|
|
132
196
|
|
|
133
197
|
// src/services/queue/workers/util/verifyEthBridgeEvent.ts
|
|
134
198
|
import { asHex, toAddress } from "@xylabs/sdk-js";
|
|
135
199
|
import { ZeroAddress } from "ethers";
|
|
136
200
|
async function verifyEthBridgeEvent(id, bridge, provider, confirmationDepth) {
|
|
137
201
|
const blockTag = await resolveEvmBlockTagAtDepth(provider, confirmationDepth);
|
|
138
|
-
const data = await bridge.bridgesToRemote(id, {
|
|
139
|
-
blockTag
|
|
140
|
-
});
|
|
202
|
+
const data = await bridge.bridgesToRemote(id, { blockTag });
|
|
141
203
|
if (data.srcAddress === ZeroAddress) {
|
|
142
204
|
return null;
|
|
143
205
|
}
|
|
@@ -155,53 +217,60 @@ async function verifyEthBridgeEvent(id, bridge, provider, confirmationDepth) {
|
|
|
155
217
|
srcAddress: toAddress(data.srcAddress)
|
|
156
218
|
};
|
|
157
219
|
}
|
|
158
|
-
__name(verifyEthBridgeEvent, "verifyEthBridgeEvent");
|
|
159
220
|
|
|
160
221
|
// src/services/queue/workers/EthEventVerification.ts
|
|
161
222
|
var name = "Verify ETH Bridge Event at Depth";
|
|
162
223
|
var queueName = "eth-event-verify";
|
|
163
|
-
var createWorker =
|
|
164
|
-
const svc =
|
|
165
|
-
const {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
state.failed =
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
224
|
+
var createWorker = (connection2, telemetry2, services) => {
|
|
225
|
+
const svc = assertEx3(services, () => "services not provided");
|
|
226
|
+
const {
|
|
227
|
+
bridge,
|
|
228
|
+
bridgeFulfillmentMap,
|
|
229
|
+
provider,
|
|
230
|
+
remoteConfirmationDepth
|
|
231
|
+
} = svc;
|
|
232
|
+
const worker = new Worker(
|
|
233
|
+
queueName,
|
|
234
|
+
async (job) => {
|
|
235
|
+
const { bridgeId, identity } = job.data;
|
|
236
|
+
const id = BigInt(bridgeId);
|
|
237
|
+
const existing = await bridgeFulfillmentMap.get(identity);
|
|
238
|
+
if (existing?.canonical) {
|
|
239
|
+
await job.log(`[${identity}] canonical already set; verification skipped`);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const state = existing ?? { identity, previousAttempts: [] };
|
|
243
|
+
if (state.failed) state.failed = void 0;
|
|
244
|
+
await job.log(`[${identity}] verifying BridgedToRemote(${id}) at depth ${remoteConfirmationDepth}`);
|
|
245
|
+
const data = await verifyEthBridgeEvent(id, bridge, provider, remoteConfirmationDepth);
|
|
246
|
+
if (isNull(data)) {
|
|
247
|
+
state.failed = {
|
|
248
|
+
at: Date.now(),
|
|
249
|
+
reason: "non-canonical at confirmation depth \u2014 orphaned by reorg or never reached canonical state"
|
|
250
|
+
};
|
|
251
|
+
await bridgeFulfillmentMap.set(identity, state);
|
|
252
|
+
await job.log(`[${identity}] non-canonical at depth \u2014 marked failed`);
|
|
253
|
+
throw new UnrecoverableError(`[${identity}] bridgesToRemote slot empty at confirmation depth ${remoteConfirmationDepth}`);
|
|
254
|
+
}
|
|
255
|
+
state.canonical = data;
|
|
186
256
|
await bridgeFulfillmentMap.set(identity, state);
|
|
187
|
-
await job.log(
|
|
188
|
-
|
|
257
|
+
await job.log(
|
|
258
|
+
`[${identity}] verified: src=${data.srcAddress} dest=${data.destAddress} amount=${data.amount} evmTxHash=${data.evmTxHash}`
|
|
259
|
+
);
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
connection: connection2,
|
|
263
|
+
telemetry: telemetry2,
|
|
264
|
+
prefix
|
|
189
265
|
}
|
|
190
|
-
|
|
191
|
-
await bridgeFulfillmentMap.set(identity, state);
|
|
192
|
-
await job.log(`[${identity}] verified: src=${data.srcAddress} dest=${data.destAddress} amount=${data.amount} evmTxHash=${data.evmTxHash}`);
|
|
193
|
-
}, {
|
|
194
|
-
connection: connection2,
|
|
195
|
-
telemetry: telemetry2,
|
|
196
|
-
prefix
|
|
197
|
-
});
|
|
266
|
+
);
|
|
198
267
|
worker.on("failed", (job, err) => {
|
|
199
268
|
console.error(`[${name}] Job ${job?.id} failed:`, err.message);
|
|
200
269
|
});
|
|
201
270
|
worker.on("error", (err) => {
|
|
202
271
|
console.error(`[${name}] Worker error:`, err);
|
|
203
272
|
});
|
|
204
|
-
}
|
|
273
|
+
};
|
|
205
274
|
var EthEventVerification = {
|
|
206
275
|
createWorker,
|
|
207
276
|
name,
|
|
@@ -212,23 +281,27 @@ var EthEventVerification = {
|
|
|
212
281
|
import { Worker as Worker2 } from "bullmq";
|
|
213
282
|
var name2 = "Bridge Ethereum to XL1";
|
|
214
283
|
var queueName2 = "eth-to-xl1-bridge";
|
|
215
|
-
var createWorker2 =
|
|
216
|
-
const worker = new Worker2(
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
284
|
+
var createWorker2 = (connection2, telemetry2) => {
|
|
285
|
+
const worker = new Worker2(
|
|
286
|
+
queueName2,
|
|
287
|
+
async (job) => {
|
|
288
|
+
await job.log(`[${job.name}] start`);
|
|
289
|
+
await job.log(`[${job.name}] done`);
|
|
290
|
+
return {};
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
connection: connection2,
|
|
294
|
+
telemetry: telemetry2,
|
|
295
|
+
prefix
|
|
296
|
+
}
|
|
297
|
+
);
|
|
225
298
|
worker.on("failed", (job, err) => {
|
|
226
299
|
console.error(`[${name2}] Job ${job?.id} failed:`, err.message);
|
|
227
300
|
});
|
|
228
301
|
worker.on("error", (err) => {
|
|
229
302
|
console.error(`[${name2}] Worker error:`, err);
|
|
230
303
|
});
|
|
231
|
-
}
|
|
304
|
+
};
|
|
232
305
|
var EthToXl1BridgeParent = {
|
|
233
306
|
createWorker: createWorker2,
|
|
234
307
|
name: name2,
|
|
@@ -236,41 +309,45 @@ var EthToXl1BridgeParent = {
|
|
|
236
309
|
};
|
|
237
310
|
|
|
238
311
|
// src/services/queue/workers/EthTransactionMonitor.ts
|
|
239
|
-
import { assertEx as
|
|
240
|
-
import { PayloadBuilder as
|
|
312
|
+
import { assertEx as assertEx4 } from "@xylabs/sdk-js";
|
|
313
|
+
import { PayloadBuilder as PayloadBuilder4 } from "@xyo-network/sdk-js";
|
|
241
314
|
import { Worker as Worker3 } from "bullmq";
|
|
242
315
|
var name3 = "Monitor Submitted ETH Transaction";
|
|
243
316
|
var queueName3 = "eth-tx-monitor";
|
|
244
|
-
var createWorker3 =
|
|
245
|
-
const provider =
|
|
246
|
-
const stateMap =
|
|
247
|
-
const worker = new Worker3(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
317
|
+
var createWorker3 = (connection2, telemetry2, services) => {
|
|
318
|
+
const provider = assertEx4(services?.provider, () => "provider service not provided");
|
|
319
|
+
const stateMap = assertEx4(services?.ethTxStateMap, () => "ethTxStateMap service not provided");
|
|
320
|
+
const worker = new Worker3(
|
|
321
|
+
queueName3,
|
|
322
|
+
async (job) => {
|
|
323
|
+
const { tx } = job.data;
|
|
324
|
+
const hash = await PayloadBuilder4.hash(tx[0]);
|
|
325
|
+
const state = assertEx4(await stateMap.get(hash), () => "State not found");
|
|
326
|
+
const submissionHash = assertEx4(state?.submissionHash, () => "submissionHash not found");
|
|
327
|
+
const receipt = assertEx4(await provider.getTransactionReceipt(submissionHash), () => "Transaction receipt not found");
|
|
328
|
+
await job.log(`[${hash}] confirmed ETH tx ${submissionHash} in block ${receipt.blockNumber}`);
|
|
329
|
+
const { blockHash, blockNumber } = receipt;
|
|
330
|
+
state.confirmationHash = blockHash;
|
|
331
|
+
await stateMap.set(hash, state);
|
|
332
|
+
return {
|
|
333
|
+
blockHash,
|
|
334
|
+
blockNumber,
|
|
335
|
+
submissionHash
|
|
336
|
+
};
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
connection: connection2,
|
|
340
|
+
telemetry: telemetry2,
|
|
341
|
+
prefix
|
|
342
|
+
}
|
|
343
|
+
);
|
|
267
344
|
worker.on("failed", (job, err) => {
|
|
268
345
|
console.error(`[${name3}] Job ${job?.id} failed:`, err.message);
|
|
269
346
|
});
|
|
270
347
|
worker.on("error", (err) => {
|
|
271
348
|
console.error(`[${name3}] Worker error:`, err);
|
|
272
349
|
});
|
|
273
|
-
}
|
|
350
|
+
};
|
|
274
351
|
var EthTransactionMonitor = {
|
|
275
352
|
createWorker: createWorker3,
|
|
276
353
|
name: name3,
|
|
@@ -278,121 +355,124 @@ var EthTransactionMonitor = {
|
|
|
278
355
|
};
|
|
279
356
|
|
|
280
357
|
// src/services/queue/workers/EthTransactionPreparation.ts
|
|
281
|
-
import { assertEx as
|
|
282
|
-
import { PayloadBuilder as
|
|
358
|
+
import { assertEx as assertEx15, hexToBigInt as hexToBigInt10 } from "@xylabs/sdk-js";
|
|
359
|
+
import { PayloadBuilder as PayloadBuilder8 } from "@xyo-network/sdk-js";
|
|
283
360
|
import { isBridgeIntent as isBridgeIntent4 } from "@xyo-network/xl1-sdk";
|
|
284
361
|
import { Worker as Worker4 } from "bullmq";
|
|
285
362
|
import { getAddress } from "ethers";
|
|
286
363
|
|
|
364
|
+
// src/services/validation/validateAmountMeetsMinBridgeAmount.ts
|
|
365
|
+
import { hexToBigInt as hexToBigInt2 } from "@xylabs/sdk-js";
|
|
366
|
+
function validateAmountMeetsMinBridgeAmount({
|
|
367
|
+
amount,
|
|
368
|
+
minBridgeAmount
|
|
369
|
+
}) {
|
|
370
|
+
return amount >= hexToBigInt2(minBridgeAmount);
|
|
371
|
+
}
|
|
372
|
+
|
|
287
373
|
// src/services/validation/validateBridgeEstimateExact.ts
|
|
288
|
-
import { hexToBigInt as
|
|
289
|
-
import { PayloadBuilder as
|
|
374
|
+
import { hexToBigInt as hexToBigInt6, isUndefined } from "@xylabs/sdk-js";
|
|
375
|
+
import { PayloadBuilder as PayloadBuilder6 } from "@xyo-network/sdk-js";
|
|
290
376
|
|
|
291
377
|
// src/services/evm/asChainId.ts
|
|
292
378
|
import { asHex as asHex2 } from "@xylabs/sdk-js";
|
|
293
|
-
var asChainId =
|
|
379
|
+
var asChainId = (value) => {
|
|
294
380
|
const chainId = asHex2(value);
|
|
295
381
|
return chainId;
|
|
296
|
-
}
|
|
382
|
+
};
|
|
297
383
|
|
|
298
384
|
// src/services/evm/asToken.ts
|
|
299
385
|
import { asAddress } from "@xylabs/sdk-js";
|
|
300
|
-
var asToken =
|
|
386
|
+
var asToken = (value) => {
|
|
301
387
|
const token = asAddress(value);
|
|
302
388
|
return token;
|
|
303
|
-
}
|
|
389
|
+
};
|
|
304
390
|
|
|
305
391
|
// src/services/evm/getBridgeEscrowAddress.ts
|
|
306
|
-
import { asAddress as asAddress2, assertEx as
|
|
307
|
-
var tryGetBridgeEscrowAddress =
|
|
392
|
+
import { asAddress as asAddress2, assertEx as assertEx5 } from "@xylabs/sdk-js";
|
|
393
|
+
var tryGetBridgeEscrowAddress = (config) => {
|
|
308
394
|
const address = asAddress2(config.escrowAddress);
|
|
309
395
|
return address;
|
|
310
|
-
}
|
|
396
|
+
};
|
|
311
397
|
|
|
312
398
|
// src/services/evm/getBridgeFeesAddress.ts
|
|
313
|
-
import { asAddress as asAddress3, assertEx as
|
|
314
|
-
var tryGetBridgeFeesAddress =
|
|
399
|
+
import { asAddress as asAddress3, assertEx as assertEx6 } from "@xylabs/sdk-js";
|
|
400
|
+
var tryGetBridgeFeesAddress = (config) => {
|
|
315
401
|
const address = asAddress3(config.feesAddress);
|
|
316
402
|
return address;
|
|
317
|
-
}
|
|
403
|
+
};
|
|
318
404
|
|
|
319
405
|
// src/services/evm/getFeeStructure.ts
|
|
320
|
-
var getFeeStructure =
|
|
406
|
+
var getFeeStructure = (config) => {
|
|
321
407
|
const { feeFixed, feeRateBasisPoints } = config;
|
|
322
|
-
return {
|
|
323
|
-
|
|
324
|
-
feeRateBasisPoints
|
|
325
|
-
};
|
|
326
|
-
}, "getFeeStructure");
|
|
408
|
+
return { feeFixed, feeRateBasisPoints };
|
|
409
|
+
};
|
|
327
410
|
|
|
328
411
|
// src/services/evm/getMaxBridgeAmount.ts
|
|
329
|
-
var getMaxBridgeAmount =
|
|
412
|
+
var getMaxBridgeAmount = (config) => {
|
|
330
413
|
const { maxBridgeAmount } = config;
|
|
331
414
|
return maxBridgeAmount;
|
|
332
|
-
}
|
|
415
|
+
};
|
|
333
416
|
|
|
334
417
|
// src/services/evm/getMinBridgeAmount.ts
|
|
335
|
-
var getMinBridgeAmount =
|
|
418
|
+
var getMinBridgeAmount = (config) => {
|
|
336
419
|
const { minBridgeAmount } = config;
|
|
337
420
|
return minBridgeAmount;
|
|
338
|
-
}
|
|
421
|
+
};
|
|
339
422
|
|
|
340
423
|
// src/services/evm/getRemoteChainId.ts
|
|
341
|
-
import { assertEx as
|
|
342
|
-
var getRemoteChainId =
|
|
343
|
-
const remoteChainId =
|
|
424
|
+
import { assertEx as assertEx7 } from "@xylabs/sdk-js";
|
|
425
|
+
var getRemoteChainId = (config) => {
|
|
426
|
+
const remoteChainId = assertEx7(asChainId(config.remoteChainId), () => "Invalid remote chain ID in config");
|
|
344
427
|
return remoteChainId;
|
|
345
|
-
}
|
|
428
|
+
};
|
|
346
429
|
|
|
347
430
|
// src/services/evm/getRemoteTokenAddress.ts
|
|
348
|
-
import { assertEx as
|
|
349
|
-
var getRemoteTokenAddress =
|
|
431
|
+
import { assertEx as assertEx8 } from "@xylabs/sdk-js";
|
|
432
|
+
var getRemoteTokenAddress = (config) => {
|
|
350
433
|
const token = asToken(config.remoteTokenAddress);
|
|
351
|
-
return
|
|
352
|
-
}
|
|
434
|
+
return assertEx8(token, () => "Remote token address is not defined in bridge configuration");
|
|
435
|
+
};
|
|
353
436
|
|
|
354
437
|
// src/services/evm/getBridgeWalletAccount.ts
|
|
355
438
|
import { isDefined as isDefined3 } from "@xylabs/sdk-js";
|
|
356
439
|
import { resolveWalletForActor } from "@xyo-network/chain-orchestration";
|
|
357
440
|
var accountServiceSingleton;
|
|
358
|
-
var getBridgeWalletAccount =
|
|
441
|
+
var getBridgeWalletAccount = async (config) => {
|
|
359
442
|
if (accountServiceSingleton) return accountServiceSingleton;
|
|
360
443
|
const accountPath = typeof config.accountPath === "string" ? config.accountPath : void 0;
|
|
361
444
|
const account = await resolveWalletForActor(config.name, accountPath);
|
|
362
445
|
accountServiceSingleton = account;
|
|
363
446
|
return accountServiceSingleton;
|
|
364
|
-
}
|
|
447
|
+
};
|
|
365
448
|
|
|
366
449
|
// src/services/evm/getTransferAddresses.ts
|
|
367
|
-
var getTransferAddresses =
|
|
450
|
+
var getTransferAddresses = async (config) => {
|
|
368
451
|
const escrowAddress = tryGetBridgeEscrowAddress(config) ?? (await getBridgeWalletAccount(config)).address;
|
|
369
452
|
const feesAddress = tryGetBridgeFeesAddress(config) ?? (await getBridgeWalletAccount(config)).address;
|
|
370
|
-
return {
|
|
371
|
-
|
|
372
|
-
feesAddress
|
|
373
|
-
};
|
|
374
|
-
}, "getTransferAddresses");
|
|
453
|
+
return { escrowAddress, feesAddress };
|
|
454
|
+
};
|
|
375
455
|
|
|
376
456
|
// src/services/evm/getXl1ChainId.ts
|
|
377
|
-
import { assertEx as
|
|
378
|
-
var getXl1ChainId =
|
|
457
|
+
import { assertEx as assertEx9, isDefined as isDefined4 } from "@xylabs/sdk-js";
|
|
458
|
+
var getXl1ChainId = (config) => {
|
|
379
459
|
const xl1ChainId = config.xl1ChainId;
|
|
380
460
|
if (isDefined4(xl1ChainId)) {
|
|
381
|
-
return
|
|
461
|
+
return assertEx9(asChainId(xl1ChainId), () => "Invalid xl1ChainId in bridge config");
|
|
382
462
|
}
|
|
383
|
-
return
|
|
384
|
-
}
|
|
463
|
+
return assertEx9(asChainId(config.chain.id), () => "Invalid chain.id in config");
|
|
464
|
+
};
|
|
385
465
|
|
|
386
466
|
// src/services/evm/getXl1TokenAddress.ts
|
|
387
467
|
import { isDefined as isDefined5 } from "@xylabs/sdk-js";
|
|
388
|
-
var getXl1TokenAddress =
|
|
468
|
+
var getXl1TokenAddress = (config) => {
|
|
389
469
|
const token = asToken(config.xl1TokenAddress);
|
|
390
470
|
if (isDefined5(token)) return token;
|
|
391
471
|
return getXl1ChainId(config);
|
|
392
|
-
}
|
|
472
|
+
};
|
|
393
473
|
|
|
394
474
|
// src/services/evm/getBridgeSettings.ts
|
|
395
|
-
var getBridgeSettings =
|
|
475
|
+
var getBridgeSettings = async (config) => {
|
|
396
476
|
const { feeFixed, feeRateBasisPoints } = getFeeStructure(config);
|
|
397
477
|
const { feesAddress, escrowAddress } = await getTransferAddresses(config);
|
|
398
478
|
const maxBridgeAmount = getMaxBridgeAmount(config);
|
|
@@ -413,84 +493,83 @@ var getBridgeSettings = /* @__PURE__ */ __name(async (config) => {
|
|
|
413
493
|
xl1TokenAddress,
|
|
414
494
|
xl1ChainId
|
|
415
495
|
};
|
|
416
|
-
}
|
|
496
|
+
};
|
|
417
497
|
|
|
418
498
|
// src/services/evm/getRemoteConfirmationDepth.ts
|
|
419
|
-
import { isDefined as isDefined6 } from "@xylabs/sdk-js";
|
|
420
|
-
var HARDHAT_CHAIN_ID = "0x7a69";
|
|
421
|
-
var ETHEREUM_MAINNET_CHAIN_ID = "0x1";
|
|
499
|
+
import { isDefined as isDefined6, toHex as toHex3 } from "@xylabs/sdk-js";
|
|
500
|
+
var HARDHAT_CHAIN_ID = toHex3("0x7a69");
|
|
501
|
+
var ETHEREUM_MAINNET_CHAIN_ID = toHex3("0x1");
|
|
422
502
|
var FALLBACK_CONFIRMATION_DEPTH = 32;
|
|
423
|
-
var DEFAULT_CONFIRMATION_DEPTH_BY_CHAIN_ID =
|
|
424
|
-
[HARDHAT_CHAIN_ID
|
|
425
|
-
[ETHEREUM_MAINNET_CHAIN_ID
|
|
426
|
-
|
|
503
|
+
var DEFAULT_CONFIRMATION_DEPTH_BY_CHAIN_ID = /* @__PURE__ */ new Map([
|
|
504
|
+
[HARDHAT_CHAIN_ID, 0],
|
|
505
|
+
[ETHEREUM_MAINNET_CHAIN_ID, 32]
|
|
506
|
+
]);
|
|
427
507
|
function getRemoteConfirmationDepth(config) {
|
|
428
508
|
if (isDefined6(config.remoteConfirmationDepth)) return config.remoteConfirmationDepth;
|
|
429
|
-
const chainId = getRemoteChainId(config)
|
|
430
|
-
return DEFAULT_CONFIRMATION_DEPTH_BY_CHAIN_ID
|
|
509
|
+
const chainId = toHex3(getRemoteChainId(config));
|
|
510
|
+
return DEFAULT_CONFIRMATION_DEPTH_BY_CHAIN_ID.get(chainId) ?? FALLBACK_CONFIRMATION_DEPTH;
|
|
431
511
|
}
|
|
432
|
-
__name(getRemoteConfirmationDepth, "getRemoteConfirmationDepth");
|
|
433
512
|
|
|
434
513
|
// src/services/evm/getScannerIntervalMs.ts
|
|
435
514
|
function getScannerIntervalMs(config) {
|
|
436
515
|
return config.scannerIntervalMs;
|
|
437
516
|
}
|
|
438
|
-
__name(getScannerIntervalMs, "getScannerIntervalMs");
|
|
439
517
|
|
|
440
518
|
// src/services/util/calculateBridgeFees.ts
|
|
441
|
-
import { hexToBigInt as
|
|
442
|
-
var calculateBridgeFees =
|
|
519
|
+
import { hexToBigInt as hexToBigInt3, toHex as toHex4 } from "@xylabs/sdk-js";
|
|
520
|
+
var calculateBridgeFees = (srcAmount, feeStructure) => {
|
|
443
521
|
const { feeFixed, feeRateBasisPoints } = feeStructure;
|
|
444
|
-
const srcAmountBigInt =
|
|
522
|
+
const srcAmountBigInt = hexToBigInt3(srcAmount);
|
|
445
523
|
const feeVariableBigInt = srcAmountBigInt * BigInt(feeRateBasisPoints) / 10000n;
|
|
446
|
-
const feeVariable =
|
|
524
|
+
const feeVariable = toHex4(feeVariableBigInt);
|
|
447
525
|
return {
|
|
448
526
|
feeFixed,
|
|
449
527
|
feeVariable,
|
|
450
528
|
srcAmount
|
|
451
529
|
};
|
|
452
|
-
}
|
|
530
|
+
};
|
|
453
531
|
|
|
454
532
|
// src/services/util/calculateMaxBridgeAmount.ts
|
|
455
|
-
import { hexToBigInt as
|
|
456
|
-
var calculateMaxBridgeAmount =
|
|
533
|
+
import { hexToBigInt as hexToBigInt4, toHex as toHex5 } from "@xylabs/sdk-js";
|
|
534
|
+
var calculateMaxBridgeAmount = (balance, feeStructure) => {
|
|
457
535
|
const { feeFixed, feeRateBasisPoints } = feeStructure;
|
|
458
|
-
const balanceBigInt =
|
|
459
|
-
const feeFixedBigInt =
|
|
460
|
-
if (balanceBigInt <= feeFixedBigInt) return
|
|
536
|
+
const balanceBigInt = hexToBigInt4(balance);
|
|
537
|
+
const feeFixedBigInt = hexToBigInt4(feeFixed);
|
|
538
|
+
if (balanceBigInt <= feeFixedBigInt) return toHex5(0n);
|
|
461
539
|
const maxAmount = (balanceBigInt - feeFixedBigInt) * 10000n / (10000n + BigInt(feeRateBasisPoints));
|
|
462
|
-
return
|
|
463
|
-
}
|
|
540
|
+
return toHex5(maxAmount);
|
|
541
|
+
};
|
|
464
542
|
|
|
465
543
|
// src/services/util/createBridgeTransfer.ts
|
|
466
|
-
import { hexToBigInt as
|
|
544
|
+
import { hexToBigInt as hexToBigInt5 } from "@xylabs/sdk-js";
|
|
467
545
|
import { createTransferPayload as createTransferPayload2 } from "@xyo-network/xl1-sdk";
|
|
468
|
-
var createBridgeTransfer =
|
|
546
|
+
var createBridgeTransfer = (sender, srcAmount, escrowAddress, feesAddress, context) => {
|
|
469
547
|
const { feeFixed, feeVariable } = context;
|
|
470
|
-
const escrowAmount =
|
|
471
|
-
const feesAmount =
|
|
472
|
-
const transfers = escrowAddress === feesAddress ? {
|
|
473
|
-
[feesAddress]: escrowAmount + feesAmount
|
|
474
|
-
} : {
|
|
475
|
-
[escrowAddress]: escrowAmount,
|
|
476
|
-
[feesAddress]: feesAmount
|
|
477
|
-
};
|
|
548
|
+
const escrowAmount = hexToBigInt5(srcAmount);
|
|
549
|
+
const feesAmount = hexToBigInt5(feeFixed) + hexToBigInt5(feeVariable);
|
|
550
|
+
const transfers = escrowAddress === feesAddress ? { [feesAddress]: escrowAmount + feesAmount } : { [escrowAddress]: escrowAmount, [feesAddress]: feesAmount };
|
|
478
551
|
const transfer = createTransferPayload2(sender, transfers, context);
|
|
479
552
|
return transfer;
|
|
480
|
-
}
|
|
553
|
+
};
|
|
481
554
|
|
|
482
555
|
// src/services/util/generateBridgeEstimate.ts
|
|
483
556
|
import { toAddress as toAddress2 } from "@xylabs/sdk-js";
|
|
484
|
-
import { PayloadBuilder as
|
|
557
|
+
import { PayloadBuilder as PayloadBuilder5 } from "@xyo-network/sdk-js";
|
|
485
558
|
import { BridgeIntentSchema as BridgeIntentSchema2 } from "@xyo-network/xl1-sdk";
|
|
486
559
|
import { v4 } from "uuid";
|
|
487
|
-
var generateBridgeEstimate =
|
|
488
|
-
const {
|
|
489
|
-
|
|
490
|
-
const fees = calculateBridgeFees(srcAmount, {
|
|
560
|
+
var generateBridgeEstimate = async (srcAddress, srcAmount, destAddress, config, nonceOverride) => {
|
|
561
|
+
const {
|
|
562
|
+
escrowAddress,
|
|
491
563
|
feeFixed,
|
|
492
|
-
feeRateBasisPoints
|
|
493
|
-
|
|
564
|
+
feeRateBasisPoints,
|
|
565
|
+
feesAddress,
|
|
566
|
+
remoteChainId,
|
|
567
|
+
remoteTokenAddress,
|
|
568
|
+
xl1ChainId,
|
|
569
|
+
xl1TokenAddress
|
|
570
|
+
} = await getBridgeSettings(config);
|
|
571
|
+
const sender = toAddress2(srcAddress);
|
|
572
|
+
const fees = calculateBridgeFees(srcAmount, { feeFixed, feeRateBasisPoints });
|
|
494
573
|
const nonce = nonceOverride ?? v4();
|
|
495
574
|
const bridgeIntentFields = {
|
|
496
575
|
// Source
|
|
@@ -502,99 +581,92 @@ var generateBridgeEstimate = /* @__PURE__ */ __name(async (srcAddress, srcAmount
|
|
|
502
581
|
dest: remoteChainId,
|
|
503
582
|
destAddress,
|
|
504
583
|
destAmount: srcAmount,
|
|
584
|
+
// This is a 1:1 bridge. Fees are handled at the transfer level, not the bridge intent level.
|
|
505
585
|
destToken: remoteTokenAddress,
|
|
506
586
|
nonce
|
|
507
587
|
};
|
|
508
|
-
const bridgeIntent = new
|
|
509
|
-
schema: BridgeIntentSchema2
|
|
510
|
-
}).fields(bridgeIntentFields).build();
|
|
588
|
+
const bridgeIntent = new PayloadBuilder5({ schema: BridgeIntentSchema2 }).fields(bridgeIntentFields).build();
|
|
511
589
|
const transfer = createBridgeTransfer(sender, srcAmount, escrowAddress, feesAddress, fees);
|
|
512
|
-
return [
|
|
513
|
-
|
|
514
|
-
transfer
|
|
515
|
-
];
|
|
516
|
-
}, "generateBridgeEstimate");
|
|
590
|
+
return [bridgeIntent, transfer];
|
|
591
|
+
};
|
|
517
592
|
|
|
518
593
|
// src/services/validation/validateBridgeEstimateExact.ts
|
|
519
|
-
var validateBridgeEstimateExact =
|
|
520
|
-
const {
|
|
521
|
-
|
|
522
|
-
|
|
594
|
+
var validateBridgeEstimateExact = async (intent, transfer, config) => {
|
|
595
|
+
const {
|
|
596
|
+
srcAddress,
|
|
597
|
+
srcAmount,
|
|
598
|
+
destAddress
|
|
599
|
+
} = intent;
|
|
600
|
+
if (hexToBigInt6(srcAmount) < hexToBigInt6(getMinBridgeAmount(config))) return false;
|
|
601
|
+
if (hexToBigInt6(srcAmount) > hexToBigInt6(getMaxBridgeAmount(config))) return false;
|
|
523
602
|
const [calculatedIntent, calculatedTransfer] = await generateBridgeEstimate(srcAddress, srcAmount, destAddress, config);
|
|
524
603
|
if (isUndefined(calculatedIntent) || isUndefined(calculatedTransfer)) return false;
|
|
525
604
|
const { nonce: expectedIntentNonce, ...expectedIntentStatic } = calculatedIntent;
|
|
526
605
|
const { nonce: actualIntentNonce, ...actualIntentStatic } = intent;
|
|
527
|
-
if (await
|
|
606
|
+
if (await PayloadBuilder6.dataHash(expectedIntentStatic) !== await PayloadBuilder6.dataHash(actualIntentStatic)) return false;
|
|
528
607
|
const { epoch: expectedTransferEpoch, ...expectedTransferStatic } = calculatedTransfer;
|
|
529
608
|
const { epoch: actualTransferEpoch, ...actualTransferStatic } = transfer;
|
|
530
|
-
if (await
|
|
609
|
+
if (await PayloadBuilder6.dataHash(expectedTransferStatic) !== await PayloadBuilder6.dataHash(actualTransferStatic)) return false;
|
|
531
610
|
return true;
|
|
532
|
-
}
|
|
611
|
+
};
|
|
533
612
|
|
|
534
613
|
// src/services/validation/validateBridgeTransaction.ts
|
|
535
614
|
import { asAddress as asAddress4 } from "@xylabs/sdk-js";
|
|
536
|
-
import {
|
|
537
|
-
|
|
615
|
+
import {
|
|
616
|
+
addressesContains,
|
|
617
|
+
BoundWitnessValidator,
|
|
618
|
+
payloadHashesContainsAll,
|
|
619
|
+
payloadSchemasContainsAll
|
|
620
|
+
} from "@xyo-network/boundwitness-validator";
|
|
621
|
+
import { PayloadBuilder as PayloadBuilder7 } from "@xyo-network/sdk-js";
|
|
538
622
|
import { BridgeIntentSchema as BridgeIntentSchema3, TransferSchema } from "@xyo-network/xl1-sdk";
|
|
539
|
-
var validateBridgeTransaction =
|
|
623
|
+
var validateBridgeTransaction = async (signedTxBw, intent, transfer, config) => {
|
|
540
624
|
const { srcAddress } = intent;
|
|
541
625
|
const chainId = getXl1ChainId(config);
|
|
542
626
|
if (signedTxBw.chain !== chainId) return false;
|
|
543
627
|
if (signedTxBw.payload_hashes.length != 2) return false;
|
|
544
|
-
if (!payloadSchemasContainsAll(signedTxBw, [
|
|
545
|
-
|
|
546
|
-
TransferSchema
|
|
547
|
-
])) return false;
|
|
548
|
-
const hashes = await PayloadBuilder6.hashes([
|
|
549
|
-
intent,
|
|
550
|
-
transfer
|
|
551
|
-
]);
|
|
628
|
+
if (!payloadSchemasContainsAll(signedTxBw, [BridgeIntentSchema3, TransferSchema])) return false;
|
|
629
|
+
const hashes = await PayloadBuilder7.hashes([intent, transfer]);
|
|
552
630
|
if (!payloadHashesContainsAll(signedTxBw, hashes)) return false;
|
|
553
631
|
const errors = await new BoundWitnessValidator(signedTxBw).validate();
|
|
554
632
|
if (errors.length > 0) return false;
|
|
555
633
|
const sender = asAddress4(srcAddress, true);
|
|
556
634
|
if (!addressesContains(signedTxBw, sender)) return false;
|
|
557
635
|
return true;
|
|
558
|
-
}
|
|
636
|
+
};
|
|
559
637
|
|
|
560
638
|
// src/services/validation/validateSufficientLiquiditySourceAllowance.ts
|
|
561
|
-
import { assertEx as
|
|
639
|
+
import { assertEx as assertEx10, hexToBigInt as hexToBigInt7 } from "@xylabs/sdk-js";
|
|
562
640
|
import { isBridgeIntent as isBridgeIntent2 } from "@xyo-network/xl1-sdk";
|
|
563
|
-
var validateSufficientLiquiditySourceAllowance =
|
|
564
|
-
const allPayloads = [
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
];
|
|
568
|
-
const bridgeIntent = assertEx9(allPayloads.find(isBridgeIntent2), () => "No bridge intent found");
|
|
569
|
-
const amount = hexToBigInt6(bridgeIntent.destAmount);
|
|
641
|
+
var validateSufficientLiquiditySourceAllowance = async (tx, offChainPayloads, bridgeableToken, bridge, logger) => {
|
|
642
|
+
const allPayloads = [...tx[1], ...offChainPayloads];
|
|
643
|
+
const bridgeIntent = assertEx10(allPayloads.find(isBridgeIntent2), () => "No bridge intent found");
|
|
644
|
+
const amount = hexToBigInt7(bridgeIntent.destAmount);
|
|
570
645
|
const liquiditySourceAddress = await bridge.liquiditySource();
|
|
571
646
|
const bridgeAddress = await bridge.getAddress();
|
|
572
647
|
const remainingAllowance = await bridgeableToken.allowance(liquiditySourceAddress, bridgeAddress);
|
|
573
648
|
await logger?.log(`Remaining allowance: ${remainingAllowance.toString()}`);
|
|
574
649
|
return remainingAllowance >= amount;
|
|
575
|
-
}
|
|
650
|
+
};
|
|
576
651
|
|
|
577
652
|
// src/services/validation/validateSufficientLiquiditySourceBalance.ts
|
|
578
|
-
import { assertEx as
|
|
653
|
+
import { assertEx as assertEx11, hexToBigInt as hexToBigInt8 } from "@xylabs/sdk-js";
|
|
579
654
|
import { isBridgeIntent as isBridgeIntent3 } from "@xyo-network/xl1-sdk";
|
|
580
|
-
var validateSufficientLiquiditySourceBalance =
|
|
581
|
-
const allPayloads = [
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
];
|
|
585
|
-
const bridgeIntent = assertEx10(allPayloads.find(isBridgeIntent3), () => "No bridge intent found");
|
|
586
|
-
const amount = hexToBigInt7(bridgeIntent.destAmount);
|
|
655
|
+
var validateSufficientLiquiditySourceBalance = async (tx, offChainPayloads, bridgeableToken, bridge, logger) => {
|
|
656
|
+
const allPayloads = [...tx[1], ...offChainPayloads];
|
|
657
|
+
const bridgeIntent = assertEx11(allPayloads.find(isBridgeIntent3), () => "No bridge intent found");
|
|
658
|
+
const amount = hexToBigInt8(bridgeIntent.destAmount);
|
|
587
659
|
const liquiditySourceAddress = await bridge.liquiditySource();
|
|
588
660
|
const balance = await bridgeableToken.balanceOf(liquiditySourceAddress);
|
|
589
661
|
await logger?.log(`Remaining balance: ${balance.toString()}`);
|
|
590
662
|
return balance >= amount;
|
|
591
|
-
}
|
|
663
|
+
};
|
|
592
664
|
|
|
593
665
|
// src/services/validation/validateSufficientRunnerEthBalanceForGas.ts
|
|
594
|
-
import { assertEx as
|
|
666
|
+
import { assertEx as assertEx12 } from "@xylabs/sdk-js";
|
|
595
667
|
var DEFAULT_GAS_BUFFER_BPS = 2000n;
|
|
596
|
-
var validateSufficientRunnerEthBalanceForGas =
|
|
597
|
-
const provider =
|
|
668
|
+
var validateSufficientRunnerEthBalanceForGas = async (preparedTx, wallet, logger, bufferBps = DEFAULT_GAS_BUFFER_BPS) => {
|
|
669
|
+
const provider = assertEx12(wallet.provider, () => "Wallet provider is not defined");
|
|
598
670
|
const feeData = await provider.getFeeData();
|
|
599
671
|
const perGas = feeData.maxFeePerGas ?? feeData.gasPrice;
|
|
600
672
|
if (perGas == null) {
|
|
@@ -610,91 +682,104 @@ var validateSufficientRunnerEthBalanceForGas = /* @__PURE__ */ __name(async (pre
|
|
|
610
682
|
const baseRequired = estGas * perGas + txValue;
|
|
611
683
|
const required = baseRequired * (10000n + bufferBps) / 10000n;
|
|
612
684
|
const balance = await provider.getBalance(await wallet.getAddress());
|
|
613
|
-
await logger?.log(
|
|
685
|
+
await logger?.log(
|
|
686
|
+
`[gas] runner=${await wallet.getAddress()} balance=${balance.toString()} estGas=${estGas.toString()} perGas=${perGas.toString()} value=${txValue.toString()} requiredWithBuffer=${required.toString()} bufferBps=${bufferBps.toString()}`
|
|
687
|
+
);
|
|
614
688
|
return balance >= required;
|
|
615
|
-
}
|
|
689
|
+
};
|
|
616
690
|
|
|
617
691
|
// src/services/validation/validateSufficientXl1ReserveBalance.ts
|
|
618
|
-
import { assertEx as
|
|
619
|
-
async function validateSufficientXl1ReserveBalance({
|
|
620
|
-
|
|
692
|
+
import { assertEx as assertEx13 } from "@xylabs/sdk-js";
|
|
693
|
+
async function validateSufficientXl1ReserveBalance({
|
|
694
|
+
amount,
|
|
695
|
+
bridgeAccount,
|
|
696
|
+
gateway,
|
|
697
|
+
logger
|
|
698
|
+
}) {
|
|
699
|
+
const viewer = assertEx13(gateway.connection.viewer, () => "Gateway connection does not have a viewer");
|
|
621
700
|
const balance = await viewer.account.balance.accountBalance(bridgeAccount.address);
|
|
622
701
|
await logger?.log(`XL1 reserve account ${bridgeAccount.address} balance: ${balance.toString()}; required: ${amount.toString()}`);
|
|
623
702
|
return balance >= amount;
|
|
624
703
|
}
|
|
625
|
-
__name(validateSufficientXl1ReserveBalance, "validateSufficientXl1ReserveBalance");
|
|
626
704
|
|
|
627
705
|
// src/services/validation/validateSufficientXL1SourceAddressBalance.ts
|
|
628
|
-
import {
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
706
|
+
import {
|
|
707
|
+
asAddress as asAddress5,
|
|
708
|
+
assertEx as assertEx14,
|
|
709
|
+
hexToBigInt as hexToBigInt9
|
|
710
|
+
} from "@xylabs/sdk-js";
|
|
711
|
+
var validateSufficientXL1SourceAddressBalance = async (bridgeIntent, gateway, config, logger) => {
|
|
712
|
+
const viewer = assertEx14(gateway.connection.viewer, () => "Gateway connection does not have a viewer");
|
|
713
|
+
const {
|
|
714
|
+
srcAddress,
|
|
715
|
+
srcAmount,
|
|
716
|
+
destAddress
|
|
717
|
+
} = bridgeIntent;
|
|
632
718
|
const srcAddressBranded = asAddress5(srcAddress, () => `Invalid source address in bridge intent: ${srcAddress}`);
|
|
633
719
|
const [_, calculatedTransfer] = await generateBridgeEstimate(srcAddress, srcAmount, destAddress, config);
|
|
634
|
-
const totalAmount = Object.values(calculatedTransfer.transfers).reduce((acc, transfer) => acc +
|
|
720
|
+
const totalAmount = Object.values(calculatedTransfer.transfers).reduce((acc, transfer) => acc + hexToBigInt9(transfer), 0n);
|
|
635
721
|
const accountBalance = await viewer.account.balance.accountBalance(srcAddressBranded);
|
|
636
722
|
await logger?.log(`Account balance for ${srcAddressBranded}: ${accountBalance.toString()}`);
|
|
637
723
|
return accountBalance >= totalAmount;
|
|
638
|
-
}
|
|
724
|
+
};
|
|
639
725
|
|
|
640
726
|
// src/services/queue/workers/EthTransactionPreparation.ts
|
|
641
727
|
var name4 = "Prepare ETH Transaction";
|
|
642
728
|
var queueName4 = "eth-tx-prepare";
|
|
643
|
-
var createWorker4 =
|
|
644
|
-
const bridge =
|
|
645
|
-
const bridgeableToken =
|
|
646
|
-
const stateMap =
|
|
647
|
-
const wallet =
|
|
648
|
-
const worker = new Worker4(
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
...offChainPayloads
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
729
|
+
var createWorker4 = (connection2, telemetry2, services) => {
|
|
730
|
+
const bridge = assertEx15(services?.bridge, () => "bridge service not provided");
|
|
731
|
+
const bridgeableToken = assertEx15(services?.bridgeableToken, () => "bridgeableToken service not provided");
|
|
732
|
+
const stateMap = assertEx15(services?.ethTxStateMap, () => "ethTxStateMap service not provided");
|
|
733
|
+
const wallet = assertEx15(services?.wallet, () => "wallet service not provided");
|
|
734
|
+
const worker = new Worker4(
|
|
735
|
+
queueName4,
|
|
736
|
+
async (job) => {
|
|
737
|
+
const { tx, offChainPayloads } = job.data;
|
|
738
|
+
const hash = await PayloadBuilder8.hash(tx[0]);
|
|
739
|
+
await job.log(`[${hash}] preparing ETH transaction`);
|
|
740
|
+
await job.log(`[${hash}] validating liquiditySource has sufficient allowance`);
|
|
741
|
+
if (!await validateSufficientLiquiditySourceAllowance(tx, offChainPayloads, bridgeableToken, bridge, job)) {
|
|
742
|
+
throw new Error("Liquidity source does not have sufficient allowance for the bridge to execute the transaction");
|
|
743
|
+
}
|
|
744
|
+
await job.log(`[${hash}] validated liquiditySource has sufficient allowance`);
|
|
745
|
+
await job.log(`[${hash}] validating liquiditySource has sufficient balance`);
|
|
746
|
+
if (!await validateSufficientLiquiditySourceBalance(tx, offChainPayloads, bridgeableToken, bridge, job)) {
|
|
747
|
+
throw new Error("Liquidity source does not have sufficient balance for the bridge to execute the transaction");
|
|
748
|
+
}
|
|
749
|
+
await job.log(`[${hash}] validated liquiditySource has sufficient balance`);
|
|
750
|
+
await job.log(`[${hash}] building ETH transaction`);
|
|
751
|
+
const allPayloads = [...tx[1], ...offChainPayloads];
|
|
752
|
+
const bridgeIntent = assertEx15(allPayloads.find(isBridgeIntent4), () => "No bridge intent found");
|
|
753
|
+
const amount = hexToBigInt10(bridgeIntent.destAmount);
|
|
754
|
+
const srcAddress = getAddress(bridgeIntent.srcAddress);
|
|
755
|
+
const destAddress = getAddress(bridgeIntent.destAddress);
|
|
756
|
+
const nonce = hexToBigInt10(await PayloadBuilder8.hash(tx[0]));
|
|
757
|
+
const preparedTx = await bridge.getFunction("bridgeFromRemote").populateTransaction(srcAddress, destAddress, amount, nonce);
|
|
758
|
+
await job.log(`[${hash}] built ETH transaction`);
|
|
759
|
+
await job.log(`[${hash}] validating tx runner has sufficient ETH for gas`);
|
|
760
|
+
if (!await validateSufficientRunnerEthBalanceForGas(preparedTx, wallet, job)) {
|
|
761
|
+
throw new Error("Transaction runner does not have sufficient ETH to cover estimated gas (with buffer)");
|
|
762
|
+
}
|
|
763
|
+
await job.log(`[${hash}] validated tx runner has sufficient ETH for gas`);
|
|
764
|
+
await job.log(`[${hash}] storing ETH preparedTx`);
|
|
765
|
+
await stateMap.set(hash, { preparedTx });
|
|
766
|
+
await job.log(`[${hash}] stored ETH preparedTx`);
|
|
767
|
+
await job.log(`[${hash}] prepared ETH transaction`);
|
|
768
|
+
return {};
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
connection: connection2,
|
|
772
|
+
telemetry: telemetry2,
|
|
773
|
+
prefix
|
|
677
774
|
}
|
|
678
|
-
|
|
679
|
-
await job.log(`[${hash}] storing ETH preparedTx`);
|
|
680
|
-
await stateMap.set(hash, {
|
|
681
|
-
preparedTx
|
|
682
|
-
});
|
|
683
|
-
await job.log(`[${hash}] stored ETH preparedTx`);
|
|
684
|
-
await job.log(`[${hash}] prepared ETH transaction`);
|
|
685
|
-
return {};
|
|
686
|
-
}, {
|
|
687
|
-
connection: connection2,
|
|
688
|
-
telemetry: telemetry2,
|
|
689
|
-
prefix
|
|
690
|
-
});
|
|
775
|
+
);
|
|
691
776
|
worker.on("failed", (job, err) => {
|
|
692
777
|
console.error(`[${name4}] Job ${job?.id} failed:`, err.message);
|
|
693
778
|
});
|
|
694
779
|
worker.on("error", (err) => {
|
|
695
780
|
console.error(`[${name4}] Worker error:`, err);
|
|
696
781
|
});
|
|
697
|
-
}
|
|
782
|
+
};
|
|
698
783
|
var EthTransactionPreparation = {
|
|
699
784
|
createWorker: createWorker4,
|
|
700
785
|
name: name4,
|
|
@@ -702,45 +787,45 @@ var EthTransactionPreparation = {
|
|
|
702
787
|
};
|
|
703
788
|
|
|
704
789
|
// src/services/queue/workers/EthTransactionSubmission.ts
|
|
705
|
-
import { assertEx as
|
|
706
|
-
import { PayloadBuilder as
|
|
790
|
+
import { assertEx as assertEx16, isDefined as isDefined7 } from "@xylabs/sdk-js";
|
|
791
|
+
import { PayloadBuilder as PayloadBuilder9 } from "@xyo-network/sdk-js";
|
|
707
792
|
import { Worker as Worker5 } from "bullmq";
|
|
708
793
|
var name5 = "Submit ETH Transaction";
|
|
709
794
|
var queueName5 = "eth-tx-submit";
|
|
710
|
-
var createWorker5 =
|
|
711
|
-
const bridge =
|
|
712
|
-
const wallet =
|
|
713
|
-
const stateMap =
|
|
714
|
-
const worker = new Worker5(
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
795
|
+
var createWorker5 = (connection2, telemetry2, services) => {
|
|
796
|
+
const bridge = assertEx16(services?.bridge, () => "bridge service not provided");
|
|
797
|
+
const wallet = assertEx16(services?.wallet, () => "wallet service not provided");
|
|
798
|
+
const stateMap = assertEx16(services?.ethTxStateMap, () => "ethTxStateMap service not provided");
|
|
799
|
+
const worker = new Worker5(
|
|
800
|
+
queueName5,
|
|
801
|
+
async (job) => {
|
|
802
|
+
const { tx, offChainPayloads } = job.data;
|
|
803
|
+
const hash = await PayloadBuilder9.hash(tx[0]);
|
|
804
|
+
const state = assertEx16(await stateMap.get(hash), () => `[${hash}] state not found`);
|
|
805
|
+
const { submissionHash: existingSubmissionHash } = state;
|
|
806
|
+
if (isDefined7(existingSubmissionHash)) {
|
|
807
|
+
await job.log(`[${hash}] Tx already submitted with submission response hash ${existingSubmissionHash}`);
|
|
808
|
+
return { submissionHash: existingSubmissionHash };
|
|
809
|
+
}
|
|
810
|
+
await job.log(`[${hash}] Submitting ETH tx`);
|
|
811
|
+
const submissionHash = assertEx16(await submitEthTransaction(tx, offChainPayloads, bridge, wallet), () => `[${hash}] submissionHash not found in receipt`);
|
|
812
|
+
await job.log(`[${hash}] Submitted ETH tx and received submission response hash ${submissionHash}`);
|
|
813
|
+
return { submissionHash };
|
|
814
|
+
},
|
|
815
|
+
{
|
|
816
|
+
connection: connection2,
|
|
817
|
+
telemetry: telemetry2,
|
|
818
|
+
concurrency: 1,
|
|
819
|
+
prefix
|
|
724
820
|
}
|
|
725
|
-
|
|
726
|
-
const submissionHash = assertEx15(await submitEthTransaction(tx, offChainPayloads, bridge, wallet), () => `[${hash}] submissionHash not found in receipt`);
|
|
727
|
-
await job.log(`[${hash}] Submitted ETH tx and received submission response hash ${submissionHash}`);
|
|
728
|
-
return {
|
|
729
|
-
submissionHash
|
|
730
|
-
};
|
|
731
|
-
}, {
|
|
732
|
-
connection: connection2,
|
|
733
|
-
telemetry: telemetry2,
|
|
734
|
-
concurrency: 1,
|
|
735
|
-
prefix
|
|
736
|
-
});
|
|
821
|
+
);
|
|
737
822
|
worker.on("failed", (job, err) => {
|
|
738
823
|
console.error(`[${name5}] Job ${job?.id} failed:`, err.message);
|
|
739
824
|
});
|
|
740
825
|
worker.on("error", (err) => {
|
|
741
826
|
console.error(`[${name5}] Worker error:`, err);
|
|
742
827
|
});
|
|
743
|
-
}
|
|
828
|
+
};
|
|
744
829
|
var EthTransactionSubmission = {
|
|
745
830
|
createWorker: createWorker5,
|
|
746
831
|
name: name5,
|
|
@@ -748,48 +833,48 @@ var EthTransactionSubmission = {
|
|
|
748
833
|
};
|
|
749
834
|
|
|
750
835
|
// src/services/queue/workers/EthTransactionSubmissionStorage.ts
|
|
751
|
-
import { assertEx as
|
|
752
|
-
import { PayloadBuilder as
|
|
836
|
+
import { assertEx as assertEx17, isDefined as isDefined8 } from "@xylabs/sdk-js";
|
|
837
|
+
import { PayloadBuilder as PayloadBuilder10 } from "@xyo-network/sdk-js";
|
|
753
838
|
import { Worker as Worker6 } from "bullmq";
|
|
754
839
|
var name6 = "Store ETH Transaction Submission";
|
|
755
840
|
var queueName6 = "eth-tx-store-submission";
|
|
756
|
-
var createWorker6 =
|
|
757
|
-
const stateMap =
|
|
758
|
-
const worker = new Worker6(
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
submissionHash
|
|
767
|
-
|
|
841
|
+
var createWorker6 = (connection2, telemetry2, services) => {
|
|
842
|
+
const stateMap = assertEx17(services?.ethTxStateMap, () => "ethTxStateMap service not provided");
|
|
843
|
+
const worker = new Worker6(
|
|
844
|
+
queueName6,
|
|
845
|
+
async (job) => {
|
|
846
|
+
const { tx } = job.data;
|
|
847
|
+
const hash = await PayloadBuilder10.hash(tx[0]);
|
|
848
|
+
const state = assertEx17(await stateMap.get(hash), () => `[${hash}] state not found`);
|
|
849
|
+
const { submissionHash: existingSubmissionHash } = state;
|
|
850
|
+
if (isDefined8(existingSubmissionHash)) {
|
|
851
|
+
await job.log(`[${hash}] submissionHash already stored as ${existingSubmissionHash}`);
|
|
852
|
+
return { submissionHash: existingSubmissionHash };
|
|
853
|
+
}
|
|
854
|
+
const childrenValues = await job.getChildrenValues();
|
|
855
|
+
const jobKey = `${prefix}:${EthTransactionSubmission.queueName}:${hash}`;
|
|
856
|
+
const childValues = childrenValues?.[jobKey];
|
|
857
|
+
const submissionHash = childValues?.submissionHash;
|
|
858
|
+
const resolvedSubmissionHash = assertEx17(submissionHash, () => `[${hash}] child submissionHash not found in children values`);
|
|
859
|
+
await job.log(`[${hash}] Storing ETH submissionHash`);
|
|
860
|
+
state.submissionHash = resolvedSubmissionHash;
|
|
861
|
+
await stateMap.set(hash, state);
|
|
862
|
+
await job.log(`[${hash}] Stored ETH submissionHash`);
|
|
863
|
+
return { submissionHash: resolvedSubmissionHash };
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
connection: connection2,
|
|
867
|
+
telemetry: telemetry2,
|
|
868
|
+
prefix
|
|
768
869
|
}
|
|
769
|
-
|
|
770
|
-
const jobKey = `${prefix}:${EthTransactionSubmission.queueName}:${hash}`;
|
|
771
|
-
const childValues = childrenValues?.[jobKey];
|
|
772
|
-
const submissionHash = childValues?.submissionHash;
|
|
773
|
-
const resolvedSubmissionHash = assertEx16(submissionHash, () => `[${hash}] child submissionHash not found in children values`);
|
|
774
|
-
await job.log(`[${hash}] Storing ETH submissionHash`);
|
|
775
|
-
state.submissionHash = resolvedSubmissionHash;
|
|
776
|
-
await stateMap.set(hash, state);
|
|
777
|
-
await job.log(`[${hash}] Stored ETH submissionHash`);
|
|
778
|
-
return {
|
|
779
|
-
submissionHash: resolvedSubmissionHash
|
|
780
|
-
};
|
|
781
|
-
}, {
|
|
782
|
-
connection: connection2,
|
|
783
|
-
telemetry: telemetry2,
|
|
784
|
-
prefix
|
|
785
|
-
});
|
|
870
|
+
);
|
|
786
871
|
worker.on("failed", (job, err) => {
|
|
787
872
|
console.error(`[${name6}] Job ${job?.id} failed:`, err.message);
|
|
788
873
|
});
|
|
789
874
|
worker.on("error", (err) => {
|
|
790
875
|
console.error(`[${name6}] Worker error:`, err);
|
|
791
876
|
});
|
|
792
|
-
}
|
|
877
|
+
};
|
|
793
878
|
var EthTransactionSubmissionStorage = {
|
|
794
879
|
createWorker: createWorker6,
|
|
795
880
|
name: name6,
|
|
@@ -797,8 +882,15 @@ var EthTransactionSubmissionStorage = {
|
|
|
797
882
|
};
|
|
798
883
|
|
|
799
884
|
// src/services/queue/workers/Xl1ReserveTxFulfillment.ts
|
|
800
|
-
import {
|
|
801
|
-
|
|
885
|
+
import {
|
|
886
|
+
assertEx as assertEx18,
|
|
887
|
+
delay,
|
|
888
|
+
hexToBigInt as hexToBigInt11,
|
|
889
|
+
isDefined as isDefined9,
|
|
890
|
+
isNull as isNull2,
|
|
891
|
+
toHex as toHex6
|
|
892
|
+
} from "@xylabs/sdk-js";
|
|
893
|
+
import { PayloadBuilder as PayloadBuilder11 } from "@xyo-network/sdk-js";
|
|
802
894
|
import { asXL1BlockNumber } from "@xyo-network/xl1-sdk";
|
|
803
895
|
import { Worker as Worker7 } from "bullmq";
|
|
804
896
|
var name7 = "XL1 Reserve Transfer Fulfillment";
|
|
@@ -807,8 +899,14 @@ var EXP_BLOCKS_AHEAD = 1e3;
|
|
|
807
899
|
var POLL_INTERVAL_MS = 5e3;
|
|
808
900
|
var CONCURRENCY = 32;
|
|
809
901
|
async function tryResumeCurrentAttempt(ctx) {
|
|
810
|
-
const {
|
|
811
|
-
|
|
902
|
+
const {
|
|
903
|
+
fulfillmentMap,
|
|
904
|
+
identity,
|
|
905
|
+
job,
|
|
906
|
+
state,
|
|
907
|
+
viewer
|
|
908
|
+
} = ctx;
|
|
909
|
+
const attempt = assertEx18(state.currentAttempt, () => "tryResumeCurrentAttempt called without currentAttempt");
|
|
812
910
|
const found = await viewer.transaction.byHash(attempt.txHash);
|
|
813
911
|
if (isDefined9(found) && !isNull2(found)) {
|
|
814
912
|
state.fulfilled = attempt;
|
|
@@ -825,10 +923,26 @@ async function tryResumeCurrentAttempt(ctx) {
|
|
|
825
923
|
await job.log(`[${identity}] resumed attempt expired (head=${head}); will build fresh`);
|
|
826
924
|
}
|
|
827
925
|
}
|
|
828
|
-
__name(tryResumeCurrentAttempt, "tryResumeCurrentAttempt");
|
|
829
926
|
async function buildAndSubmitFreshAttempt(ctx) {
|
|
830
|
-
const {
|
|
831
|
-
|
|
927
|
+
const {
|
|
928
|
+
account,
|
|
929
|
+
bridgeId,
|
|
930
|
+
config,
|
|
931
|
+
contractAddress,
|
|
932
|
+
evmChainId,
|
|
933
|
+
fulfillmentMap,
|
|
934
|
+
gateway,
|
|
935
|
+
identity,
|
|
936
|
+
job,
|
|
937
|
+
state,
|
|
938
|
+
viewer,
|
|
939
|
+
xl1ChainId,
|
|
940
|
+
xl1TokenAddress
|
|
941
|
+
} = ctx;
|
|
942
|
+
const canonical = assertEx18(state.canonical, () => "buildAndSubmitFreshAttempt requires canonical");
|
|
943
|
+
const fees = calculateBridgeFees(toHex6(canonical.amount), getFeeStructure(config));
|
|
944
|
+
const feesAmount = hexToBigInt11(fees.feeFixed) + hexToBigInt11(fees.feeVariable);
|
|
945
|
+
const { feesAddress } = await getTransferAddresses(config);
|
|
832
946
|
const sufficient = await validateSufficientXl1ReserveBalance({
|
|
833
947
|
amount: canonical.amount,
|
|
834
948
|
bridgeAccount: account,
|
|
@@ -853,11 +967,13 @@ async function buildAndSubmitFreshAttempt(ctx) {
|
|
|
853
967
|
evmTokenAddress: canonical.destToken,
|
|
854
968
|
evmTxHash: canonical.evmTxHash,
|
|
855
969
|
exp,
|
|
970
|
+
feesAddress,
|
|
971
|
+
feesAmount,
|
|
856
972
|
nbf,
|
|
857
973
|
xl1ChainId,
|
|
858
974
|
xl1TokenAddress
|
|
859
975
|
});
|
|
860
|
-
const txHash = await
|
|
976
|
+
const txHash = await PayloadBuilder11.hash(tx[0]);
|
|
861
977
|
state.currentAttempt = {
|
|
862
978
|
exp: head + EXP_BLOCKS_AHEAD,
|
|
863
979
|
nbf: head,
|
|
@@ -866,12 +982,19 @@ async function buildAndSubmitFreshAttempt(ctx) {
|
|
|
866
982
|
};
|
|
867
983
|
await fulfillmentMap.set(identity, state);
|
|
868
984
|
await submitXl1Transaction(tx, [], gateway);
|
|
869
|
-
await job.log(
|
|
985
|
+
await job.log(
|
|
986
|
+
`[${identity}] attempt ${state.previousAttempts.length + 1} submitted: txHash=${txHash} nbf=${head} exp=${head + EXP_BLOCKS_AHEAD}`
|
|
987
|
+
);
|
|
870
988
|
}
|
|
871
|
-
__name(buildAndSubmitFreshAttempt, "buildAndSubmitFreshAttempt");
|
|
872
989
|
async function pollUntilIncludedOrExpired(ctx) {
|
|
873
|
-
const {
|
|
874
|
-
|
|
990
|
+
const {
|
|
991
|
+
fulfillmentMap,
|
|
992
|
+
identity,
|
|
993
|
+
job,
|
|
994
|
+
state,
|
|
995
|
+
viewer
|
|
996
|
+
} = ctx;
|
|
997
|
+
const attempt = assertEx18(state.currentAttempt, () => "pollUntilIncludedOrExpired requires currentAttempt");
|
|
875
998
|
while (true) {
|
|
876
999
|
const found = await viewer.transaction.byHash(attempt.txHash);
|
|
877
1000
|
if (isDefined9(found) && !isNull2(found)) {
|
|
@@ -893,54 +1016,80 @@ async function pollUntilIncludedOrExpired(ctx) {
|
|
|
893
1016
|
await delay(POLL_INTERVAL_MS);
|
|
894
1017
|
}
|
|
895
1018
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
const
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
if (state.failed) {
|
|
910
|
-
state.failed = void 0;
|
|
911
|
-
await bridgeFulfillmentMap.set(identity, state);
|
|
912
|
-
}
|
|
913
|
-
const viewer = assertEx17(gateway.connection.viewer, () => `[${identity}] gateway viewer not available`);
|
|
914
|
-
const ctx = {
|
|
915
|
-
fulfillmentMap: bridgeFulfillmentMap,
|
|
916
|
-
identity,
|
|
917
|
-
job,
|
|
918
|
-
state,
|
|
919
|
-
viewer
|
|
920
|
-
};
|
|
921
|
-
if (state.currentAttempt) {
|
|
922
|
-
await tryResumeCurrentAttempt(ctx);
|
|
923
|
-
if (state.fulfilled) return;
|
|
924
|
-
}
|
|
925
|
-
if (!state.currentAttempt) {
|
|
926
|
-
await buildAndSubmitFreshAttempt({
|
|
927
|
-
...ctx,
|
|
928
|
-
account,
|
|
929
|
-
bridgeId: BigInt(bridgeId),
|
|
1019
|
+
var createWorker7 = (connection2, telemetry2, services) => {
|
|
1020
|
+
const svc = assertEx18(services, () => "services not provided");
|
|
1021
|
+
const {
|
|
1022
|
+
account,
|
|
1023
|
+
bridgeFulfillmentMap,
|
|
1024
|
+
config,
|
|
1025
|
+
gateway
|
|
1026
|
+
} = svc;
|
|
1027
|
+
const worker = new Worker7(
|
|
1028
|
+
queueName7,
|
|
1029
|
+
async (job) => {
|
|
1030
|
+
const {
|
|
1031
|
+
bridgeId,
|
|
930
1032
|
contractAddress,
|
|
931
1033
|
evmChainId,
|
|
932
|
-
|
|
1034
|
+
identity,
|
|
933
1035
|
xl1ChainId,
|
|
934
1036
|
xl1TokenAddress
|
|
935
|
-
}
|
|
1037
|
+
} = job.data;
|
|
1038
|
+
const initialState = await bridgeFulfillmentMap.get(identity);
|
|
1039
|
+
if (initialState?.fulfilled) {
|
|
1040
|
+
await job.log(`[${identity}] already fulfilled \u2014 skipping`);
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
const state = assertEx18(initialState, () => `[${identity}] no fulfillment state \u2014 Stage 1 did not run`);
|
|
1044
|
+
const canonical = assertEx18(state.canonical, () => `[${identity}] canonical missing \u2014 Stage 1 did not write canonical`);
|
|
1045
|
+
if (state.failed) {
|
|
1046
|
+
state.failed = void 0;
|
|
1047
|
+
await bridgeFulfillmentMap.set(identity, state);
|
|
1048
|
+
}
|
|
1049
|
+
const minBridgeAmount = getMinBridgeAmount(config);
|
|
1050
|
+
if (!validateAmountMeetsMinBridgeAmount({ amount: canonical.amount, minBridgeAmount })) {
|
|
1051
|
+
state.failed = {
|
|
1052
|
+
at: Date.now(),
|
|
1053
|
+
reason: `below_min_bridge_amount: amount=${canonical.amount} minBridgeAmount=${minBridgeAmount}`
|
|
1054
|
+
};
|
|
1055
|
+
await bridgeFulfillmentMap.set(identity, state);
|
|
1056
|
+
await job.log(`[${identity}] amount ${canonical.amount} below minBridgeAmount ${minBridgeAmount}; terminal`);
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
const viewer = assertEx18(gateway.connection.viewer, () => `[${identity}] gateway viewer not available`);
|
|
1060
|
+
const ctx = {
|
|
1061
|
+
fulfillmentMap: bridgeFulfillmentMap,
|
|
1062
|
+
identity,
|
|
1063
|
+
job,
|
|
1064
|
+
state,
|
|
1065
|
+
viewer
|
|
1066
|
+
};
|
|
1067
|
+
if (state.currentAttempt) {
|
|
1068
|
+
await tryResumeCurrentAttempt(ctx);
|
|
1069
|
+
if (state.fulfilled) return;
|
|
1070
|
+
}
|
|
1071
|
+
if (!state.currentAttempt) {
|
|
1072
|
+
await buildAndSubmitFreshAttempt({
|
|
1073
|
+
...ctx,
|
|
1074
|
+
account,
|
|
1075
|
+
bridgeId: BigInt(bridgeId),
|
|
1076
|
+
config,
|
|
1077
|
+
contractAddress,
|
|
1078
|
+
evmChainId,
|
|
1079
|
+
gateway,
|
|
1080
|
+
xl1ChainId,
|
|
1081
|
+
xl1TokenAddress
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
await pollUntilIncludedOrExpired(ctx);
|
|
1085
|
+
},
|
|
1086
|
+
{
|
|
1087
|
+
concurrency: CONCURRENCY,
|
|
1088
|
+
connection: connection2,
|
|
1089
|
+
prefix,
|
|
1090
|
+
telemetry: telemetry2
|
|
936
1091
|
}
|
|
937
|
-
|
|
938
|
-
}, {
|
|
939
|
-
concurrency: CONCURRENCY,
|
|
940
|
-
connection: connection2,
|
|
941
|
-
prefix,
|
|
942
|
-
telemetry: telemetry2
|
|
943
|
-
});
|
|
1092
|
+
);
|
|
944
1093
|
worker.on("failed", async (job, err) => {
|
|
945
1094
|
if (!isDefined9(job)) return;
|
|
946
1095
|
const attemptsAllowed = job.opts.attempts ?? Infinity;
|
|
@@ -958,7 +1107,7 @@ var createWorker7 = /* @__PURE__ */ __name((connection2, telemetry2, services) =
|
|
|
958
1107
|
worker.on("error", (err) => {
|
|
959
1108
|
console.error(`[${name7}] Worker error:`, err);
|
|
960
1109
|
});
|
|
961
|
-
}
|
|
1110
|
+
};
|
|
962
1111
|
var Xl1ReserveTxFulfillment = {
|
|
963
1112
|
createWorker: createWorker7,
|
|
964
1113
|
name: name7,
|
|
@@ -969,23 +1118,27 @@ var Xl1ReserveTxFulfillment = {
|
|
|
969
1118
|
import { Worker as Worker8 } from "bullmq";
|
|
970
1119
|
var name8 = "Bridge XL1 to Ethereum";
|
|
971
1120
|
var queueName8 = "xl1-to-eth-bridge";
|
|
972
|
-
var createWorker8 =
|
|
973
|
-
const worker = new Worker8(
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1121
|
+
var createWorker8 = (connection2, telemetry2) => {
|
|
1122
|
+
const worker = new Worker8(
|
|
1123
|
+
queueName8,
|
|
1124
|
+
async (job) => {
|
|
1125
|
+
await job.log(`[${job.name}] start`);
|
|
1126
|
+
await job.log(`[${job.name}] done`);
|
|
1127
|
+
return {};
|
|
1128
|
+
},
|
|
1129
|
+
{
|
|
1130
|
+
connection: connection2,
|
|
1131
|
+
telemetry: telemetry2,
|
|
1132
|
+
prefix
|
|
1133
|
+
}
|
|
1134
|
+
);
|
|
982
1135
|
worker.on("failed", (job, err) => {
|
|
983
1136
|
console.error(`[${name8}] Job ${job?.id} failed:`, err.message);
|
|
984
1137
|
});
|
|
985
1138
|
worker.on("error", (err) => {
|
|
986
1139
|
console.error(`[${name8}] Worker error:`, err);
|
|
987
1140
|
});
|
|
988
|
-
}
|
|
1141
|
+
};
|
|
989
1142
|
var Xl1ToEthBridgeParent = {
|
|
990
1143
|
createWorker: createWorker8,
|
|
991
1144
|
name: name8,
|
|
@@ -993,48 +1146,56 @@ var Xl1ToEthBridgeParent = {
|
|
|
993
1146
|
};
|
|
994
1147
|
|
|
995
1148
|
// src/services/queue/workers/Xl1TransactionMonitor.ts
|
|
996
|
-
import {
|
|
997
|
-
|
|
1149
|
+
import {
|
|
1150
|
+
assertEx as assertEx19,
|
|
1151
|
+
isDefined as isDefined10,
|
|
1152
|
+
isNull as isNull3
|
|
1153
|
+
} from "@xylabs/sdk-js";
|
|
1154
|
+
import { PayloadBuilder as PayloadBuilder12 } from "@xyo-network/sdk-js";
|
|
998
1155
|
import { UnrecoverableError as UnrecoverableError2, Worker as Worker9 } from "bullmq";
|
|
999
1156
|
var name9 = "Monitor Submitted XL1 Transaction";
|
|
1000
1157
|
var queueName9 = "xl1-tx-monitor";
|
|
1001
|
-
var createWorker9 =
|
|
1002
|
-
const gateway =
|
|
1003
|
-
const stateMap =
|
|
1004
|
-
const viewer =
|
|
1005
|
-
const worker = new Worker9(
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
await
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1158
|
+
var createWorker9 = (connection2, telemetry2, services) => {
|
|
1159
|
+
const gateway = assertEx19(services?.gateway, () => "gateway service not provided");
|
|
1160
|
+
const stateMap = assertEx19(services?.xl1TxStateMap, () => "xl1TxStateMap service not provided");
|
|
1161
|
+
const viewer = assertEx19(gateway.connection.viewer, () => "viewer not defined on gateway");
|
|
1162
|
+
const worker = new Worker9(
|
|
1163
|
+
queueName9,
|
|
1164
|
+
async (job) => {
|
|
1165
|
+
const { tx } = job.data;
|
|
1166
|
+
const hash = await PayloadBuilder12.hash(tx[0]);
|
|
1167
|
+
const state = assertEx19(await stateMap.get(hash), () => `[${hash}] state not found`);
|
|
1168
|
+
const submissionHash = assertEx19(state.submissionHash, () => `[${hash}] submissionHash not found`);
|
|
1169
|
+
await job.log(`[${hash}] Checking for XL1 transaction inclusion on chain`);
|
|
1170
|
+
const foundTx = await viewer.transaction.byHash(submissionHash);
|
|
1171
|
+
if (isDefined10(foundTx) && !isNull3(foundTx)) {
|
|
1172
|
+
await job.log(`[${hash}] Found transaction on chain`);
|
|
1173
|
+
const submissionHash2 = await PayloadBuilder12.hash(foundTx[0]);
|
|
1174
|
+
return { submissionHash: submissionHash2 };
|
|
1175
|
+
}
|
|
1176
|
+
const currentBlockNumber = await viewer.currentBlockNumber();
|
|
1177
|
+
if (tx[0].exp < currentBlockNumber) {
|
|
1178
|
+
await job.log(
|
|
1179
|
+
`[${hash}] Transaction expired at block ${tx[0].exp}, current block ${currentBlockNumber}`
|
|
1180
|
+
);
|
|
1181
|
+
throw new UnrecoverableError2(`[${hash}] Transaction expired and will never be included`);
|
|
1182
|
+
}
|
|
1183
|
+
await job.log(`[${hash}] Transaction not yet included, retrying later`);
|
|
1184
|
+
throw new Error(`[${hash}] Transaction not yet included`);
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
connection: connection2,
|
|
1188
|
+
telemetry: telemetry2,
|
|
1189
|
+
prefix
|
|
1023
1190
|
}
|
|
1024
|
-
|
|
1025
|
-
throw new Error(`[${hash}] Transaction not yet included`);
|
|
1026
|
-
}, {
|
|
1027
|
-
connection: connection2,
|
|
1028
|
-
telemetry: telemetry2,
|
|
1029
|
-
prefix
|
|
1030
|
-
});
|
|
1191
|
+
);
|
|
1031
1192
|
worker.on("failed", (job, err) => {
|
|
1032
1193
|
console.error(`[${name9}] Job ${job?.id} failed:`, err.message);
|
|
1033
1194
|
});
|
|
1034
1195
|
worker.on("error", (err) => {
|
|
1035
1196
|
console.error(`[${name9}] Worker error:`, err);
|
|
1036
1197
|
});
|
|
1037
|
-
}
|
|
1198
|
+
};
|
|
1038
1199
|
var Xl1TransactionMonitor = {
|
|
1039
1200
|
createWorker: createWorker9,
|
|
1040
1201
|
name: name9,
|
|
@@ -1042,40 +1203,39 @@ var Xl1TransactionMonitor = {
|
|
|
1042
1203
|
};
|
|
1043
1204
|
|
|
1044
1205
|
// src/services/queue/workers/Xl1TransactionPreparation.ts
|
|
1045
|
-
import { assertEx as
|
|
1046
|
-
import { PayloadBuilder as
|
|
1206
|
+
import { assertEx as assertEx20 } from "@xylabs/sdk-js";
|
|
1207
|
+
import { PayloadBuilder as PayloadBuilder13 } from "@xyo-network/sdk-js";
|
|
1047
1208
|
import { Worker as Worker10 } from "bullmq";
|
|
1048
1209
|
var name10 = "Prepare XL1 Transaction";
|
|
1049
1210
|
var queueName10 = "xl1-tx-prepare";
|
|
1050
|
-
var createWorker10 =
|
|
1051
|
-
const stateMap =
|
|
1052
|
-
const worker = new Worker10(
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
preparedTx
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
});
|
|
1211
|
+
var createWorker10 = (connection2, telemetry2, services) => {
|
|
1212
|
+
const stateMap = assertEx20(services?.xl1TxStateMap, () => "xl1TxStateMap service not provided");
|
|
1213
|
+
const worker = new Worker10(
|
|
1214
|
+
queueName10,
|
|
1215
|
+
async (job) => {
|
|
1216
|
+
const { tx, offChainPayloads = [] } = job.data;
|
|
1217
|
+
const hash = await PayloadBuilder13.hash(tx[0]);
|
|
1218
|
+
await job.log(`[${hash}] preparing XL1 transaction`);
|
|
1219
|
+
const preparedTx = tx;
|
|
1220
|
+
await job.log(`[${hash}] storing XL1 preparedTx`);
|
|
1221
|
+
await stateMap.set(hash, { offChainPayloads, preparedTx });
|
|
1222
|
+
await job.log(`[${hash}] stored XL1 preparedTx`);
|
|
1223
|
+
await job.log(`[${hash}] prepared XL1 transaction`);
|
|
1224
|
+
return { preparedTx };
|
|
1225
|
+
},
|
|
1226
|
+
{
|
|
1227
|
+
connection: connection2,
|
|
1228
|
+
telemetry: telemetry2,
|
|
1229
|
+
prefix
|
|
1230
|
+
}
|
|
1231
|
+
);
|
|
1072
1232
|
worker.on("failed", (job, err) => {
|
|
1073
1233
|
console.error(`[${name10}] Job ${job?.id} failed:`, err.message);
|
|
1074
1234
|
});
|
|
1075
1235
|
worker.on("error", (err) => {
|
|
1076
1236
|
console.error(`[${name10}] Worker error:`, err);
|
|
1077
1237
|
});
|
|
1078
|
-
}
|
|
1238
|
+
};
|
|
1079
1239
|
var Xl1TransactionPreparation = {
|
|
1080
1240
|
createWorker: createWorker10,
|
|
1081
1241
|
name: name10,
|
|
@@ -1083,44 +1243,48 @@ var Xl1TransactionPreparation = {
|
|
|
1083
1243
|
};
|
|
1084
1244
|
|
|
1085
1245
|
// src/services/queue/workers/Xl1TransactionSubmission.ts
|
|
1086
|
-
import { assertEx as
|
|
1087
|
-
import { PayloadBuilder as
|
|
1246
|
+
import { assertEx as assertEx21, isDefined as isDefined11 } from "@xylabs/sdk-js";
|
|
1247
|
+
import { PayloadBuilder as PayloadBuilder14 } from "@xyo-network/sdk-js";
|
|
1088
1248
|
import { Worker as Worker11 } from "bullmq";
|
|
1089
1249
|
var name11 = "Submit XL1 Transaction";
|
|
1090
1250
|
var queueName11 = "xl1-tx-submit";
|
|
1091
|
-
var createWorker11 =
|
|
1092
|
-
const gateway =
|
|
1093
|
-
const stateMap =
|
|
1094
|
-
const worker = new Worker11(
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1251
|
+
var createWorker11 = (connection2, telemetry2, services) => {
|
|
1252
|
+
const gateway = assertEx21(services?.gateway, () => "gateway service not provided");
|
|
1253
|
+
const stateMap = assertEx21(services?.xl1TxStateMap, () => "xl1TxStateMap service not provided");
|
|
1254
|
+
const worker = new Worker11(
|
|
1255
|
+
queueName11,
|
|
1256
|
+
async (job) => {
|
|
1257
|
+
const { tx } = job.data;
|
|
1258
|
+
const hash = await PayloadBuilder14.hash(tx[0]);
|
|
1259
|
+
const state = assertEx21(await stateMap.get(hash), () => `[${hash}] state not found`);
|
|
1260
|
+
const {
|
|
1261
|
+
preparedTx,
|
|
1262
|
+
offChainPayloads = [],
|
|
1102
1263
|
submissionHash: existingSubmissionHash
|
|
1103
|
-
};
|
|
1264
|
+
} = state;
|
|
1265
|
+
if (isDefined11(existingSubmissionHash)) {
|
|
1266
|
+
await job.log(`[${hash}] Tx already submitted with submission response hash ${existingSubmissionHash}`);
|
|
1267
|
+
return { submissionHash: existingSubmissionHash };
|
|
1268
|
+
}
|
|
1269
|
+
const txToSubmit = assertEx21(preparedTx, () => `[${hash}] preparedTx not found`);
|
|
1270
|
+
await job.log(`[${hash}] Submitting XL1 tx`);
|
|
1271
|
+
const [submissionHash] = await submitXl1Transaction(txToSubmit, offChainPayloads, gateway);
|
|
1272
|
+
await job.log(`[${hash}] Submitted XL1 tx`);
|
|
1273
|
+
return { submissionHash };
|
|
1274
|
+
},
|
|
1275
|
+
{
|
|
1276
|
+
connection: connection2,
|
|
1277
|
+
telemetry: telemetry2,
|
|
1278
|
+
prefix
|
|
1104
1279
|
}
|
|
1105
|
-
|
|
1106
|
-
await job.log(`[${hash}] Submitting XL1 tx`);
|
|
1107
|
-
const [submissionHash] = await submitXl1Transaction(txToSubmit, offChainPayloads, gateway);
|
|
1108
|
-
await job.log(`[${hash}] Submitted XL1 tx`);
|
|
1109
|
-
return {
|
|
1110
|
-
submissionHash
|
|
1111
|
-
};
|
|
1112
|
-
}, {
|
|
1113
|
-
connection: connection2,
|
|
1114
|
-
telemetry: telemetry2,
|
|
1115
|
-
prefix
|
|
1116
|
-
});
|
|
1280
|
+
);
|
|
1117
1281
|
worker.on("failed", (job, err) => {
|
|
1118
1282
|
console.error(`[${name11}] Job ${job?.id} failed:`, err.message);
|
|
1119
1283
|
});
|
|
1120
1284
|
worker.on("error", (err) => {
|
|
1121
1285
|
console.error(`[${name11}] Worker error:`, err);
|
|
1122
1286
|
});
|
|
1123
|
-
}
|
|
1287
|
+
};
|
|
1124
1288
|
var Xl1TransactionSubmission = {
|
|
1125
1289
|
createWorker: createWorker11,
|
|
1126
1290
|
name: name11,
|
|
@@ -1128,48 +1292,48 @@ var Xl1TransactionSubmission = {
|
|
|
1128
1292
|
};
|
|
1129
1293
|
|
|
1130
1294
|
// src/services/queue/workers/Xl1TransactionSubmissionStorage.ts
|
|
1131
|
-
import { assertEx as
|
|
1132
|
-
import { PayloadBuilder as
|
|
1295
|
+
import { assertEx as assertEx22, isDefined as isDefined12 } from "@xylabs/sdk-js";
|
|
1296
|
+
import { PayloadBuilder as PayloadBuilder15 } from "@xyo-network/sdk-js";
|
|
1133
1297
|
import { Worker as Worker12 } from "bullmq";
|
|
1134
1298
|
var name12 = "Store XL1 Transaction Submission";
|
|
1135
1299
|
var queueName12 = "xl1-tx-store-submission";
|
|
1136
|
-
var createWorker12 =
|
|
1137
|
-
const stateMap =
|
|
1138
|
-
const worker = new Worker12(
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
submissionHash
|
|
1147
|
-
|
|
1300
|
+
var createWorker12 = (connection2, telemetry2, services) => {
|
|
1301
|
+
const stateMap = assertEx22(services?.xl1TxStateMap, () => "xl1TxStateMap service not provided");
|
|
1302
|
+
const worker = new Worker12(
|
|
1303
|
+
queueName12,
|
|
1304
|
+
async (job) => {
|
|
1305
|
+
const { tx } = job.data;
|
|
1306
|
+
const hash = await PayloadBuilder15.hash(tx[0]);
|
|
1307
|
+
const state = assertEx22(await stateMap.get(hash), () => `[${hash}] state not found`);
|
|
1308
|
+
const { submissionHash: existingSubmissionHash } = state;
|
|
1309
|
+
if (isDefined12(existingSubmissionHash)) {
|
|
1310
|
+
await job.log(`[${hash}] submissionHash already stored as ${existingSubmissionHash}`);
|
|
1311
|
+
return { submissionHash: existingSubmissionHash };
|
|
1312
|
+
}
|
|
1313
|
+
const childrenValues = await job.getChildrenValues();
|
|
1314
|
+
const jobKey = `${prefix}:${Xl1TransactionSubmission.queueName}:${hash}`;
|
|
1315
|
+
const childValues = childrenValues?.[jobKey];
|
|
1316
|
+
const submissionHash = childValues?.submissionHash;
|
|
1317
|
+
const resolvedSubmissionHash = assertEx22(submissionHash, () => `[${hash}] child submissionHash not found in children values`);
|
|
1318
|
+
await job.log(`[${hash}] Storing XL1 submissionHash`);
|
|
1319
|
+
state.submissionHash = resolvedSubmissionHash;
|
|
1320
|
+
await stateMap.set(hash, state);
|
|
1321
|
+
await job.log(`[${hash}] Stored XL1 submissionHash`);
|
|
1322
|
+
return { submissionHash: resolvedSubmissionHash };
|
|
1323
|
+
},
|
|
1324
|
+
{
|
|
1325
|
+
connection: connection2,
|
|
1326
|
+
telemetry: telemetry2,
|
|
1327
|
+
prefix
|
|
1148
1328
|
}
|
|
1149
|
-
|
|
1150
|
-
const jobKey = `${prefix}:${Xl1TransactionSubmission.queueName}:${hash}`;
|
|
1151
|
-
const childValues = childrenValues?.[jobKey];
|
|
1152
|
-
const submissionHash = childValues?.submissionHash;
|
|
1153
|
-
const resolvedSubmissionHash = assertEx21(submissionHash, () => `[${hash}] child submissionHash not found in children values`);
|
|
1154
|
-
await job.log(`[${hash}] Storing XL1 submissionHash`);
|
|
1155
|
-
state.submissionHash = resolvedSubmissionHash;
|
|
1156
|
-
await stateMap.set(hash, state);
|
|
1157
|
-
await job.log(`[${hash}] Stored XL1 submissionHash`);
|
|
1158
|
-
return {
|
|
1159
|
-
submissionHash: resolvedSubmissionHash
|
|
1160
|
-
};
|
|
1161
|
-
}, {
|
|
1162
|
-
connection: connection2,
|
|
1163
|
-
telemetry: telemetry2,
|
|
1164
|
-
prefix
|
|
1165
|
-
});
|
|
1329
|
+
);
|
|
1166
1330
|
worker.on("failed", (job, err) => {
|
|
1167
1331
|
console.error(`[${name12}] Job ${job?.id} failed:`, err.message);
|
|
1168
1332
|
});
|
|
1169
1333
|
worker.on("error", (err) => {
|
|
1170
1334
|
console.error(`[${name12}] Worker error:`, err);
|
|
1171
1335
|
});
|
|
1172
|
-
}
|
|
1336
|
+
};
|
|
1173
1337
|
var Xl1TransactionSubmissionStorage = {
|
|
1174
1338
|
createWorker: createWorker12,
|
|
1175
1339
|
name: name12,
|
|
@@ -1177,7 +1341,7 @@ var Xl1TransactionSubmissionStorage = {
|
|
|
1177
1341
|
};
|
|
1178
1342
|
|
|
1179
1343
|
// src/services/queue/workers/createWorkers.ts
|
|
1180
|
-
var createWorkers =
|
|
1344
|
+
var createWorkers = (connection2, telemetry2, services) => {
|
|
1181
1345
|
EthEventVerification.createWorker(connection2, telemetry2, services);
|
|
1182
1346
|
EthToXl1BridgeParent.createWorker(connection2, telemetry2);
|
|
1183
1347
|
EthTransactionMonitor.createWorker(connection2, telemetry2, services);
|
|
@@ -1190,13 +1354,12 @@ var createWorkers = /* @__PURE__ */ __name((connection2, telemetry2, services) =
|
|
|
1190
1354
|
Xl1TransactionPreparation.createWorker(connection2, telemetry2, services);
|
|
1191
1355
|
Xl1TransactionSubmission.createWorker(connection2, telemetry2, services);
|
|
1192
1356
|
Xl1TransactionSubmissionStorage.createWorker(connection2, telemetry2, services);
|
|
1193
|
-
}
|
|
1357
|
+
};
|
|
1194
1358
|
|
|
1195
1359
|
// src/services/queue/flows/createEthToXl1BridgeJob/getJobIdForEthToXl1BridgeJob.ts
|
|
1196
1360
|
function getJobIdForEthToXl1BridgeJob(context) {
|
|
1197
|
-
return `evm
|
|
1361
|
+
return `evm-${context.evmChainId.toLowerCase()}-${context.contractAddress.toLowerCase()}-${context.bridgeId.toString()}`;
|
|
1198
1362
|
}
|
|
1199
|
-
__name(getJobIdForEthToXl1BridgeJob, "getJobIdForEthToXl1BridgeJob");
|
|
1200
1363
|
|
|
1201
1364
|
// src/services/queue/flows/createEthToXl1BridgeJob/createEthToXl1BridgeJob.ts
|
|
1202
1365
|
var STAGE_2_RETRY = {
|
|
@@ -1206,10 +1369,8 @@ var STAGE_2_RETRY = {
|
|
|
1206
1369
|
type: "fixed"
|
|
1207
1370
|
}
|
|
1208
1371
|
};
|
|
1209
|
-
var STAGE_1_RETRY = {
|
|
1210
|
-
|
|
1211
|
-
};
|
|
1212
|
-
var createEthToXl1BridgeJob = /* @__PURE__ */ __name(async (flowProducer2, context) => {
|
|
1372
|
+
var STAGE_1_RETRY = { attempts: 1 };
|
|
1373
|
+
var createEthToXl1BridgeJob = async (flowProducer2, context) => {
|
|
1213
1374
|
const jobId = getJobIdForEthToXl1BridgeJob(context);
|
|
1214
1375
|
const identity = jobId;
|
|
1215
1376
|
const stageJobData = {
|
|
@@ -1224,175 +1385,121 @@ var createEthToXl1BridgeJob = /* @__PURE__ */ __name(async (flowProducer2, conte
|
|
|
1224
1385
|
name: EthToXl1BridgeParent.name,
|
|
1225
1386
|
queueName: EthToXl1BridgeParent.queueName,
|
|
1226
1387
|
data: stageJobData,
|
|
1227
|
-
opts: {
|
|
1228
|
-
jobId
|
|
1229
|
-
},
|
|
1388
|
+
opts: { jobId },
|
|
1230
1389
|
children: [
|
|
1231
1390
|
{
|
|
1232
1391
|
name: Xl1ReserveTxFulfillment.name,
|
|
1233
1392
|
queueName: Xl1ReserveTxFulfillment.queueName,
|
|
1234
1393
|
data: stageJobData,
|
|
1235
|
-
opts: {
|
|
1236
|
-
jobId,
|
|
1237
|
-
...STAGE_2_RETRY
|
|
1238
|
-
},
|
|
1394
|
+
opts: { jobId, ...STAGE_2_RETRY },
|
|
1239
1395
|
children: [
|
|
1240
1396
|
{
|
|
1241
1397
|
name: EthEventVerification.name,
|
|
1242
1398
|
queueName: EthEventVerification.queueName,
|
|
1243
1399
|
data: stageJobData,
|
|
1244
|
-
opts: {
|
|
1245
|
-
jobId,
|
|
1246
|
-
...STAGE_1_RETRY
|
|
1247
|
-
}
|
|
1400
|
+
opts: { jobId, ...STAGE_1_RETRY }
|
|
1248
1401
|
}
|
|
1249
1402
|
]
|
|
1250
1403
|
}
|
|
1251
1404
|
]
|
|
1252
1405
|
});
|
|
1253
|
-
}
|
|
1406
|
+
};
|
|
1254
1407
|
|
|
1255
1408
|
// src/services/queue/flows/createXl1ToEthBridgeJob/getJobIdForXl1ToEthBridgeJob.ts
|
|
1256
|
-
import { PayloadBuilder as
|
|
1257
|
-
var getJobIdForXl1ToEthBridgeJob =
|
|
1258
|
-
const jobId = await
|
|
1409
|
+
import { PayloadBuilder as PayloadBuilder16 } from "@xyo-network/sdk-js";
|
|
1410
|
+
var getJobIdForXl1ToEthBridgeJob = async (tx) => {
|
|
1411
|
+
const jobId = await PayloadBuilder16.hash(tx[0]);
|
|
1259
1412
|
return jobId;
|
|
1260
|
-
}
|
|
1413
|
+
};
|
|
1261
1414
|
|
|
1262
1415
|
// src/services/queue/flows/createXl1ToEthBridgeJob/createXl1ToEthBridgeJob.ts
|
|
1263
|
-
var createXl1ToEthBridgeJob =
|
|
1416
|
+
var createXl1ToEthBridgeJob = async (flowProducer2, tx, offChainPayloads = []) => {
|
|
1264
1417
|
const jobId = await getJobIdForXl1ToEthBridgeJob(tx);
|
|
1265
1418
|
const flow = await flowProducer2.add({
|
|
1266
1419
|
// Step 0 (runs first as parent job)
|
|
1267
1420
|
name: Xl1ToEthBridgeParent.name,
|
|
1268
1421
|
queueName: Xl1ToEthBridgeParent.queueName,
|
|
1269
|
-
data: {
|
|
1270
|
-
|
|
1271
|
-
offChainPayloads
|
|
1272
|
-
},
|
|
1273
|
-
opts: {
|
|
1274
|
-
jobId
|
|
1275
|
-
},
|
|
1422
|
+
data: { tx, offChainPayloads },
|
|
1423
|
+
opts: { jobId },
|
|
1276
1424
|
children: [
|
|
1277
1425
|
{
|
|
1278
1426
|
// Step 8
|
|
1279
1427
|
name: EthTransactionMonitor.name,
|
|
1280
1428
|
queueName: EthTransactionMonitor.queueName,
|
|
1281
|
-
data: {
|
|
1282
|
-
tx
|
|
1283
|
-
},
|
|
1429
|
+
data: { tx },
|
|
1284
1430
|
opts: {
|
|
1285
1431
|
jobId,
|
|
1286
1432
|
attempts: 60,
|
|
1287
|
-
backoff: {
|
|
1288
|
-
type: "fixed",
|
|
1289
|
-
delay: 5e3
|
|
1290
|
-
}
|
|
1433
|
+
backoff: { type: "fixed", delay: 5e3 }
|
|
1291
1434
|
},
|
|
1292
1435
|
children: [
|
|
1293
1436
|
{
|
|
1294
1437
|
// Step 7
|
|
1295
1438
|
name: EthTransactionSubmissionStorage.name,
|
|
1296
1439
|
queueName: EthTransactionSubmissionStorage.queueName,
|
|
1297
|
-
data: {
|
|
1298
|
-
tx
|
|
1299
|
-
},
|
|
1440
|
+
data: { tx },
|
|
1300
1441
|
opts: {
|
|
1301
1442
|
jobId,
|
|
1302
1443
|
attempts: 60,
|
|
1303
|
-
backoff: {
|
|
1304
|
-
type: "fixed",
|
|
1305
|
-
delay: 5e3
|
|
1306
|
-
}
|
|
1444
|
+
backoff: { type: "fixed", delay: 5e3 }
|
|
1307
1445
|
},
|
|
1308
1446
|
children: [
|
|
1309
1447
|
{
|
|
1310
1448
|
// Step 6
|
|
1311
1449
|
name: EthTransactionSubmission.name,
|
|
1312
1450
|
queueName: EthTransactionSubmission.queueName,
|
|
1313
|
-
data: {
|
|
1314
|
-
|
|
1315
|
-
offChainPayloads
|
|
1316
|
-
},
|
|
1317
|
-
opts: {
|
|
1318
|
-
jobId
|
|
1319
|
-
},
|
|
1451
|
+
data: { tx, offChainPayloads },
|
|
1452
|
+
opts: { jobId },
|
|
1320
1453
|
children: [
|
|
1321
1454
|
{
|
|
1322
1455
|
// Step 5
|
|
1323
1456
|
name: EthTransactionPreparation.name,
|
|
1324
1457
|
queueName: EthTransactionPreparation.queueName,
|
|
1325
|
-
data: {
|
|
1326
|
-
tx,
|
|
1327
|
-
offChainPayloads
|
|
1328
|
-
},
|
|
1458
|
+
data: { tx, offChainPayloads },
|
|
1329
1459
|
opts: {
|
|
1330
1460
|
jobId,
|
|
1331
1461
|
attempts: 60,
|
|
1332
|
-
backoff: {
|
|
1333
|
-
type: "fixed",
|
|
1334
|
-
delay: 5e3
|
|
1335
|
-
}
|
|
1462
|
+
backoff: { type: "fixed", delay: 5e3 }
|
|
1336
1463
|
},
|
|
1337
1464
|
children: [
|
|
1338
1465
|
{
|
|
1339
1466
|
// Step 4
|
|
1340
1467
|
name: Xl1TransactionMonitor.name,
|
|
1341
1468
|
queueName: Xl1TransactionMonitor.queueName,
|
|
1342
|
-
data: {
|
|
1343
|
-
tx
|
|
1344
|
-
},
|
|
1469
|
+
data: { tx },
|
|
1345
1470
|
opts: {
|
|
1346
1471
|
jobId,
|
|
1347
1472
|
attempts: 60,
|
|
1348
|
-
backoff: {
|
|
1349
|
-
type: "fixed",
|
|
1350
|
-
delay: 5e3
|
|
1351
|
-
}
|
|
1473
|
+
backoff: { type: "fixed", delay: 5e3 }
|
|
1352
1474
|
},
|
|
1353
1475
|
children: [
|
|
1354
1476
|
{
|
|
1355
1477
|
// Step 3
|
|
1356
1478
|
name: Xl1TransactionSubmissionStorage.name,
|
|
1357
1479
|
queueName: Xl1TransactionSubmissionStorage.queueName,
|
|
1358
|
-
data: {
|
|
1359
|
-
tx
|
|
1360
|
-
},
|
|
1480
|
+
data: { tx },
|
|
1361
1481
|
opts: {
|
|
1362
1482
|
jobId,
|
|
1363
1483
|
attempts: 60,
|
|
1364
|
-
backoff: {
|
|
1365
|
-
type: "fixed",
|
|
1366
|
-
delay: 5e3
|
|
1367
|
-
}
|
|
1484
|
+
backoff: { type: "fixed", delay: 5e3 }
|
|
1368
1485
|
},
|
|
1369
1486
|
children: [
|
|
1370
1487
|
{
|
|
1371
1488
|
// Step 2
|
|
1372
1489
|
name: Xl1TransactionSubmission.name,
|
|
1373
1490
|
queueName: Xl1TransactionSubmission.queueName,
|
|
1374
|
-
data: {
|
|
1375
|
-
|
|
1376
|
-
},
|
|
1377
|
-
opts: {
|
|
1378
|
-
jobId
|
|
1379
|
-
},
|
|
1491
|
+
data: { tx },
|
|
1492
|
+
opts: { jobId },
|
|
1380
1493
|
children: [
|
|
1381
1494
|
{
|
|
1382
1495
|
// Step 1 (runs first as deepest child)
|
|
1383
1496
|
name: Xl1TransactionPreparation.name,
|
|
1384
1497
|
queueName: Xl1TransactionPreparation.queueName,
|
|
1385
|
-
data: {
|
|
1386
|
-
tx,
|
|
1387
|
-
offChainPayloads
|
|
1388
|
-
},
|
|
1498
|
+
data: { tx, offChainPayloads },
|
|
1389
1499
|
opts: {
|
|
1390
1500
|
jobId,
|
|
1391
1501
|
attempts: 60,
|
|
1392
|
-
backoff: {
|
|
1393
|
-
type: "fixed",
|
|
1394
|
-
delay: 5e3
|
|
1395
|
-
}
|
|
1502
|
+
backoff: { type: "fixed", delay: 5e3 }
|
|
1396
1503
|
}
|
|
1397
1504
|
}
|
|
1398
1505
|
]
|
|
@@ -1412,44 +1519,41 @@ var createXl1ToEthBridgeJob = /* @__PURE__ */ __name(async (flowProducer2, tx, o
|
|
|
1412
1519
|
]
|
|
1413
1520
|
});
|
|
1414
1521
|
return flow;
|
|
1415
|
-
}
|
|
1522
|
+
};
|
|
1416
1523
|
|
|
1417
1524
|
// src/services/queue/flows/createXl1ToEthBridgeJob/getXl1ToEthBridgeJob.ts
|
|
1418
|
-
var getXl1ToEthBridgeJob =
|
|
1525
|
+
var getXl1ToEthBridgeJob = async (flowProducer2, tx) => {
|
|
1419
1526
|
const id = await getJobIdForXl1ToEthBridgeJob(tx);
|
|
1420
|
-
const flow = await flowProducer2.getFlow({
|
|
1421
|
-
queueName: Xl1ToEthBridgeParent.queueName,
|
|
1422
|
-
id
|
|
1423
|
-
});
|
|
1527
|
+
const flow = await flowProducer2.getFlow({ queueName: Xl1ToEthBridgeParent.queueName, id });
|
|
1424
1528
|
return flow;
|
|
1425
|
-
}
|
|
1529
|
+
};
|
|
1426
1530
|
|
|
1427
1531
|
// src/services/queue/getEthToXl1Queues.ts
|
|
1428
1532
|
import { Queue } from "bullmq";
|
|
1429
1533
|
var ethToXl1Queues;
|
|
1430
|
-
var getEthToXl1Queues =
|
|
1534
|
+
var getEthToXl1Queues = (config) => {
|
|
1431
1535
|
if (ethToXl1Queues) return ethToXl1Queues;
|
|
1432
1536
|
const connection2 = getConnection(config);
|
|
1433
1537
|
ethToXl1Queues = {
|
|
1434
|
-
ethEventVerification: new Queue(EthEventVerification.queueName, {
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
}),
|
|
1438
|
-
ethToXl1BridgeParent: new Queue(EthToXl1BridgeParent.queueName, {
|
|
1439
|
-
connection: connection2,
|
|
1440
|
-
prefix
|
|
1441
|
-
}),
|
|
1442
|
-
xl1ReserveTxFulfillment: new Queue(Xl1ReserveTxFulfillment.queueName, {
|
|
1443
|
-
connection: connection2,
|
|
1444
|
-
prefix
|
|
1445
|
-
})
|
|
1538
|
+
ethEventVerification: new Queue(EthEventVerification.queueName, { connection: connection2, prefix }),
|
|
1539
|
+
ethToXl1BridgeParent: new Queue(EthToXl1BridgeParent.queueName, { connection: connection2, prefix }),
|
|
1540
|
+
xl1ReserveTxFulfillment: new Queue(Xl1ReserveTxFulfillment.queueName, { connection: connection2, prefix })
|
|
1446
1541
|
};
|
|
1447
1542
|
return ethToXl1Queues;
|
|
1448
|
-
}
|
|
1543
|
+
};
|
|
1449
1544
|
|
|
1450
1545
|
// src/services/queue/getXl1ToEthQueueJobs.ts
|
|
1451
|
-
var getStatusQueueJobs =
|
|
1452
|
-
const [
|
|
1546
|
+
var getStatusQueueJobs = async (queues, jobId) => {
|
|
1547
|
+
const [
|
|
1548
|
+
ethTransactionMonitorJob,
|
|
1549
|
+
ethTransactionPreparationJob,
|
|
1550
|
+
ethTransactionSubmissionJob,
|
|
1551
|
+
xl1ToEthBridgeParentJob,
|
|
1552
|
+
xl1TransactionMonitorJob,
|
|
1553
|
+
xl1TransactionPreparationJob,
|
|
1554
|
+
xl1TransactionSubmissionJob,
|
|
1555
|
+
xl1TransactionSubmissionStorageJob
|
|
1556
|
+
] = await Promise.all([
|
|
1453
1557
|
queues.ethTransactionMonitor.getJob(jobId),
|
|
1454
1558
|
queues.ethTransactionPreparation.getJob(jobId),
|
|
1455
1559
|
queues.ethTransactionSubmission.getJob(jobId),
|
|
@@ -1469,54 +1573,36 @@ var getStatusQueueJobs = /* @__PURE__ */ __name(async (queues, jobId) => {
|
|
|
1469
1573
|
xl1TransactionSubmissionStorageJob,
|
|
1470
1574
|
xl1TransactionSubmissionJob
|
|
1471
1575
|
};
|
|
1472
|
-
}
|
|
1576
|
+
};
|
|
1473
1577
|
|
|
1474
1578
|
// src/services/queue/getXl1ToEthQueues.ts
|
|
1475
1579
|
import { Queue as Queue2 } from "bullmq";
|
|
1476
1580
|
var xl1ToEthQueues;
|
|
1477
|
-
var getXl1ToEthQueues =
|
|
1581
|
+
var getXl1ToEthQueues = (config) => {
|
|
1478
1582
|
if (xl1ToEthQueues) return xl1ToEthQueues;
|
|
1479
1583
|
const connection2 = getConnection(config);
|
|
1480
1584
|
xl1ToEthQueues = {
|
|
1481
|
-
ethTransactionMonitor: new Queue2(EthTransactionMonitor.queueName, {
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
}),
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
})
|
|
1489
|
-
ethTransactionSubmission: new Queue2(EthTransactionSubmission.queueName, {
|
|
1490
|
-
connection: connection2,
|
|
1491
|
-
prefix
|
|
1492
|
-
}),
|
|
1493
|
-
xl1ToEthBridgeParent: new Queue2(Xl1ToEthBridgeParent.queueName, {
|
|
1494
|
-
connection: connection2,
|
|
1495
|
-
prefix
|
|
1496
|
-
}),
|
|
1497
|
-
xl1TransactionMonitor: new Queue2(Xl1TransactionMonitor.queueName, {
|
|
1498
|
-
connection: connection2,
|
|
1499
|
-
prefix
|
|
1500
|
-
}),
|
|
1501
|
-
xl1TransactionPreparation: new Queue2(Xl1TransactionPreparation.queueName, {
|
|
1502
|
-
connection: connection2,
|
|
1503
|
-
prefix
|
|
1504
|
-
}),
|
|
1505
|
-
xl1TransactionSubmission: new Queue2(Xl1TransactionSubmission.queueName, {
|
|
1506
|
-
connection: connection2,
|
|
1507
|
-
prefix
|
|
1508
|
-
}),
|
|
1509
|
-
xl1TransactionSubmissionStorage: new Queue2(Xl1TransactionSubmissionStorage.queueName, {
|
|
1510
|
-
connection: connection2,
|
|
1511
|
-
prefix
|
|
1512
|
-
})
|
|
1585
|
+
ethTransactionMonitor: new Queue2(EthTransactionMonitor.queueName, { connection: connection2, prefix }),
|
|
1586
|
+
ethTransactionPreparation: new Queue2(EthTransactionPreparation.queueName, { connection: connection2, prefix }),
|
|
1587
|
+
ethTransactionSubmission: new Queue2(EthTransactionSubmission.queueName, { connection: connection2, prefix }),
|
|
1588
|
+
xl1ToEthBridgeParent: new Queue2(Xl1ToEthBridgeParent.queueName, { connection: connection2, prefix }),
|
|
1589
|
+
xl1TransactionMonitor: new Queue2(Xl1TransactionMonitor.queueName, { connection: connection2, prefix }),
|
|
1590
|
+
xl1TransactionPreparation: new Queue2(Xl1TransactionPreparation.queueName, { connection: connection2, prefix }),
|
|
1591
|
+
xl1TransactionSubmission: new Queue2(Xl1TransactionSubmission.queueName, { connection: connection2, prefix }),
|
|
1592
|
+
xl1TransactionSubmissionStorage: new Queue2(Xl1TransactionSubmissionStorage.queueName, { connection: connection2, prefix })
|
|
1513
1593
|
};
|
|
1514
1594
|
return xl1ToEthQueues;
|
|
1515
|
-
}
|
|
1595
|
+
};
|
|
1516
1596
|
|
|
1517
1597
|
// src/services/queue/scanner/createEnqueueEthToXl1Bridge.ts
|
|
1518
1598
|
function createEnqueueEthToXl1Bridge(options2) {
|
|
1519
|
-
const {
|
|
1599
|
+
const {
|
|
1600
|
+
evmChainId,
|
|
1601
|
+
evmContractAddress,
|
|
1602
|
+
flowProducer: flowProducer2,
|
|
1603
|
+
xl1ChainId,
|
|
1604
|
+
xl1TokenAddress
|
|
1605
|
+
} = options2;
|
|
1520
1606
|
return async (bridgeId, jobLog) => {
|
|
1521
1607
|
await createEthToXl1BridgeJob(flowProducer2, {
|
|
1522
1608
|
bridgeId,
|
|
@@ -1528,7 +1614,6 @@ function createEnqueueEthToXl1Bridge(options2) {
|
|
|
1528
1614
|
await jobLog?.(`[bridge-scanner] bridgeId ${bridgeId} enqueued`);
|
|
1529
1615
|
};
|
|
1530
1616
|
}
|
|
1531
|
-
__name(createEnqueueEthToXl1Bridge, "createEnqueueEthToXl1Bridge");
|
|
1532
1617
|
|
|
1533
1618
|
// src/services/queue/scanner/EvmBridgeScanner.ts
|
|
1534
1619
|
import { isUndefined as isUndefined2 } from "@xylabs/sdk-js";
|
|
@@ -1537,19 +1622,24 @@ import { isUndefined as isUndefined2 } from "@xylabs/sdk-js";
|
|
|
1537
1622
|
function getEvmBridgeCursorKey(chainId, contractAddress) {
|
|
1538
1623
|
return `${chainId.toLowerCase()}:${contractAddress.toLowerCase()}`;
|
|
1539
1624
|
}
|
|
1540
|
-
__name(getEvmBridgeCursorKey, "getEvmBridgeCursorKey");
|
|
1541
1625
|
|
|
1542
1626
|
// src/services/queue/scanner/EvmBridgeScanner.ts
|
|
1543
1627
|
function createEvmBridgeScanner(options2) {
|
|
1544
|
-
const {
|
|
1628
|
+
const {
|
|
1629
|
+
bridge,
|
|
1630
|
+
bridgeAddress,
|
|
1631
|
+
chainId,
|
|
1632
|
+
confirmationDepth,
|
|
1633
|
+
cursors,
|
|
1634
|
+
enqueue,
|
|
1635
|
+
provider
|
|
1636
|
+
} = options2;
|
|
1545
1637
|
const cursorKey = getEvmBridgeCursorKey(chainId, bridgeAddress);
|
|
1546
1638
|
return {
|
|
1547
1639
|
async scan(options3) {
|
|
1548
1640
|
const jobLog = options3?.jobLog;
|
|
1549
1641
|
const blockTag = await resolveEvmBlockTagAtDepth(provider, confirmationDepth);
|
|
1550
|
-
const confirmedHigh = await bridge.nextBridgeToId({
|
|
1551
|
-
blockTag
|
|
1552
|
-
});
|
|
1642
|
+
const confirmedHigh = await bridge.nextBridgeToId({ blockTag });
|
|
1553
1643
|
const cursor = await cursors.get(cursorKey);
|
|
1554
1644
|
const lastProcessedId = isUndefined2(cursor) ? 0n : BigInt(cursor.lastProcessedId);
|
|
1555
1645
|
if (confirmedHigh <= lastProcessedId) {
|
|
@@ -1564,9 +1654,7 @@ function createEvmBridgeScanner(options2) {
|
|
|
1564
1654
|
await enqueue(id, jobLog);
|
|
1565
1655
|
enqueued++;
|
|
1566
1656
|
}
|
|
1567
|
-
await cursors.set(cursorKey, {
|
|
1568
|
-
lastProcessedId: confirmedHigh.toString()
|
|
1569
|
-
});
|
|
1657
|
+
await cursors.set(cursorKey, { lastProcessedId: confirmedHigh.toString() });
|
|
1570
1658
|
return {
|
|
1571
1659
|
confirmedHigh,
|
|
1572
1660
|
enqueued,
|
|
@@ -1575,7 +1663,6 @@ function createEvmBridgeScanner(options2) {
|
|
|
1575
1663
|
}
|
|
1576
1664
|
};
|
|
1577
1665
|
}
|
|
1578
|
-
__name(createEvmBridgeScanner, "createEvmBridgeScanner");
|
|
1579
1666
|
|
|
1580
1667
|
// src/services/queue/scanner/EvmBridgeScannerRunner.ts
|
|
1581
1668
|
import { Queue as Queue3, Worker as Worker13 } from "bullmq";
|
|
@@ -1583,7 +1670,12 @@ var QUEUE_NAME = "eth-to-xl1-scanner";
|
|
|
1583
1670
|
var REPEATABLE_JOB_NAME = "scan";
|
|
1584
1671
|
var REPEATABLE_JOB_ID = "eth-to-xl1-scanner-tick";
|
|
1585
1672
|
function createEvmBridgeScannerRunner(options2) {
|
|
1586
|
-
const {
|
|
1673
|
+
const {
|
|
1674
|
+
connection: connection2,
|
|
1675
|
+
intervalMs,
|
|
1676
|
+
scanner,
|
|
1677
|
+
telemetry: telemetry2
|
|
1678
|
+
} = options2;
|
|
1587
1679
|
const logger = options2.logger ?? console;
|
|
1588
1680
|
let queue;
|
|
1589
1681
|
let worker;
|
|
@@ -1596,10 +1688,10 @@ function createEvmBridgeScannerRunner(options2) {
|
|
|
1596
1688
|
});
|
|
1597
1689
|
worker = new Worker13(QUEUE_NAME, async (job) => {
|
|
1598
1690
|
await job.log("[scanner] tick start");
|
|
1599
|
-
const result = await scanner.scan({
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1691
|
+
const result = await scanner.scan({ jobLog: (msg) => job.log(msg) });
|
|
1692
|
+
await job.log(
|
|
1693
|
+
`[scanner] tick complete: enqueued=${result.enqueued} confirmedHigh=${result.confirmedHigh.toString()} lastProcessedId=${result.lastProcessedId.toString()}`
|
|
1694
|
+
);
|
|
1603
1695
|
}, {
|
|
1604
1696
|
connection: connection2,
|
|
1605
1697
|
prefix,
|
|
@@ -1613,9 +1705,7 @@ function createEvmBridgeScannerRunner(options2) {
|
|
|
1613
1705
|
});
|
|
1614
1706
|
await queue.add(REPEATABLE_JOB_NAME, {}, {
|
|
1615
1707
|
jobId: REPEATABLE_JOB_ID,
|
|
1616
|
-
repeat: {
|
|
1617
|
-
every: intervalMs
|
|
1618
|
-
}
|
|
1708
|
+
repeat: { every: intervalMs }
|
|
1619
1709
|
});
|
|
1620
1710
|
},
|
|
1621
1711
|
async stop() {
|
|
@@ -1626,11 +1716,17 @@ function createEvmBridgeScannerRunner(options2) {
|
|
|
1626
1716
|
}
|
|
1627
1717
|
};
|
|
1628
1718
|
}
|
|
1629
|
-
__name(createEvmBridgeScannerRunner, "createEvmBridgeScannerRunner");
|
|
1630
1719
|
|
|
1631
1720
|
// src/services/queue/scanner/buildEvmBridgeScannerRunner.ts
|
|
1632
1721
|
function buildEvmBridgeScannerRunner(options2) {
|
|
1633
|
-
const {
|
|
1722
|
+
const {
|
|
1723
|
+
config,
|
|
1724
|
+
connection: connection2,
|
|
1725
|
+
flowProducer: flowProducer2,
|
|
1726
|
+
logger,
|
|
1727
|
+
services,
|
|
1728
|
+
telemetry: telemetry2
|
|
1729
|
+
} = options2;
|
|
1634
1730
|
const evmChainId = getRemoteChainId(config);
|
|
1635
1731
|
const evmContractAddress = config.remoteBridgeContractAddress;
|
|
1636
1732
|
const xl1ChainId = getXl1ChainId(config);
|
|
@@ -1660,100 +1756,95 @@ function buildEvmBridgeScannerRunner(options2) {
|
|
|
1660
1756
|
telemetry: telemetry2
|
|
1661
1757
|
});
|
|
1662
1758
|
}
|
|
1663
|
-
__name(buildEvmBridgeScannerRunner, "buildEvmBridgeScannerRunner");
|
|
1664
1759
|
|
|
1665
1760
|
// src/services/queue/telemetry.ts
|
|
1666
1761
|
import { isDefined as isDefined13 } from "@xylabs/sdk-js";
|
|
1667
1762
|
import { BullMQOtel } from "bullmq-otel";
|
|
1668
1763
|
var telemetry;
|
|
1669
|
-
var options = {
|
|
1670
|
-
|
|
1671
|
-
};
|
|
1672
|
-
var getTelemetry = /* @__PURE__ */ __name(() => {
|
|
1764
|
+
var options = { enableMetrics: true };
|
|
1765
|
+
var getTelemetry = () => {
|
|
1673
1766
|
if (isDefined13(telemetry)) return telemetry;
|
|
1674
1767
|
telemetry = new BullMQOtel(options);
|
|
1675
1768
|
return telemetry;
|
|
1676
|
-
}
|
|
1769
|
+
};
|
|
1677
1770
|
|
|
1678
1771
|
// src/server/addFlowProducer.ts
|
|
1679
|
-
var addFlowProducer =
|
|
1772
|
+
var addFlowProducer = (app, config) => {
|
|
1680
1773
|
const connection2 = getConnection(config);
|
|
1681
1774
|
const telemetry2 = getTelemetry();
|
|
1682
1775
|
const flowProducer2 = getFlowProducer(connection2, telemetry2);
|
|
1683
1776
|
app.flowProducer = flowProducer2;
|
|
1684
1777
|
return app;
|
|
1685
|
-
}
|
|
1778
|
+
};
|
|
1686
1779
|
|
|
1687
1780
|
// src/server/instrumentation.ts
|
|
1688
1781
|
import { registerInstrumentations } from "@opentelemetry/instrumentation";
|
|
1689
1782
|
import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
|
|
1690
1783
|
import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
|
|
1691
|
-
var addInstrumentation =
|
|
1692
|
-
const instrumentations = [
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
];
|
|
1696
|
-
registerInstrumentations({
|
|
1697
|
-
instrumentations
|
|
1698
|
-
});
|
|
1699
|
-
}, "addInstrumentation");
|
|
1784
|
+
var addInstrumentation = () => {
|
|
1785
|
+
const instrumentations = [new HttpInstrumentation(), new ExpressInstrumentation()];
|
|
1786
|
+
registerInstrumentations({ instrumentations });
|
|
1787
|
+
};
|
|
1700
1788
|
|
|
1701
1789
|
// src/server/routes/livez/get.ts
|
|
1702
1790
|
import { setRawResponseFormat } from "@xylabs/express";
|
|
1703
1791
|
import { ReasonPhrases } from "http-status-codes";
|
|
1704
1792
|
var message = ReasonPhrases.OK;
|
|
1705
|
-
var handler =
|
|
1793
|
+
var handler = (_req, res) => {
|
|
1706
1794
|
setRawResponseFormat(res);
|
|
1707
|
-
res.status(200).send({
|
|
1708
|
-
|
|
1709
|
-
});
|
|
1710
|
-
}, "handler");
|
|
1795
|
+
res.status(200).send({ message });
|
|
1796
|
+
};
|
|
1711
1797
|
var getLivez = handler;
|
|
1712
1798
|
|
|
1713
1799
|
// src/server/routes/readyz/get.ts
|
|
1714
1800
|
import { setRawResponseFormat as setRawResponseFormat2 } from "@xylabs/express";
|
|
1715
1801
|
import { ReasonPhrases as ReasonPhrases2 } from "http-status-codes";
|
|
1716
1802
|
var message2 = ReasonPhrases2.OK;
|
|
1717
|
-
var handler2 =
|
|
1803
|
+
var handler2 = (_req, res) => {
|
|
1718
1804
|
setRawResponseFormat2(res);
|
|
1719
|
-
res.status(200).send({
|
|
1720
|
-
|
|
1721
|
-
});
|
|
1722
|
-
}, "handler");
|
|
1805
|
+
res.status(200).send({ message: message2 });
|
|
1806
|
+
};
|
|
1723
1807
|
var getReadyz = handler2;
|
|
1724
1808
|
|
|
1725
1809
|
// src/server/routes/startupz/get.ts
|
|
1726
1810
|
import { setRawResponseFormat as setRawResponseFormat3 } from "@xylabs/express";
|
|
1727
1811
|
import { ReasonPhrases as ReasonPhrases3 } from "http-status-codes";
|
|
1728
1812
|
var message3 = ReasonPhrases3.OK;
|
|
1729
|
-
var handler3 =
|
|
1813
|
+
var handler3 = (_req, res) => {
|
|
1730
1814
|
setRawResponseFormat3(res);
|
|
1731
|
-
res.status(200).send({
|
|
1732
|
-
|
|
1733
|
-
});
|
|
1734
|
-
}, "handler");
|
|
1815
|
+
res.status(200).send({ message: message3 });
|
|
1816
|
+
};
|
|
1735
1817
|
var getStartupz = handler3;
|
|
1736
1818
|
|
|
1737
1819
|
// src/server/routes/addProbeRoutes.ts
|
|
1738
|
-
var addProbeRoutes =
|
|
1820
|
+
var addProbeRoutes = (app) => {
|
|
1739
1821
|
app.get("/livez", getLivez);
|
|
1740
1822
|
app.get("/readyz", getReadyz);
|
|
1741
1823
|
app.get("/startupz", getStartupz);
|
|
1742
|
-
}
|
|
1824
|
+
};
|
|
1743
1825
|
|
|
1744
1826
|
// src/server/routes/bridge/routeDefinitions/routes/bridgeConfig.ts
|
|
1745
1827
|
import { requestHandlerValidator } from "@xylabs/express";
|
|
1746
1828
|
import { BridgeSettingsZod } from "@xyo-network/chain-orchestration";
|
|
1747
1829
|
var BridgeConfigResponseZod = BridgeSettingsZod;
|
|
1748
|
-
var validateRequest = requestHandlerValidator({
|
|
1749
|
-
|
|
1750
|
-
});
|
|
1751
|
-
var makeBridgeConfigRoute = /* @__PURE__ */ __name((config) => {
|
|
1830
|
+
var validateRequest = requestHandlerValidator({ response: BridgeConfigResponseZod });
|
|
1831
|
+
var makeBridgeConfigRoute = (config) => {
|
|
1752
1832
|
return {
|
|
1753
1833
|
method: "get",
|
|
1754
1834
|
path: "/bridge/chains/:chainId/config",
|
|
1755
1835
|
handlers: validateRequest(async (_, res) => {
|
|
1756
|
-
const {
|
|
1836
|
+
const {
|
|
1837
|
+
escrowAddress,
|
|
1838
|
+
feeFixed,
|
|
1839
|
+
feeRateBasisPoints,
|
|
1840
|
+
feesAddress,
|
|
1841
|
+
maxBridgeAmount,
|
|
1842
|
+
minBridgeAmount,
|
|
1843
|
+
remoteChainId,
|
|
1844
|
+
remoteTokenAddress,
|
|
1845
|
+
xl1ChainId,
|
|
1846
|
+
xl1TokenAddress
|
|
1847
|
+
} = await getBridgeSettings(config);
|
|
1757
1848
|
const sanitizedConfig = {
|
|
1758
1849
|
escrowAddress,
|
|
1759
1850
|
feeFixed,
|
|
@@ -1769,18 +1860,33 @@ var makeBridgeConfigRoute = /* @__PURE__ */ __name((config) => {
|
|
|
1769
1860
|
res.json(sanitizedConfig);
|
|
1770
1861
|
})
|
|
1771
1862
|
};
|
|
1772
|
-
}
|
|
1863
|
+
};
|
|
1773
1864
|
|
|
1774
|
-
// src/server/routes/bridge/routeDefinitions/routes/
|
|
1865
|
+
// src/server/routes/bridge/routeDefinitions/routes/bridgeFromRemoteEstimate.ts
|
|
1775
1866
|
import { requestHandlerValidator as requestHandlerValidator2 } from "@xylabs/express";
|
|
1776
|
-
import {
|
|
1867
|
+
import {
|
|
1868
|
+
assertEx as assertEx23,
|
|
1869
|
+
hexToBigInt as hexToBigInt12,
|
|
1870
|
+
toAddress as toAddress3
|
|
1871
|
+
} from "@xylabs/sdk-js";
|
|
1777
1872
|
import { PayloadZodStrictOfSchema } from "@xyo-network/sdk-js";
|
|
1778
|
-
import {
|
|
1873
|
+
import {
|
|
1874
|
+
BridgeIntentFieldsZod,
|
|
1875
|
+
BridgeIntentSchema as BridgeIntentSchema4,
|
|
1876
|
+
buildUnsignedTransaction,
|
|
1877
|
+
toXL1BlockNumber,
|
|
1878
|
+
TransactionBoundWitnessZod,
|
|
1879
|
+
TransferZod
|
|
1880
|
+
} from "@xyo-network/xl1-sdk";
|
|
1779
1881
|
import { z } from "zod";
|
|
1780
1882
|
|
|
1781
1883
|
// src/server/routes/bridge/routeDefinitions/pathParams/ChainIdPathParam.ts
|
|
1782
|
-
import {
|
|
1783
|
-
|
|
1884
|
+
import {
|
|
1885
|
+
asHex as asHex3,
|
|
1886
|
+
HexZod,
|
|
1887
|
+
isUndefined as isUndefined3
|
|
1888
|
+
} from "@xylabs/sdk-js";
|
|
1889
|
+
var getRemoteChainIdZod = (config) => {
|
|
1784
1890
|
const remoteChainId = getRemoteChainId(config);
|
|
1785
1891
|
return HexZod.superRefine((val, ctx) => {
|
|
1786
1892
|
const chainId = asHex3(val);
|
|
@@ -1792,72 +1898,145 @@ var getRemoteChainIdZod = /* @__PURE__ */ __name((config) => {
|
|
|
1792
1898
|
ctx.addIssue(`Only ${remoteChainId} is supported`);
|
|
1793
1899
|
}
|
|
1794
1900
|
});
|
|
1795
|
-
}
|
|
1901
|
+
};
|
|
1902
|
+
|
|
1903
|
+
// src/server/routes/bridge/routeDefinitions/routes/bridgeFromRemoteEstimate.ts
|
|
1904
|
+
var BridgeFromRemoteEstimateBodyZod = BridgeIntentFieldsZod.pick({
|
|
1905
|
+
destAddress: true,
|
|
1906
|
+
srcAddress: true,
|
|
1907
|
+
srcAmount: true
|
|
1908
|
+
});
|
|
1909
|
+
var BridgeFromRemoteEstimateResponseZod = z.tuple([
|
|
1910
|
+
TransactionBoundWitnessZod,
|
|
1911
|
+
PayloadZodStrictOfSchema(BridgeIntentSchema4).extend(BridgeIntentFieldsZod.shape),
|
|
1912
|
+
TransferZod
|
|
1913
|
+
]);
|
|
1914
|
+
var makeBridgeFromRemoteEstimateRoute = (config) => {
|
|
1915
|
+
const params = z.object({ chainId: getRemoteChainIdZod(config) });
|
|
1916
|
+
const validateRequest2 = requestHandlerValidator2({
|
|
1917
|
+
params,
|
|
1918
|
+
body: BridgeFromRemoteEstimateBodyZod,
|
|
1919
|
+
response: BridgeFromRemoteEstimateResponseZod
|
|
1920
|
+
});
|
|
1921
|
+
return {
|
|
1922
|
+
method: "post",
|
|
1923
|
+
path: "/bridge/chains/:chainId/bridgeFromRemote/estimate",
|
|
1924
|
+
handlers: validateRequest2(async (req, res) => {
|
|
1925
|
+
const services = req.app.services;
|
|
1926
|
+
const {
|
|
1927
|
+
account,
|
|
1928
|
+
bridge,
|
|
1929
|
+
gateway
|
|
1930
|
+
} = services;
|
|
1931
|
+
const {
|
|
1932
|
+
srcAddress,
|
|
1933
|
+
srcAmount,
|
|
1934
|
+
destAddress
|
|
1935
|
+
} = req.body;
|
|
1936
|
+
const { maxBridgeAmount, minBridgeAmount } = await getBridgeSettings(config);
|
|
1937
|
+
if (hexToBigInt12(srcAmount) < hexToBigInt12(minBridgeAmount) || hexToBigInt12(srcAmount) > hexToBigInt12(maxBridgeAmount)) {
|
|
1938
|
+
res.status(400).send();
|
|
1939
|
+
return;
|
|
1940
|
+
}
|
|
1941
|
+
const fees = calculateBridgeFees(srcAmount, getFeeStructure(config));
|
|
1942
|
+
const feesAmount = hexToBigInt12(fees.feeFixed) + hexToBigInt12(fees.feeVariable);
|
|
1943
|
+
const { feesAddress } = await getTransferAddresses(config);
|
|
1944
|
+
const currentNextId = await bridge.nextBridgeToId({ blockTag: "latest" });
|
|
1945
|
+
const projectedBridgeId = currentNextId + 1n;
|
|
1946
|
+
const xl1ChainId = getXl1ChainId(config);
|
|
1947
|
+
const xl1TokenAddress = getXl1TokenAddress(config);
|
|
1948
|
+
const evmChainId = config.remoteChainId;
|
|
1949
|
+
const evmContractAddress = config.remoteBridgeContractAddress;
|
|
1950
|
+
const evmTokenAddress = getRemoteTokenAddress(config);
|
|
1951
|
+
const viewer = assertEx23(gateway.connection.viewer, () => new Error("Viewer not available on gateway connection"));
|
|
1952
|
+
const currentBlockNumber = await viewer.currentBlockNumber();
|
|
1953
|
+
const nbf = toXL1BlockNumber(currentBlockNumber, true);
|
|
1954
|
+
const exp = toXL1BlockNumber(currentBlockNumber + 1e3, true);
|
|
1955
|
+
const { intent, transfer } = buildEthToXl1BridgePayloads({
|
|
1956
|
+
amount: hexToBigInt12(srcAmount),
|
|
1957
|
+
bridgeAccountAddress: account.address,
|
|
1958
|
+
bridgeId: projectedBridgeId,
|
|
1959
|
+
destAddress: toAddress3(destAddress),
|
|
1960
|
+
evmChainId,
|
|
1961
|
+
evmContractAddress,
|
|
1962
|
+
evmSrcAddress: toAddress3(srcAddress),
|
|
1963
|
+
evmTokenAddress,
|
|
1964
|
+
feesAddress,
|
|
1965
|
+
feesAmount,
|
|
1966
|
+
xl1ChainId,
|
|
1967
|
+
xl1TokenAddress
|
|
1968
|
+
});
|
|
1969
|
+
const [txBw] = await buildUnsignedTransaction(xl1ChainId, [transfer], [intent], nbf, exp, account.address);
|
|
1970
|
+
res.json([txBw, intent, transfer]);
|
|
1971
|
+
})
|
|
1972
|
+
};
|
|
1973
|
+
};
|
|
1796
1974
|
|
|
1797
1975
|
// src/server/routes/bridge/routeDefinitions/routes/bridgeFromRemoteStatus.ts
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1976
|
+
import { requestHandlerValidator as requestHandlerValidator3 } from "@xylabs/express";
|
|
1977
|
+
import {
|
|
1978
|
+
hexToBigInt as hexToBigInt13,
|
|
1979
|
+
isDefined as isDefined14,
|
|
1980
|
+
toHex as toHex7
|
|
1981
|
+
} from "@xylabs/sdk-js";
|
|
1982
|
+
import { PayloadZodStrictOfSchema as PayloadZodStrictOfSchema2 } from "@xyo-network/sdk-js";
|
|
1983
|
+
import {
|
|
1984
|
+
BridgeDestinationObservationFieldsZod,
|
|
1985
|
+
BridgeDestinationObservationSchema,
|
|
1986
|
+
BridgeIntentFieldsZod as BridgeIntentFieldsZod2,
|
|
1987
|
+
BridgeIntentSchema as BridgeIntentSchema5,
|
|
1988
|
+
BridgeSourceObservationFieldsZod,
|
|
1989
|
+
BridgeSourceObservationSchema as BridgeSourceObservationSchema2
|
|
1990
|
+
} from "@xyo-network/xl1-sdk";
|
|
1991
|
+
import { z as z2 } from "zod";
|
|
1992
|
+
var BridgeIntentResponseZod = PayloadZodStrictOfSchema2(BridgeIntentSchema5).extend(BridgeIntentFieldsZod2.shape);
|
|
1993
|
+
var BridgeSourceResponseZod = PayloadZodStrictOfSchema2(BridgeSourceObservationSchema2).extend(BridgeSourceObservationFieldsZod.shape);
|
|
1994
|
+
var BridgeDestinationResponseZod = PayloadZodStrictOfSchema2(BridgeDestinationObservationSchema).extend(BridgeDestinationObservationFieldsZod.shape);
|
|
1995
|
+
var BridgeFromRemoteStatusResponseZod = z2.union([
|
|
1996
|
+
z2.tuple([]),
|
|
1997
|
+
z2.tuple([BridgeIntentResponseZod]),
|
|
1998
|
+
z2.tuple([BridgeIntentResponseZod, BridgeSourceResponseZod]),
|
|
1999
|
+
z2.tuple([BridgeIntentResponseZod, BridgeSourceResponseZod, BridgeDestinationResponseZod])
|
|
1815
2000
|
]);
|
|
1816
2001
|
function buildIntentAndSource(ctx) {
|
|
1817
|
-
const {
|
|
1818
|
-
|
|
2002
|
+
const {
|
|
2003
|
+
canonical,
|
|
2004
|
+
config,
|
|
2005
|
+
nonce
|
|
2006
|
+
} = ctx;
|
|
2007
|
+
const srcAmountHex = toHex7(canonical.amount);
|
|
2008
|
+
const fees = calculateBridgeFees(srcAmountHex, getFeeStructure(config));
|
|
2009
|
+
const feesAmount = hexToBigInt13(fees.feeFixed) + hexToBigInt13(fees.feeVariable);
|
|
2010
|
+
const destAmountHex = toHex7(canonical.amount - feesAmount);
|
|
1819
2011
|
const xl1ChainId = getXl1ChainId(config);
|
|
1820
2012
|
const xl1TokenAddress = getXl1TokenAddress(config);
|
|
1821
2013
|
const evmChainId = config.remoteChainId;
|
|
1822
2014
|
const evmTokenAddress = getRemoteTokenAddress(config);
|
|
1823
|
-
const intentFields =
|
|
2015
|
+
const intentFields = BridgeIntentFieldsZod2.parse({
|
|
1824
2016
|
dest: xl1ChainId,
|
|
1825
2017
|
destAddress: canonical.destAddress,
|
|
1826
|
-
destAmount:
|
|
2018
|
+
destAmount: destAmountHex,
|
|
1827
2019
|
destToken: xl1TokenAddress,
|
|
1828
2020
|
nonce,
|
|
1829
2021
|
src: evmChainId,
|
|
1830
2022
|
srcAddress: canonical.srcAddress,
|
|
1831
|
-
srcAmount:
|
|
2023
|
+
srcAmount: srcAmountHex,
|
|
1832
2024
|
srcToken: evmTokenAddress
|
|
1833
2025
|
});
|
|
1834
|
-
const intent = {
|
|
1835
|
-
schema: BridgeIntentSchema4,
|
|
1836
|
-
...intentFields
|
|
1837
|
-
};
|
|
2026
|
+
const intent = { schema: BridgeIntentSchema5, ...intentFields };
|
|
1838
2027
|
const sourceFields = BridgeSourceObservationFieldsZod.parse({
|
|
1839
2028
|
...intentFields,
|
|
1840
2029
|
srcConfirmation: canonical.evmTxHash
|
|
1841
2030
|
});
|
|
1842
|
-
const source = {
|
|
1843
|
-
|
|
1844
|
-
...sourceFields
|
|
1845
|
-
};
|
|
1846
|
-
return [
|
|
1847
|
-
intent,
|
|
1848
|
-
source
|
|
1849
|
-
];
|
|
2031
|
+
const source = { schema: BridgeSourceObservationSchema2, ...sourceFields };
|
|
2032
|
+
return [intent, source];
|
|
1850
2033
|
}
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
const params = z.object({
|
|
2034
|
+
var makeBridgeFromRemoteStatusRoute = (config) => {
|
|
2035
|
+
const params = z2.object({
|
|
1854
2036
|
chainId: getRemoteChainIdZod(config),
|
|
1855
|
-
nonce:
|
|
1856
|
-
});
|
|
1857
|
-
const validateRequest2 = requestHandlerValidator2({
|
|
1858
|
-
params,
|
|
1859
|
-
response: BridgeFromRemoteStatusResponseZod
|
|
2037
|
+
nonce: z2.string().regex(/^\d+$/, "nonce must be a non-negative integer (the bridge contract's id)")
|
|
1860
2038
|
});
|
|
2039
|
+
const validateRequest2 = requestHandlerValidator3({ params, response: BridgeFromRemoteStatusResponseZod });
|
|
1861
2040
|
return {
|
|
1862
2041
|
method: "get",
|
|
1863
2042
|
path: "/bridge/chains/:chainId/bridgeFromRemote/status/:nonce",
|
|
@@ -1884,44 +2063,43 @@ var makeBridgeFromRemoteStatusRoute = /* @__PURE__ */ __name((config) => {
|
|
|
1884
2063
|
config,
|
|
1885
2064
|
nonce: identity
|
|
1886
2065
|
});
|
|
1887
|
-
if (!state.fulfilled) return res.json([
|
|
1888
|
-
intent,
|
|
1889
|
-
source
|
|
1890
|
-
]);
|
|
2066
|
+
if (!state.fulfilled) return res.json([intent, source]);
|
|
1891
2067
|
const destinationFields = BridgeDestinationObservationFieldsZod.parse({
|
|
1892
2068
|
...intent,
|
|
1893
2069
|
destConfirmation: state.fulfilled.txHash
|
|
1894
2070
|
});
|
|
1895
|
-
const destination = {
|
|
1896
|
-
|
|
1897
|
-
...destinationFields
|
|
1898
|
-
};
|
|
1899
|
-
res.json([
|
|
1900
|
-
intent,
|
|
1901
|
-
source,
|
|
1902
|
-
destination
|
|
1903
|
-
]);
|
|
2071
|
+
const destination = { schema: BridgeDestinationObservationSchema, ...destinationFields };
|
|
2072
|
+
res.json([intent, source, destination]);
|
|
1904
2073
|
})
|
|
1905
2074
|
};
|
|
1906
|
-
}
|
|
2075
|
+
};
|
|
1907
2076
|
|
|
1908
2077
|
// src/server/routes/bridge/routeDefinitions/routes/bridgeToRemote.ts
|
|
1909
|
-
import { requestHandlerValidator as
|
|
2078
|
+
import { requestHandlerValidator as requestHandlerValidator4 } from "@xylabs/express";
|
|
1910
2079
|
import { isDefined as isDefined15 } from "@xylabs/sdk-js";
|
|
1911
|
-
import {
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
2080
|
+
import {
|
|
2081
|
+
PayloadBuilder as PayloadBuilder17,
|
|
2082
|
+
PayloadZodLooseOfSchema,
|
|
2083
|
+
PayloadZodStrictOfSchema as PayloadZodStrictOfSchema3
|
|
2084
|
+
} from "@xyo-network/sdk-js";
|
|
2085
|
+
import {
|
|
2086
|
+
BridgeIntentFieldsZod as BridgeIntentFieldsZod3,
|
|
2087
|
+
BridgeIntentSchema as BridgeIntentSchema6,
|
|
2088
|
+
BridgeSourceObservationFieldsZod as BridgeSourceObservationFieldsZod2,
|
|
2089
|
+
BridgeSourceObservationSchema as BridgeSourceObservationSchema3,
|
|
1915
2090
|
SignedTransactionBoundWitnessZod,
|
|
1916
|
-
|
|
1917
|
-
|
|
2091
|
+
TransferZod as TransferZod2
|
|
2092
|
+
} from "@xyo-network/xl1-sdk";
|
|
2093
|
+
import { z as z3 } from "zod";
|
|
2094
|
+
var BridgeToRemoteBodyZod = z3.tuple([
|
|
2095
|
+
SignedTransactionBoundWitnessZod,
|
|
2096
|
+
PayloadZodLooseOfSchema(BridgeIntentSchema6).extend(BridgeIntentFieldsZod3.shape),
|
|
2097
|
+
TransferZod2
|
|
1918
2098
|
]);
|
|
1919
|
-
var BridgeToRemoteResponseZod =
|
|
1920
|
-
var makeBridgeToRemoteRoute =
|
|
1921
|
-
const params =
|
|
1922
|
-
|
|
1923
|
-
});
|
|
1924
|
-
const validateRequest2 = requestHandlerValidator3({
|
|
2099
|
+
var BridgeToRemoteResponseZod = PayloadZodStrictOfSchema3(BridgeSourceObservationSchema3).extend(BridgeSourceObservationFieldsZod2.shape);
|
|
2100
|
+
var makeBridgeToRemoteRoute = (config) => {
|
|
2101
|
+
const params = z3.object({ chainId: getRemoteChainIdZod(config) });
|
|
2102
|
+
const validateRequest2 = requestHandlerValidator4({
|
|
1925
2103
|
params,
|
|
1926
2104
|
body: BridgeToRemoteBodyZod,
|
|
1927
2105
|
response: BridgeToRemoteResponseZod
|
|
@@ -1948,56 +2126,55 @@ var makeBridgeToRemoteRoute = /* @__PURE__ */ __name((config) => {
|
|
|
1948
2126
|
res.status(400).send();
|
|
1949
2127
|
return;
|
|
1950
2128
|
}
|
|
1951
|
-
const singedHydratedTransaction = [
|
|
1952
|
-
signedTxBw,
|
|
1953
|
-
[
|
|
1954
|
-
transfer
|
|
1955
|
-
]
|
|
1956
|
-
];
|
|
2129
|
+
const singedHydratedTransaction = [signedTxBw, [transfer]];
|
|
1957
2130
|
const existingFlow = await getXl1ToEthBridgeJob(flowProducer2, singedHydratedTransaction);
|
|
1958
2131
|
if (isDefined15(existingFlow)) {
|
|
1959
2132
|
res.status(200).send();
|
|
1960
2133
|
return;
|
|
1961
2134
|
}
|
|
1962
|
-
await createXl1ToEthBridgeJob(flowProducer2, singedHydratedTransaction, [
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
const srcConfirmation = await PayloadBuilder16.hash(signedTxBw);
|
|
1966
|
-
const bridgeCommonFieldsZod = z2.object({}).extend(BridgeSourceObservationFieldsZod2.shape);
|
|
2135
|
+
await createXl1ToEthBridgeJob(flowProducer2, singedHydratedTransaction, [bridgeIntent]);
|
|
2136
|
+
const srcConfirmation = await PayloadBuilder17.hash(signedTxBw);
|
|
2137
|
+
const bridgeCommonFieldsZod = z3.object({}).extend(BridgeSourceObservationFieldsZod2.shape);
|
|
1967
2138
|
const bridgeCommonFields = bridgeCommonFieldsZod.parse(bridgeIntent);
|
|
1968
|
-
const bridgeObservationFields = {
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
const bridgeObservation = new PayloadBuilder16({
|
|
1973
|
-
schema: BridgeSourceObservationSchema3
|
|
1974
|
-
}).fields(bridgeObservationFields).build();
|
|
2139
|
+
const bridgeObservationFields = { ...bridgeCommonFields, srcConfirmation };
|
|
2140
|
+
const bridgeObservation = new PayloadBuilder17(
|
|
2141
|
+
{ schema: BridgeSourceObservationSchema3 }
|
|
2142
|
+
).fields(bridgeObservationFields).build();
|
|
1975
2143
|
res.status(202).json(bridgeObservation);
|
|
1976
2144
|
})
|
|
1977
2145
|
};
|
|
1978
|
-
}
|
|
2146
|
+
};
|
|
1979
2147
|
|
|
1980
2148
|
// src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteEstimate.ts
|
|
1981
|
-
import { requestHandlerValidator as
|
|
1982
|
-
import {
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
2149
|
+
import { requestHandlerValidator as requestHandlerValidator5 } from "@xylabs/express";
|
|
2150
|
+
import {
|
|
2151
|
+
assertEx as assertEx24,
|
|
2152
|
+
hexToBigInt as hexToBigInt14,
|
|
2153
|
+
toAddress as toAddress4
|
|
2154
|
+
} from "@xylabs/sdk-js";
|
|
2155
|
+
import { PayloadZodStrictOfSchema as PayloadZodStrictOfSchema4 } from "@xyo-network/sdk-js";
|
|
2156
|
+
import {
|
|
2157
|
+
BridgeIntentFieldsZod as BridgeIntentFieldsZod4,
|
|
2158
|
+
BridgeIntentSchema as BridgeIntentSchema7,
|
|
2159
|
+
buildUnsignedTransaction as buildUnsignedTransaction2,
|
|
2160
|
+
toXL1BlockNumber as toXL1BlockNumber2,
|
|
2161
|
+
TransactionBoundWitnessZod as TransactionBoundWitnessZod2,
|
|
2162
|
+
TransferZod as TransferZod3
|
|
2163
|
+
} from "@xyo-network/xl1-sdk";
|
|
2164
|
+
import { z as z4 } from "zod";
|
|
2165
|
+
var BridgeToRemoteEstimateBodyZod = BridgeIntentFieldsZod4.pick({
|
|
1987
2166
|
destAddress: true,
|
|
1988
2167
|
srcAddress: true,
|
|
1989
2168
|
srcAmount: true
|
|
1990
2169
|
});
|
|
1991
|
-
var BridgeToRemoteEstimateResponseZod =
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
2170
|
+
var BridgeToRemoteEstimateResponseZod = z4.tuple([
|
|
2171
|
+
TransactionBoundWitnessZod2,
|
|
2172
|
+
PayloadZodStrictOfSchema4(BridgeIntentSchema7).extend(BridgeIntentFieldsZod4.shape),
|
|
2173
|
+
TransferZod3
|
|
1995
2174
|
]);
|
|
1996
|
-
var makeBridgeToRemoteEstimateRoute =
|
|
1997
|
-
const params =
|
|
1998
|
-
|
|
1999
|
-
});
|
|
2000
|
-
const validateRequest2 = requestHandlerValidator4({
|
|
2175
|
+
var makeBridgeToRemoteEstimateRoute = (config, gateway) => {
|
|
2176
|
+
const params = z4.object({ chainId: getRemoteChainIdZod(config) });
|
|
2177
|
+
const validateRequest2 = requestHandlerValidator5({
|
|
2001
2178
|
params,
|
|
2002
2179
|
body: BridgeToRemoteEstimateBodyZod,
|
|
2003
2180
|
response: BridgeToRemoteEstimateResponseZod
|
|
@@ -2007,53 +2184,59 @@ var makeBridgeToRemoteEstimateRoute = /* @__PURE__ */ __name((config, gateway) =
|
|
|
2007
2184
|
path: "/bridge/chains/:chainId/bridgeToRemote/estimate",
|
|
2008
2185
|
handlers: validateRequest2(async (req, res) => {
|
|
2009
2186
|
const xl1ChainId = getXl1ChainId(config);
|
|
2010
|
-
const {
|
|
2187
|
+
const {
|
|
2188
|
+
srcAddress,
|
|
2189
|
+
srcAmount,
|
|
2190
|
+
destAddress
|
|
2191
|
+
} = req.body;
|
|
2011
2192
|
const { maxBridgeAmount, minBridgeAmount } = await getBridgeSettings(config);
|
|
2012
|
-
if (
|
|
2193
|
+
if (hexToBigInt14(srcAmount) < hexToBigInt14(minBridgeAmount) || hexToBigInt14(srcAmount) > hexToBigInt14(maxBridgeAmount)) {
|
|
2013
2194
|
res.status(400).send();
|
|
2014
2195
|
return;
|
|
2015
2196
|
}
|
|
2016
2197
|
const [bridgeIntent, transfer] = await generateBridgeEstimate(srcAddress, srcAmount, destAddress, config);
|
|
2017
|
-
const sender =
|
|
2018
|
-
const viewer =
|
|
2198
|
+
const sender = toAddress4(srcAddress);
|
|
2199
|
+
const viewer = assertEx24(gateway.connection.viewer, () => new Error("Viewer not available on gateway connection"));
|
|
2019
2200
|
const currentBlockNumber = await viewer.currentBlockNumber();
|
|
2020
|
-
const nbf =
|
|
2021
|
-
const exp =
|
|
2022
|
-
const [txBw] = await
|
|
2023
|
-
|
|
2024
|
-
], [
|
|
2025
|
-
bridgeIntent
|
|
2026
|
-
], nbf, exp, sender);
|
|
2027
|
-
res.json([
|
|
2028
|
-
txBw,
|
|
2029
|
-
bridgeIntent,
|
|
2030
|
-
transfer
|
|
2031
|
-
]);
|
|
2201
|
+
const nbf = toXL1BlockNumber2(currentBlockNumber, true);
|
|
2202
|
+
const exp = toXL1BlockNumber2(currentBlockNumber + 1e3, true);
|
|
2203
|
+
const [txBw] = await buildUnsignedTransaction2(xl1ChainId, [transfer], [bridgeIntent], nbf, exp, sender);
|
|
2204
|
+
res.json([txBw, bridgeIntent, transfer]);
|
|
2032
2205
|
})
|
|
2033
2206
|
};
|
|
2034
|
-
}
|
|
2207
|
+
};
|
|
2035
2208
|
|
|
2036
2209
|
// src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteMaxEstimate.ts
|
|
2037
|
-
import { requestHandlerValidator as
|
|
2038
|
-
import {
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2210
|
+
import { requestHandlerValidator as requestHandlerValidator6 } from "@xylabs/express";
|
|
2211
|
+
import {
|
|
2212
|
+
assertEx as assertEx25,
|
|
2213
|
+
hexToBigInt as hexToBigInt15,
|
|
2214
|
+
toAddress as toAddress5,
|
|
2215
|
+
toHex as toHex8
|
|
2216
|
+
} from "@xylabs/sdk-js";
|
|
2217
|
+
import { PayloadZodStrictOfSchema as PayloadZodStrictOfSchema5 } from "@xyo-network/sdk-js";
|
|
2218
|
+
import {
|
|
2219
|
+
BridgeIntentFieldsZod as BridgeIntentFieldsZod5,
|
|
2220
|
+
BridgeIntentSchema as BridgeIntentSchema8,
|
|
2221
|
+
buildUnsignedTransaction as buildUnsignedTransaction3,
|
|
2222
|
+
toXL1BlockNumber as toXL1BlockNumber3,
|
|
2223
|
+
TransactionBoundWitnessZod as TransactionBoundWitnessZod3,
|
|
2224
|
+
TransferZod as TransferZod4
|
|
2225
|
+
} from "@xyo-network/xl1-sdk";
|
|
2226
|
+
import { z as z5 } from "zod";
|
|
2227
|
+
var BridgeToRemoteMaxEstimateBodyZod = BridgeIntentFieldsZod5.pick({
|
|
2043
2228
|
destAddress: true,
|
|
2044
2229
|
srcAddress: true,
|
|
2045
2230
|
srcAmount: true
|
|
2046
2231
|
});
|
|
2047
|
-
var BridgeToRemoteMaxEstimateResponseZod =
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2232
|
+
var BridgeToRemoteMaxEstimateResponseZod = z5.tuple([
|
|
2233
|
+
TransactionBoundWitnessZod3,
|
|
2234
|
+
PayloadZodStrictOfSchema5(BridgeIntentSchema8).extend(BridgeIntentFieldsZod5.shape),
|
|
2235
|
+
TransferZod4
|
|
2051
2236
|
]);
|
|
2052
|
-
var makeBridgeToRemoteMaxEstimateRoute =
|
|
2053
|
-
const params =
|
|
2054
|
-
|
|
2055
|
-
});
|
|
2056
|
-
const validateRequest2 = requestHandlerValidator5({
|
|
2237
|
+
var makeBridgeToRemoteMaxEstimateRoute = (config, gateway) => {
|
|
2238
|
+
const params = z5.object({ chainId: getRemoteChainIdZod(config) });
|
|
2239
|
+
const validateRequest2 = requestHandlerValidator6({
|
|
2057
2240
|
params,
|
|
2058
2241
|
body: BridgeToRemoteMaxEstimateBodyZod,
|
|
2059
2242
|
response: BridgeToRemoteMaxEstimateResponseZod
|
|
@@ -2062,66 +2245,61 @@ var makeBridgeToRemoteMaxEstimateRoute = /* @__PURE__ */ __name((config, gateway
|
|
|
2062
2245
|
method: "post",
|
|
2063
2246
|
path: "/bridge/chains/:chainId/bridgeToRemote/maxEstimate",
|
|
2064
2247
|
handlers: validateRequest2(async (req, res) => {
|
|
2065
|
-
const {
|
|
2066
|
-
const { srcAddress, srcAmount: balance, destAddress } = req.body;
|
|
2067
|
-
const balanceMax = calculateMaxBridgeAmount(balance, {
|
|
2248
|
+
const {
|
|
2068
2249
|
feeFixed,
|
|
2069
|
-
feeRateBasisPoints
|
|
2070
|
-
|
|
2071
|
-
|
|
2250
|
+
feeRateBasisPoints,
|
|
2251
|
+
maxBridgeAmount: configMax,
|
|
2252
|
+
xl1ChainId
|
|
2253
|
+
} = await getBridgeSettings(config);
|
|
2254
|
+
const {
|
|
2255
|
+
srcAddress,
|
|
2256
|
+
srcAmount: balance,
|
|
2257
|
+
destAddress
|
|
2258
|
+
} = req.body;
|
|
2259
|
+
const balanceMax = calculateMaxBridgeAmount(balance, { feeFixed, feeRateBasisPoints });
|
|
2260
|
+
const maxBridgeAmount = toHex8(hexToBigInt15(balanceMax) < hexToBigInt15(configMax) ? balanceMax : configMax);
|
|
2072
2261
|
const [bridgeIntent, transfer] = await generateBridgeEstimate(srcAddress, maxBridgeAmount, destAddress, config);
|
|
2073
|
-
const sender =
|
|
2074
|
-
const viewer =
|
|
2262
|
+
const sender = toAddress5(srcAddress);
|
|
2263
|
+
const viewer = assertEx25(gateway.connection.viewer, () => new Error("Viewer not available on gateway connection"));
|
|
2075
2264
|
const currentBlockNumber = await viewer.currentBlockNumber();
|
|
2076
|
-
const nbf =
|
|
2077
|
-
const exp =
|
|
2078
|
-
const [txBw] = await
|
|
2079
|
-
|
|
2080
|
-
], [
|
|
2081
|
-
bridgeIntent
|
|
2082
|
-
], nbf, exp, sender);
|
|
2083
|
-
res.json([
|
|
2084
|
-
txBw,
|
|
2085
|
-
bridgeIntent,
|
|
2086
|
-
transfer
|
|
2087
|
-
]);
|
|
2265
|
+
const nbf = toXL1BlockNumber3(currentBlockNumber, true);
|
|
2266
|
+
const exp = toXL1BlockNumber3(currentBlockNumber + 1e3, true);
|
|
2267
|
+
const [txBw] = await buildUnsignedTransaction3(xl1ChainId, [transfer], [bridgeIntent], nbf, exp, sender);
|
|
2268
|
+
res.json([txBw, bridgeIntent, transfer]);
|
|
2088
2269
|
})
|
|
2089
2270
|
};
|
|
2090
|
-
}
|
|
2271
|
+
};
|
|
2091
2272
|
|
|
2092
2273
|
// src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteStatus.ts
|
|
2093
|
-
import { requestHandlerValidator as
|
|
2274
|
+
import { requestHandlerValidator as requestHandlerValidator7 } from "@xylabs/express";
|
|
2094
2275
|
import { asHex as asHex4, isDefined as isDefined16 } from "@xylabs/sdk-js";
|
|
2095
|
-
import { PayloadBuilder as
|
|
2096
|
-
import {
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
])
|
|
2276
|
+
import { PayloadBuilder as PayloadBuilder18, PayloadZodStrictOfSchema as PayloadZodStrictOfSchema6 } from "@xyo-network/sdk-js";
|
|
2277
|
+
import {
|
|
2278
|
+
asBridgeIntent,
|
|
2279
|
+
BridgeDestinationObservationFieldsZod as BridgeDestinationObservationFieldsZod2,
|
|
2280
|
+
BridgeDestinationObservationSchema as BridgeDestinationObservationSchema2,
|
|
2281
|
+
BridgeIntentFieldsZod as BridgeIntentFieldsZod6,
|
|
2282
|
+
BridgeIntentSchema as BridgeIntentSchema9,
|
|
2283
|
+
BridgeSourceObservationFieldsZod as BridgeSourceObservationFieldsZod3,
|
|
2284
|
+
BridgeSourceObservationSchema as BridgeSourceObservationSchema4,
|
|
2285
|
+
isBridgeIntent as isBridgeIntent5
|
|
2286
|
+
} from "@xyo-network/xl1-sdk";
|
|
2287
|
+
import { z as z6 } from "zod";
|
|
2288
|
+
var BridgeIntentResponseZod2 = PayloadZodStrictOfSchema6(BridgeIntentSchema9).extend(BridgeIntentFieldsZod6.shape);
|
|
2289
|
+
var BridgeSourceResponseZod2 = PayloadZodStrictOfSchema6(BridgeSourceObservationSchema4).extend(BridgeSourceObservationFieldsZod3.shape);
|
|
2290
|
+
var BridgeDestinationResponseZod2 = PayloadZodStrictOfSchema6(BridgeDestinationObservationSchema2).extend(BridgeDestinationObservationFieldsZod2.shape);
|
|
2291
|
+
var BridgeToRemoteStatusResponseZod = z6.union([
|
|
2292
|
+
z6.tuple([]),
|
|
2293
|
+
z6.tuple([BridgeIntentResponseZod2]),
|
|
2294
|
+
z6.tuple([BridgeIntentResponseZod2, BridgeSourceResponseZod2]),
|
|
2295
|
+
z6.tuple([BridgeIntentResponseZod2, BridgeSourceResponseZod2, BridgeDestinationResponseZod2])
|
|
2115
2296
|
]);
|
|
2116
|
-
var makeBridgeToRemoteStatusRoute =
|
|
2117
|
-
const params =
|
|
2297
|
+
var makeBridgeToRemoteStatusRoute = (config) => {
|
|
2298
|
+
const params = z6.object({
|
|
2118
2299
|
chainId: getRemoteChainIdZod(config),
|
|
2119
|
-
nonce:
|
|
2120
|
-
});
|
|
2121
|
-
const validateRequest2 = requestHandlerValidator6({
|
|
2122
|
-
params,
|
|
2123
|
-
response: BridgeToRemoteStatusResponseZod
|
|
2300
|
+
nonce: z6.string().nonempty()
|
|
2124
2301
|
});
|
|
2302
|
+
const validateRequest2 = requestHandlerValidator7({ params, response: BridgeToRemoteStatusResponseZod });
|
|
2125
2303
|
return {
|
|
2126
2304
|
method: "get",
|
|
2127
2305
|
path: "/bridge/chains/:chainId/bridgeToRemote/status/:nonce",
|
|
@@ -2132,13 +2310,10 @@ var makeBridgeToRemoteStatusRoute = /* @__PURE__ */ __name((config) => {
|
|
|
2132
2310
|
const statusQueueJobs = await getStatusQueueJobs(queues, jobId);
|
|
2133
2311
|
const { tx, offChainPayloads = [] } = statusQueueJobs.xl1ToEthBridgeParentJob?.data ?? {};
|
|
2134
2312
|
if (!tx) return res.sendStatus(404);
|
|
2135
|
-
const allPayloads = [
|
|
2136
|
-
...tx[1],
|
|
2137
|
-
...offChainPayloads
|
|
2138
|
-
];
|
|
2313
|
+
const allPayloads = [...tx[1], ...offChainPayloads];
|
|
2139
2314
|
const bridgeIntent = allPayloads.find(isBridgeIntent5);
|
|
2140
2315
|
if (!bridgeIntent) return res.sendStatus(404);
|
|
2141
|
-
result[0] = asBridgeIntent(
|
|
2316
|
+
result[0] = asBridgeIntent(PayloadBuilder18.omitMeta(bridgeIntent));
|
|
2142
2317
|
const { xl1TransactionMonitorJob } = statusQueueJobs;
|
|
2143
2318
|
const xl1MonitorState = xl1TransactionMonitorJob ? await xl1TransactionMonitorJob.getState() : void 0;
|
|
2144
2319
|
if (xl1MonitorState === "completed") {
|
|
@@ -2172,36 +2347,37 @@ var makeBridgeToRemoteStatusRoute = /* @__PURE__ */ __name((config) => {
|
|
|
2172
2347
|
res.json(result);
|
|
2173
2348
|
})
|
|
2174
2349
|
};
|
|
2175
|
-
}
|
|
2350
|
+
};
|
|
2176
2351
|
|
|
2177
2352
|
// src/server/routes/bridge/routeDefinitions/getRouteDefinitions.ts
|
|
2178
|
-
var getRouteDefinitions =
|
|
2353
|
+
var getRouteDefinitions = (config, gateway) => {
|
|
2179
2354
|
return [
|
|
2180
2355
|
makeBridgeConfigRoute(config),
|
|
2181
2356
|
makeBridgeToRemoteEstimateRoute(config, gateway),
|
|
2182
2357
|
makeBridgeToRemoteMaxEstimateRoute(config, gateway),
|
|
2183
2358
|
makeBridgeToRemoteRoute(config),
|
|
2184
2359
|
makeBridgeToRemoteStatusRoute(config),
|
|
2360
|
+
makeBridgeFromRemoteEstimateRoute(config),
|
|
2185
2361
|
makeBridgeFromRemoteStatusRoute(config)
|
|
2186
2362
|
];
|
|
2187
|
-
}
|
|
2363
|
+
};
|
|
2188
2364
|
|
|
2189
2365
|
// src/server/routes/bridge/addBridgeRoutes.ts
|
|
2190
|
-
var addBridgeRoutes =
|
|
2366
|
+
var addBridgeRoutes = (app, config, gateway) => {
|
|
2191
2367
|
const routeDefinitions = getRouteDefinitions(config, gateway);
|
|
2192
2368
|
for (const definition of routeDefinitions) {
|
|
2193
2369
|
app[definition.method](definition.path, definition.handlers);
|
|
2194
2370
|
}
|
|
2195
|
-
}
|
|
2371
|
+
};
|
|
2196
2372
|
|
|
2197
2373
|
// src/server/routes/addRoutes.ts
|
|
2198
|
-
var addRoutes =
|
|
2374
|
+
var addRoutes = (app, config, gateway) => {
|
|
2199
2375
|
addProbeRoutes(app);
|
|
2200
2376
|
addBridgeRoutes(app, config, gateway);
|
|
2201
|
-
}
|
|
2377
|
+
};
|
|
2202
2378
|
|
|
2203
2379
|
// src/server/app.ts
|
|
2204
|
-
var getApp =
|
|
2380
|
+
var getApp = (config, gateway) => {
|
|
2205
2381
|
addInstrumentation();
|
|
2206
2382
|
const app = express();
|
|
2207
2383
|
sharedMiddleware(app);
|
|
@@ -2209,10 +2385,10 @@ var getApp = /* @__PURE__ */ __name((config, gateway) => {
|
|
|
2209
2385
|
addRoutes(app, config, gateway);
|
|
2210
2386
|
app.use(standardErrors);
|
|
2211
2387
|
return app;
|
|
2212
|
-
}
|
|
2388
|
+
};
|
|
2213
2389
|
|
|
2214
2390
|
// src/services/getServices.ts
|
|
2215
|
-
import { assertEx as
|
|
2391
|
+
import { assertEx as assertEx26 } from "@xylabs/sdk-js";
|
|
2216
2392
|
import { initEvmProvider, resolveWalletForActor as resolveWalletForActor2 } from "@xyo-network/chain-orchestration";
|
|
2217
2393
|
import { BridgeableToken__factory, LiquidityPoolBridge__factory } from "@xyo-network/typechain";
|
|
2218
2394
|
import { getAddress as getAddress2, Wallet } from "ethers";
|
|
@@ -2221,10 +2397,16 @@ import { getAddress as getAddress2, Wallet } from "ethers";
|
|
|
2221
2397
|
import { BaseMongoSdk } from "@xylabs/mongo";
|
|
2222
2398
|
import { MongoMap } from "@xyo-network/chain-protocol-driver-mongodb";
|
|
2223
2399
|
import { hasMongoConfig, mapToMapType } from "@xyo-network/xl1-sdk";
|
|
2224
|
-
var getIterableMap =
|
|
2400
|
+
var getIterableMap = async (config, collection) => {
|
|
2225
2401
|
const mongoConfig = config.storage?.mongo;
|
|
2226
2402
|
if (hasMongoConfig(mongoConfig)) {
|
|
2227
|
-
const {
|
|
2403
|
+
const {
|
|
2404
|
+
connectionString: dbConnectionString,
|
|
2405
|
+
database: dbName,
|
|
2406
|
+
domain: dbDomain,
|
|
2407
|
+
password: dbPassword,
|
|
2408
|
+
username: dbUserName
|
|
2409
|
+
} = mongoConfig;
|
|
2228
2410
|
const payloadSdkConfig = {
|
|
2229
2411
|
dbConnectionString,
|
|
2230
2412
|
dbDomain,
|
|
@@ -2232,44 +2414,44 @@ var getIterableMap = /* @__PURE__ */ __name(async (config, collection) => {
|
|
|
2232
2414
|
dbPassword,
|
|
2233
2415
|
dbUserName
|
|
2234
2416
|
};
|
|
2235
|
-
const sdkBalanceSummaryMap = new BaseMongoSdk({
|
|
2236
|
-
...payloadSdkConfig,
|
|
2237
|
-
collection
|
|
2238
|
-
});
|
|
2417
|
+
const sdkBalanceSummaryMap = new BaseMongoSdk({ ...payloadSdkConfig, collection });
|
|
2239
2418
|
const result = await MongoMap.create({
|
|
2240
2419
|
sdk: sdkBalanceSummaryMap,
|
|
2241
|
-
getCache: {
|
|
2242
|
-
enabled: true,
|
|
2243
|
-
maxEntries: 5e3
|
|
2244
|
-
}
|
|
2420
|
+
getCache: { enabled: true, maxEntries: 5e3 }
|
|
2245
2421
|
});
|
|
2246
2422
|
return result;
|
|
2247
2423
|
} else {
|
|
2248
2424
|
return mapToMapType(/* @__PURE__ */ new Map());
|
|
2249
2425
|
}
|
|
2250
|
-
}
|
|
2426
|
+
};
|
|
2251
2427
|
|
|
2252
2428
|
// src/services/getServices.ts
|
|
2253
|
-
var getServices =
|
|
2429
|
+
var getServices = async (context, gateway) => {
|
|
2254
2430
|
const { config } = context;
|
|
2255
2431
|
const ethTxStateMap = await getIterableMap(config, "liquidity_bridge_xl1_to_eth_eth_tx_state");
|
|
2256
2432
|
const xl1TxStateMap = await getIterableMap(config, "liquidity_bridge_xl1_to_eth_xl1_tx_state");
|
|
2257
2433
|
const evmBridgeCursorMap = await getIterableMap(config, "liquidity_bridge_eth_to_xl1_scanner_cursor");
|
|
2258
2434
|
const bridgeFulfillmentMap = await getIterableMap(config, "liquidity_bridge_eth_to_xl1_fulfillment");
|
|
2259
2435
|
const provider = await initEvmProvider(context);
|
|
2260
|
-
const {
|
|
2436
|
+
const {
|
|
2437
|
+
remoteBridgeContractAddress,
|
|
2438
|
+
remoteChainWalletPrivateKey,
|
|
2439
|
+
remoteTokenAddress,
|
|
2440
|
+
accountPath
|
|
2441
|
+
} = config;
|
|
2261
2442
|
const account = await resolveWalletForActor2(config.name, accountPath);
|
|
2262
2443
|
const wallet = new Wallet(remoteChainWalletPrivateKey, provider);
|
|
2263
2444
|
const bridgeableToken = BridgeableToken__factory.connect(getAddress2(remoteTokenAddress), wallet);
|
|
2264
2445
|
const bridge = LiquidityPoolBridge__factory.connect(getAddress2(remoteBridgeContractAddress), wallet);
|
|
2265
2446
|
const bridgeOwner = await bridge.owner();
|
|
2266
|
-
|
|
2447
|
+
assertEx26(bridgeOwner.toLowerCase() === wallet.address.toLowerCase(), () => "Wallet is not the owner of the bridge contract");
|
|
2267
2448
|
const remoteConfirmationDepth = getRemoteConfirmationDepth(config);
|
|
2268
2449
|
return {
|
|
2269
2450
|
account,
|
|
2270
2451
|
bridge,
|
|
2271
2452
|
bridgeableToken,
|
|
2272
2453
|
bridgeFulfillmentMap,
|
|
2454
|
+
config,
|
|
2273
2455
|
ethTxStateMap,
|
|
2274
2456
|
evmBridgeCursorMap,
|
|
2275
2457
|
gateway,
|
|
@@ -2278,18 +2460,18 @@ var getServices = /* @__PURE__ */ __name(async (context, gateway) => {
|
|
|
2278
2460
|
wallet,
|
|
2279
2461
|
xl1TxStateMap
|
|
2280
2462
|
};
|
|
2281
|
-
}
|
|
2463
|
+
};
|
|
2282
2464
|
|
|
2283
2465
|
// src/server/addWorkers.ts
|
|
2284
|
-
var addWorkers =
|
|
2466
|
+
var addWorkers = (config, services) => {
|
|
2285
2467
|
const connection2 = getConnection(config);
|
|
2286
2468
|
const telemetry2 = getTelemetry();
|
|
2287
2469
|
createWorkers(connection2, telemetry2, services);
|
|
2288
|
-
}
|
|
2470
|
+
};
|
|
2289
2471
|
|
|
2290
2472
|
// src/server/server.ts
|
|
2291
2473
|
var hostname = "::";
|
|
2292
|
-
var getServer =
|
|
2474
|
+
var getServer = async (context, gateway) => {
|
|
2293
2475
|
const { logger, config } = context;
|
|
2294
2476
|
const { port } = config;
|
|
2295
2477
|
const app = getApp(config, gateway);
|
|
@@ -2304,51 +2486,53 @@ var getServer = /* @__PURE__ */ __name(async (context, gateway) => {
|
|
|
2304
2486
|
srv.once("error", reject);
|
|
2305
2487
|
});
|
|
2306
2488
|
server.setTimeout(2e4);
|
|
2307
|
-
return {
|
|
2308
|
-
|
|
2309
|
-
services
|
|
2310
|
-
};
|
|
2311
|
-
}, "getServer");
|
|
2489
|
+
return { server, services };
|
|
2490
|
+
};
|
|
2312
2491
|
|
|
2313
2492
|
// src/telemetry/createBalanceMonitor.ts
|
|
2314
2493
|
var DEFAULT_INTERVAL_MS = 6e4;
|
|
2315
2494
|
var WEI_PER_GWEI = 10n ** 9n;
|
|
2316
2495
|
var TOKEN_DECIMALS = 10n ** 18n;
|
|
2317
2496
|
function createBalanceMonitor(config) {
|
|
2318
|
-
const {
|
|
2497
|
+
const {
|
|
2498
|
+
account,
|
|
2499
|
+
bridge,
|
|
2500
|
+
bridgeableToken,
|
|
2501
|
+
gateway,
|
|
2502
|
+
meter,
|
|
2503
|
+
provider,
|
|
2504
|
+
wallet,
|
|
2505
|
+
intervalMs = DEFAULT_INTERVAL_MS
|
|
2506
|
+
} = config;
|
|
2319
2507
|
let timer;
|
|
2320
|
-
const ethWalletGasBalance = meter.createGauge(
|
|
2321
|
-
|
|
2322
|
-
unit: "gwei"
|
|
2323
|
-
|
|
2324
|
-
const liquidityTokenBalance = meter.createGauge(
|
|
2325
|
-
|
|
2326
|
-
unit: "tokens"
|
|
2327
|
-
|
|
2328
|
-
const liquidityTokenAllowance = meter.createGauge(
|
|
2329
|
-
|
|
2330
|
-
unit: "tokens"
|
|
2331
|
-
|
|
2332
|
-
const xl1AccountBalance = meter.createGauge(
|
|
2333
|
-
|
|
2334
|
-
unit: "xl1"
|
|
2335
|
-
|
|
2508
|
+
const ethWalletGasBalance = meter.createGauge(
|
|
2509
|
+
"bridge_eth_wallet_gas_balance_gwei",
|
|
2510
|
+
{ description: "ETH balance of the bridge runner wallet (in gwei)", unit: "gwei" }
|
|
2511
|
+
);
|
|
2512
|
+
const liquidityTokenBalance = meter.createGauge(
|
|
2513
|
+
"bridge_eth_liquidity_token_balance",
|
|
2514
|
+
{ description: "ERC-20 token balance of the liquidity source (in whole tokens)", unit: "tokens" }
|
|
2515
|
+
);
|
|
2516
|
+
const liquidityTokenAllowance = meter.createGauge(
|
|
2517
|
+
"bridge_eth_liquidity_token_allowance",
|
|
2518
|
+
{ description: "ERC-20 token allowance from liquidity source to bridge contract (in whole tokens)", unit: "tokens" }
|
|
2519
|
+
);
|
|
2520
|
+
const xl1AccountBalance = meter.createGauge(
|
|
2521
|
+
"bridge_xl1_account_balance",
|
|
2522
|
+
{ description: "XL1 native balance of the bridge reserve account (in whole XL1)", unit: "xl1" }
|
|
2523
|
+
);
|
|
2336
2524
|
const walletAddress = wallet.address;
|
|
2337
2525
|
async function poll() {
|
|
2338
2526
|
try {
|
|
2339
2527
|
const balance = await provider.getBalance(walletAddress);
|
|
2340
|
-
ethWalletGasBalance.record(Number(balance / WEI_PER_GWEI), {
|
|
2341
|
-
address: walletAddress
|
|
2342
|
-
});
|
|
2528
|
+
ethWalletGasBalance.record(Number(balance / WEI_PER_GWEI), { address: walletAddress });
|
|
2343
2529
|
} catch (err) {
|
|
2344
2530
|
console.error("[BalanceMonitor] Failed to read ETH wallet gas balance:", err);
|
|
2345
2531
|
}
|
|
2346
2532
|
try {
|
|
2347
2533
|
const liquiditySourceAddress = await bridge.liquiditySource();
|
|
2348
2534
|
const balance = await bridgeableToken.balanceOf(liquiditySourceAddress);
|
|
2349
|
-
liquidityTokenBalance.record(Number(balance / TOKEN_DECIMALS), {
|
|
2350
|
-
address: liquiditySourceAddress
|
|
2351
|
-
});
|
|
2535
|
+
liquidityTokenBalance.record(Number(balance / TOKEN_DECIMALS), { address: liquiditySourceAddress });
|
|
2352
2536
|
} catch (err) {
|
|
2353
2537
|
console.error("[BalanceMonitor] Failed to read liquidity source token balance:", err);
|
|
2354
2538
|
}
|
|
@@ -2356,9 +2540,7 @@ function createBalanceMonitor(config) {
|
|
|
2356
2540
|
const liquiditySourceAddress = await bridge.liquiditySource();
|
|
2357
2541
|
const bridgeAddress = await bridge.getAddress();
|
|
2358
2542
|
const allowance = await bridgeableToken.allowance(liquiditySourceAddress, bridgeAddress);
|
|
2359
|
-
liquidityTokenAllowance.record(Number(allowance / TOKEN_DECIMALS), {
|
|
2360
|
-
address: liquiditySourceAddress
|
|
2361
|
-
});
|
|
2543
|
+
liquidityTokenAllowance.record(Number(allowance / TOKEN_DECIMALS), { address: liquiditySourceAddress });
|
|
2362
2544
|
} catch (err) {
|
|
2363
2545
|
console.error("[BalanceMonitor] Failed to read liquidity source token allowance:", err);
|
|
2364
2546
|
}
|
|
@@ -2366,15 +2548,12 @@ function createBalanceMonitor(config) {
|
|
|
2366
2548
|
const viewer = gateway.connection.viewer;
|
|
2367
2549
|
if (viewer) {
|
|
2368
2550
|
const balance = await viewer.account.balance.accountBalance(account.address);
|
|
2369
|
-
xl1AccountBalance.record(Number(balance / TOKEN_DECIMALS), {
|
|
2370
|
-
address: account.address.toString()
|
|
2371
|
-
});
|
|
2551
|
+
xl1AccountBalance.record(Number(balance / TOKEN_DECIMALS), { address: account.address.toString() });
|
|
2372
2552
|
}
|
|
2373
2553
|
} catch (err) {
|
|
2374
2554
|
console.error("[BalanceMonitor] Failed to read XL1 account balance:", err);
|
|
2375
2555
|
}
|
|
2376
2556
|
}
|
|
2377
|
-
__name(poll, "poll");
|
|
2378
2557
|
return {
|
|
2379
2558
|
start() {
|
|
2380
2559
|
void poll();
|
|
@@ -2388,35 +2567,41 @@ function createBalanceMonitor(config) {
|
|
|
2388
2567
|
}
|
|
2389
2568
|
};
|
|
2390
2569
|
}
|
|
2391
|
-
__name(createBalanceMonitor, "createBalanceMonitor");
|
|
2392
2570
|
|
|
2393
2571
|
// src/telemetry/createQueueMetrics.ts
|
|
2394
2572
|
var DEFAULT_INTERVAL_MS2 = 3e4;
|
|
2395
2573
|
function createQueueMetrics(config) {
|
|
2396
|
-
const {
|
|
2574
|
+
const {
|
|
2575
|
+
meter,
|
|
2576
|
+
queues,
|
|
2577
|
+
intervalMs = DEFAULT_INTERVAL_MS2
|
|
2578
|
+
} = config;
|
|
2397
2579
|
let timer;
|
|
2398
|
-
const waitingGauge = meter.createGauge(
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
description: "Number of
|
|
2409
|
-
|
|
2410
|
-
const
|
|
2411
|
-
|
|
2412
|
-
|
|
2580
|
+
const waitingGauge = meter.createGauge(
|
|
2581
|
+
"bridge_queue_waiting",
|
|
2582
|
+
{ description: "Number of waiting jobs in the bridge queue" }
|
|
2583
|
+
);
|
|
2584
|
+
const activeGauge = meter.createGauge(
|
|
2585
|
+
"bridge_queue_active",
|
|
2586
|
+
{ description: "Number of active jobs in the bridge queue" }
|
|
2587
|
+
);
|
|
2588
|
+
const completedGauge = meter.createGauge(
|
|
2589
|
+
"bridge_queue_completed",
|
|
2590
|
+
{ description: "Number of completed jobs in the bridge queue" }
|
|
2591
|
+
);
|
|
2592
|
+
const failedGauge = meter.createGauge(
|
|
2593
|
+
"bridge_queue_failed",
|
|
2594
|
+
{ description: "Number of failed jobs in the bridge queue" }
|
|
2595
|
+
);
|
|
2596
|
+
const delayedGauge = meter.createGauge(
|
|
2597
|
+
"bridge_queue_delayed",
|
|
2598
|
+
{ description: "Number of delayed jobs in the bridge queue" }
|
|
2599
|
+
);
|
|
2413
2600
|
async function poll() {
|
|
2414
2601
|
for (const [name13, queue] of Object.entries(queues)) {
|
|
2415
2602
|
try {
|
|
2416
2603
|
const counts = await queue.getJobCounts("waiting", "active", "completed", "failed", "delayed");
|
|
2417
|
-
const attrs = {
|
|
2418
|
-
queue_name: name13
|
|
2419
|
-
};
|
|
2604
|
+
const attrs = { queue_name: name13 };
|
|
2420
2605
|
waitingGauge.record(counts.waiting ?? 0, attrs);
|
|
2421
2606
|
activeGauge.record(counts.active ?? 0, attrs);
|
|
2422
2607
|
completedGauge.record(counts.completed ?? 0, attrs);
|
|
@@ -2427,7 +2612,6 @@ function createQueueMetrics(config) {
|
|
|
2427
2612
|
}
|
|
2428
2613
|
}
|
|
2429
2614
|
}
|
|
2430
|
-
__name(poll, "poll");
|
|
2431
2615
|
return {
|
|
2432
2616
|
start() {
|
|
2433
2617
|
void poll();
|
|
@@ -2441,26 +2625,9 @@ function createQueueMetrics(config) {
|
|
|
2441
2625
|
}
|
|
2442
2626
|
};
|
|
2443
2627
|
}
|
|
2444
|
-
__name(createQueueMetrics, "createQueueMetrics");
|
|
2445
2628
|
|
|
2446
2629
|
// src/BridgeActor.ts
|
|
2447
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
2448
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2449
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2450
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2451
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2452
|
-
}
|
|
2453
|
-
__name(_ts_decorate, "_ts_decorate");
|
|
2454
2630
|
var BridgeActor = class extends ActorV3 {
|
|
2455
|
-
static {
|
|
2456
|
-
__name(this, "BridgeActor");
|
|
2457
|
-
}
|
|
2458
|
-
static needs = {
|
|
2459
|
-
required: [
|
|
2460
|
-
XyoGatewayRunnerMoniker,
|
|
2461
|
-
XyoViewerMoniker
|
|
2462
|
-
]
|
|
2463
|
-
};
|
|
2464
2631
|
_gatewayRunner;
|
|
2465
2632
|
_balanceMonitor;
|
|
2466
2633
|
_queueMetrics;
|
|
@@ -2532,7 +2699,13 @@ var BridgeActor = class extends ActorV3 {
|
|
|
2532
2699
|
this.server = void 0;
|
|
2533
2700
|
}
|
|
2534
2701
|
};
|
|
2535
|
-
BridgeActor
|
|
2702
|
+
__publicField(BridgeActor, "needs", {
|
|
2703
|
+
required: [
|
|
2704
|
+
XyoGatewayRunnerMoniker,
|
|
2705
|
+
XyoViewerMoniker
|
|
2706
|
+
]
|
|
2707
|
+
});
|
|
2708
|
+
BridgeActor = __decorateClass([
|
|
2536
2709
|
creatable()
|
|
2537
2710
|
], BridgeActor);
|
|
2538
2711
|
|
|
@@ -2542,7 +2715,7 @@ import { BridgeConfigZod } from "@xyo-network/chain-orchestration";
|
|
|
2542
2715
|
// src/run.ts
|
|
2543
2716
|
import { exists } from "@xylabs/sdk-js";
|
|
2544
2717
|
import { initActorWallet } from "@xyo-network/chain-orchestration";
|
|
2545
|
-
var getBridgeActor =
|
|
2718
|
+
var getBridgeActor = async (config, locator) => {
|
|
2546
2719
|
const account = await initActorWallet({
|
|
2547
2720
|
config,
|
|
2548
2721
|
logger: locator.context.logger,
|
|
@@ -2554,17 +2727,15 @@ var getBridgeActor = /* @__PURE__ */ __name(async (config, locator) => {
|
|
|
2554
2727
|
config,
|
|
2555
2728
|
locator
|
|
2556
2729
|
});
|
|
2557
|
-
}
|
|
2558
|
-
var runBridge =
|
|
2730
|
+
};
|
|
2731
|
+
var runBridge = async (config, orchestrator, locator) => {
|
|
2559
2732
|
const bridge = await getBridgeActor(config, locator);
|
|
2560
|
-
const actors = [
|
|
2561
|
-
bridge
|
|
2562
|
-
].filter(exists);
|
|
2733
|
+
const actors = [bridge].filter(exists);
|
|
2563
2734
|
for (const actor of actors) {
|
|
2564
2735
|
await orchestrator.registerActor(actor);
|
|
2565
2736
|
}
|
|
2566
2737
|
await orchestrator.start();
|
|
2567
|
-
}
|
|
2738
|
+
};
|
|
2568
2739
|
|
|
2569
2740
|
// src/command.ts
|
|
2570
2741
|
function bridgeCommand(getConfiguration, getLocatorsFromConfig) {
|
|
@@ -2572,16 +2743,13 @@ function bridgeCommand(getConfiguration, getLocatorsFromConfig) {
|
|
|
2572
2743
|
command: "bridge",
|
|
2573
2744
|
deprecated: 'Use "start bridge" instead',
|
|
2574
2745
|
describe: "Run a XL1 Bridge Node",
|
|
2575
|
-
handler:
|
|
2746
|
+
handler: async () => {
|
|
2576
2747
|
const configuration = getConfiguration();
|
|
2577
|
-
const { locators, orchestrator } = await getLocatorsFromConfig([
|
|
2578
|
-
"bridge"
|
|
2579
|
-
], configuration);
|
|
2748
|
+
const { locators, orchestrator } = await getLocatorsFromConfig(["bridge"], configuration);
|
|
2580
2749
|
await runBridge(BridgeConfigZod.parse(locators["bridge"].context.config), orchestrator, locators["bridge"]);
|
|
2581
|
-
}
|
|
2750
|
+
}
|
|
2582
2751
|
};
|
|
2583
2752
|
}
|
|
2584
|
-
__name(bridgeCommand, "bridgeCommand");
|
|
2585
2753
|
export {
|
|
2586
2754
|
BridgeActor,
|
|
2587
2755
|
bridgeCommand,
|
|
@@ -2590,4 +2758,4 @@ export {
|
|
|
2590
2758
|
getBridgeActor,
|
|
2591
2759
|
runBridge
|
|
2592
2760
|
};
|
|
2593
|
-
//# sourceMappingURL=index.mjs.map
|
|
2761
|
+
//# sourceMappingURL=index.mjs.map
|