@xyo-network/chain-bridge 1.19.17 → 1.19.18

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.
Files changed (64) hide show
  1. package/dist/node/index.mjs +145 -92
  2. package/dist/node/index.mjs.map +1 -1
  3. package/dist/node/queue/flowProducer.d.ts +2 -1
  4. package/dist/node/queue/flowProducer.d.ts.map +1 -1
  5. package/dist/node/queue/index.d.ts +1 -0
  6. package/dist/node/queue/index.d.ts.map +1 -1
  7. package/dist/node/queue/telemetry.d.ts +3 -0
  8. package/dist/node/queue/telemetry.d.ts.map +1 -0
  9. package/dist/node/queue/workers/EthTransactionMonitor.d.ts +9 -0
  10. package/dist/node/queue/workers/EthTransactionMonitor.d.ts.map +1 -1
  11. package/dist/node/queue/workers/EthTransactionPreparation.d.ts +7 -1
  12. package/dist/node/queue/workers/EthTransactionPreparation.d.ts.map +1 -1
  13. package/dist/node/queue/workers/EthTransactionSubmission.d.ts +8 -0
  14. package/dist/node/queue/workers/EthTransactionSubmission.d.ts.map +1 -1
  15. package/dist/node/queue/workers/WorkerDescription.d.ts +2 -1
  16. package/dist/node/queue/workers/WorkerDescription.d.ts.map +1 -1
  17. package/dist/node/queue/workers/Xl1ToEthBridgeParent.d.ts +3 -0
  18. package/dist/node/queue/workers/Xl1ToEthBridgeParent.d.ts.map +1 -1
  19. package/dist/node/queue/workers/Xl1TransactionMonitor.d.ts +6 -0
  20. package/dist/node/queue/workers/Xl1TransactionMonitor.d.ts.map +1 -1
  21. package/dist/node/queue/workers/Xl1TransactionPreparation.d.ts +7 -0
  22. package/dist/node/queue/workers/Xl1TransactionPreparation.d.ts.map +1 -1
  23. package/dist/node/queue/workers/Xl1TransactionSubmission.d.ts +8 -0
  24. package/dist/node/queue/workers/Xl1TransactionSubmission.d.ts.map +1 -1
  25. package/dist/node/queue/workers/createWorkers.d.ts +2 -1
  26. package/dist/node/queue/workers/createWorkers.d.ts.map +1 -1
  27. package/dist/node/queue/workers/util/AsyncLogger.d.ts +5 -0
  28. package/dist/node/queue/workers/util/AsyncLogger.d.ts.map +1 -0
  29. package/dist/node/queue/workers/util/index.d.ts +3 -2
  30. package/dist/node/queue/workers/util/index.d.ts.map +1 -1
  31. package/dist/node/queue/workers/util/{validateSufficientAllowance.d.ts → validateSufficientLiquiditySourceAllowance.d.ts} +3 -7
  32. package/dist/node/queue/workers/util/validateSufficientLiquiditySourceAllowance.d.ts.map +1 -0
  33. package/dist/node/queue/workers/util/{validateSufficientBalance.d.ts → validateSufficientLiquiditySourceBalance.d.ts} +3 -7
  34. package/dist/node/queue/workers/util/validateSufficientLiquiditySourceBalance.d.ts.map +1 -0
  35. package/dist/node/queue/workers/util/validateSufficientRunnerEthBalanceForGas.d.ts +14 -0
  36. package/dist/node/queue/workers/util/validateSufficientRunnerEthBalanceForGas.d.ts.map +1 -0
  37. package/dist/node/server/addFlowProducer.d.ts.map +1 -1
  38. package/dist/node/server/addWorkers.d.ts.map +1 -1
  39. package/package.json +26 -30
  40. package/src/config/getBridgeWalletAccount.ts +1 -1
  41. package/src/config/getGateway.ts +1 -1
  42. package/src/queue/flowProducer.ts +3 -2
  43. package/src/queue/index.ts +1 -0
  44. package/src/queue/telemetry.ts +12 -0
  45. package/src/queue/workers/EthTransactionMonitor.ts +10 -6
  46. package/src/queue/workers/EthTransactionPreparation.ts +17 -9
  47. package/src/queue/workers/EthTransactionSubmission.ts +8 -28
  48. package/src/queue/workers/WorkerDescription.ts +2 -1
  49. package/src/queue/workers/Xl1ToEthBridgeParent.ts +8 -5
  50. package/src/queue/workers/Xl1TransactionMonitor.ts +7 -5
  51. package/src/queue/workers/Xl1TransactionPreparation.ts +7 -7
  52. package/src/queue/workers/Xl1TransactionSubmission.ts +6 -5
  53. package/src/queue/workers/createWorkers.ts +9 -8
  54. package/src/queue/workers/util/AsyncLogger.ts +5 -0
  55. package/src/queue/workers/util/index.ts +3 -2
  56. package/src/queue/workers/util/{validateSufficientAllowance.ts → validateSufficientLiquiditySourceAllowance.ts} +3 -6
  57. package/src/queue/workers/util/{validateSufficientBalance.ts → validateSufficientLiquiditySourceBalance.ts} +3 -6
  58. package/src/queue/workers/util/validateSufficientRunnerEthBalanceForGas.ts +57 -0
  59. package/src/server/addFlowProducer.ts +5 -2
  60. package/src/server/addWorkers.ts +6 -2
  61. package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteStatus.ts +3 -3
  62. package/src/services/getServices.ts +1 -1
  63. package/dist/node/queue/workers/util/validateSufficientAllowance.d.ts.map +0 -1
  64. package/dist/node/queue/workers/util/validateSufficientBalance.d.ts.map +0 -1
@@ -32,10 +32,11 @@ var getConnection = /* @__PURE__ */ __name((config) => {
32
32
  import { isDefined as isDefined2 } from "@xylabs/sdk-js";
33
33
  import { FlowProducer } from "bullmq";
34
34
  var flowProducer;
35
- var getFlowProducer = /* @__PURE__ */ __name((connection2) => {
35
+ var getFlowProducer = /* @__PURE__ */ __name((connection2, telemetry2) => {
36
36
  if (isDefined2(flowProducer)) return flowProducer;
37
37
  flowProducer = new FlowProducer({
38
- connection: connection2
38
+ connection: connection2,
39
+ telemetry: telemetry2
39
40
  });
40
41
  return flowProducer;
41
42
  }, "getFlowProducer");
@@ -44,14 +45,14 @@ var getFlowProducer = /* @__PURE__ */ __name((connection2) => {
44
45
  import { PayloadBuilder as PayloadBuilder8 } from "@xyo-network/sdk-js";
45
46
 
46
47
  // src/queue/workers/createWorkers.ts
47
- var createWorkers = /* @__PURE__ */ __name((connection2, services) => {
48
- Xl1ToEthBridgeParent.createWorker(connection2);
49
- Xl1TransactionPreparation.createWorker(connection2, services);
50
- Xl1TransactionSubmission.createWorker(connection2, services);
51
- Xl1TransactionMonitor.createWorker(connection2, services);
52
- EthTransactionPreparation.createWorker(connection2, services);
53
- EthTransactionSubmission.createWorker(connection2, services);
54
- EthTransactionMonitor.createWorker(connection2, services);
48
+ var createWorkers = /* @__PURE__ */ __name((connection2, telemetry2, services) => {
49
+ Xl1ToEthBridgeParent.createWorker(connection2, telemetry2);
50
+ Xl1TransactionPreparation.createWorker(connection2, telemetry2, services);
51
+ Xl1TransactionSubmission.createWorker(connection2, telemetry2, services);
52
+ Xl1TransactionMonitor.createWorker(connection2, telemetry2, services);
53
+ EthTransactionPreparation.createWorker(connection2, telemetry2, services);
54
+ EthTransactionSubmission.createWorker(connection2, telemetry2, services);
55
+ EthTransactionMonitor.createWorker(connection2, telemetry2, services);
55
56
  }, "createWorkers");
56
57
 
57
58
  // src/queue/workers/EthTransactionMonitor.ts
@@ -60,7 +61,7 @@ import { PayloadBuilder } from "@xyo-network/sdk-js";
60
61
  import { Worker } from "bullmq";
61
62
  var name = "Monitor Submitted ETH Transaction";
62
63
  var queueName = "eth-tx-monitor";
63
- var createWorker = /* @__PURE__ */ __name((connection2, services) => {
64
+ var createWorker = /* @__PURE__ */ __name((connection2, telemetry2, services) => {
64
65
  const provider = assertEx(services?.provider, () => "provider service not provided");
65
66
  const stateMap = assertEx(services?.ethTxStateMap, () => "ethTxStateMap service not provided");
66
67
  const worker = new Worker(queueName, async (job) => {
@@ -75,10 +76,12 @@ var createWorker = /* @__PURE__ */ __name((connection2, services) => {
75
76
  await stateMap.set(hash, state);
76
77
  return {
77
78
  blockHash,
78
- blockNumber
79
+ blockNumber,
80
+ submissionHash
79
81
  };
80
82
  }, {
81
- connection: connection2
83
+ connection: connection2,
84
+ telemetry: telemetry2
82
85
  });
83
86
  worker.on("failed", (job, err) => {
84
87
  console.error(`[${name}] Job ${job?.id} failed:`, err.message);
@@ -94,7 +97,7 @@ var EthTransactionMonitor = {
94
97
  };
95
98
 
96
99
  // src/queue/workers/EthTransactionPreparation.ts
97
- import { assertEx as assertEx5, hexToBigInt as hexToBigInt4 } from "@xylabs/sdk-js";
100
+ import { assertEx as assertEx6, hexToBigInt as hexToBigInt4 } from "@xylabs/sdk-js";
98
101
  import { PayloadBuilder as PayloadBuilder3 } from "@xyo-network/sdk-js";
99
102
  import { isBridgeIntent as isBridgeIntent4 } from "@xyo-network/xl1-sdk";
100
103
  import { Worker as Worker2 } from "bullmq";
@@ -124,10 +127,10 @@ var submitXl1Transaction = /* @__PURE__ */ __name(async (preparedTx, gateway) =>
124
127
  return result;
125
128
  }, "submitXl1Transaction");
126
129
 
127
- // src/queue/workers/util/validateSufficientAllowance.ts
130
+ // src/queue/workers/util/validateSufficientLiquiditySourceAllowance.ts
128
131
  import { assertEx as assertEx3, hexToBigInt as hexToBigInt2 } from "@xylabs/sdk-js";
129
132
  import { isBridgeIntent as isBridgeIntent2 } from "@xyo-network/xl1-sdk";
130
- var validateSufficientAllowance = /* @__PURE__ */ __name(async (tx, bridgeableToken, bridge, logger) => {
133
+ var validateSufficientLiquiditySourceAllowance = /* @__PURE__ */ __name(async (tx, bridgeableToken, bridge, logger) => {
131
134
  const bridgeIntent = assertEx3(tx[1].find(isBridgeIntent2), () => "No bridge intent found");
132
135
  const amount = hexToBigInt2(bridgeIntent.destAmount);
133
136
  const liquiditySourceAddress = await bridge.liquiditySource();
@@ -135,49 +138,79 @@ var validateSufficientAllowance = /* @__PURE__ */ __name(async (tx, bridgeableTo
135
138
  const remainingAllowance = await bridgeableToken.allowance(liquiditySourceAddress, bridgeAddress);
136
139
  await logger?.log(`Remaining allowance: ${remainingAllowance.toString()}`);
137
140
  return remainingAllowance >= amount;
138
- }, "validateSufficientAllowance");
141
+ }, "validateSufficientLiquiditySourceAllowance");
139
142
 
140
- // src/queue/workers/util/validateSufficientBalance.ts
143
+ // src/queue/workers/util/validateSufficientLiquiditySourceBalance.ts
141
144
  import { assertEx as assertEx4, hexToBigInt as hexToBigInt3 } from "@xylabs/sdk-js";
142
145
  import { isBridgeIntent as isBridgeIntent3 } from "@xyo-network/xl1-sdk";
143
- var validateSufficientBalance = /* @__PURE__ */ __name(async (tx, bridgeableToken, bridge, logger) => {
146
+ var validateSufficientLiquiditySourceBalance = /* @__PURE__ */ __name(async (tx, bridgeableToken, bridge, logger) => {
144
147
  const bridgeIntent = assertEx4(tx[1].find(isBridgeIntent3), () => "No bridge intent found");
145
148
  const amount = hexToBigInt3(bridgeIntent.destAmount);
146
149
  const liquiditySourceAddress = await bridge.liquiditySource();
147
150
  const balance = await bridgeableToken.balanceOf(liquiditySourceAddress);
148
151
  await logger?.log(`Remaining balance: ${balance.toString()}`);
149
152
  return balance >= amount;
150
- }, "validateSufficientBalance");
153
+ }, "validateSufficientLiquiditySourceBalance");
154
+
155
+ // src/queue/workers/util/validateSufficientRunnerEthBalanceForGas.ts
156
+ import { assertEx as assertEx5 } from "@xylabs/sdk-js";
157
+ var DEFAULT_GAS_BUFFER_BPS = 2000n;
158
+ var validateSufficientRunnerEthBalanceForGas = /* @__PURE__ */ __name(async (preparedTx, wallet, logger, bufferBps = DEFAULT_GAS_BUFFER_BPS) => {
159
+ const provider = assertEx5(wallet.provider, () => "Wallet provider is not defined");
160
+ const feeData = await provider.getFeeData();
161
+ const perGas = feeData.maxFeePerGas ?? feeData.gasPrice;
162
+ if (perGas == null) {
163
+ await logger?.log("[gas] unable to resolve gas price / maxFeePerGas from provider");
164
+ return true;
165
+ }
166
+ const transactionRequest = {
167
+ ...preparedTx,
168
+ from: await wallet.getAddress()
169
+ };
170
+ const estGas = await provider.estimateGas(transactionRequest);
171
+ const txValue = preparedTx?.value ?? 0n;
172
+ const baseRequired = estGas * perGas + txValue;
173
+ const required = baseRequired * (10000n + bufferBps) / 10000n;
174
+ const balance = await provider.getBalance(await wallet.getAddress());
175
+ await logger?.log(`[gas] runner=${await wallet.getAddress()} balance=${balance.toString()} estGas=${estGas.toString()} perGas=${perGas.toString()} value=${txValue.toString()} requiredWithBuffer=${required.toString()} bufferBps=${bufferBps.toString()}`);
176
+ return balance >= required;
177
+ }, "validateSufficientRunnerEthBalanceForGas");
151
178
 
152
179
  // src/queue/workers/EthTransactionPreparation.ts
153
180
  var name2 = "Prepare ETH Transaction";
154
181
  var queueName2 = "eth-tx-prepare";
155
- var createWorker2 = /* @__PURE__ */ __name((connection2, services) => {
156
- const bridge = assertEx5(services?.bridge, () => "bridge service not provided");
157
- const bridgeableToken = assertEx5(services?.bridgeableToken, () => "bridgeableToken service not provided");
158
- const stateMap = assertEx5(services?.ethTxStateMap, () => "ethTxStateMap service not provided");
182
+ var createWorker2 = /* @__PURE__ */ __name((connection2, telemetry2, services) => {
183
+ const bridge = assertEx6(services?.bridge, () => "bridge service not provided");
184
+ const bridgeableToken = assertEx6(services?.bridgeableToken, () => "bridgeableToken service not provided");
185
+ const stateMap = assertEx6(services?.ethTxStateMap, () => "ethTxStateMap service not provided");
186
+ const wallet = assertEx6(services?.wallet, () => "wallet service not provided");
159
187
  const worker = new Worker2(queueName2, async (job) => {
160
188
  const { tx } = job.data;
161
189
  const hash = await PayloadBuilder3.hash(tx[0]);
162
190
  await job.log(`[${hash}] preparing ETH transaction`);
163
191
  await job.log(`[${hash}] validating liquiditySource has sufficient allowance`);
164
- if (!await validateSufficientAllowance(tx, bridgeableToken, bridge, job)) {
192
+ if (!await validateSufficientLiquiditySourceAllowance(tx, bridgeableToken, bridge, job)) {
165
193
  throw new Error("Liquidity source does not have sufficient allowance for the bridge to execute the transaction");
166
194
  }
167
195
  await job.log(`[${hash}] validated liquiditySource has sufficient allowance`);
168
196
  await job.log(`[${hash}] validating liquiditySource has sufficient balance`);
169
- if (!await validateSufficientBalance(tx, bridgeableToken, bridge, job)) {
197
+ if (!await validateSufficientLiquiditySourceBalance(tx, bridgeableToken, bridge, job)) {
170
198
  throw new Error("Liquidity source does not have sufficient balance for the bridge to execute the transaction");
171
199
  }
172
200
  await job.log(`[${hash}] validated liquiditySource has sufficient balance`);
173
201
  await job.log(`[${hash}] building ETH transaction`);
174
- const bridgeIntent = assertEx5(tx[1].find(isBridgeIntent4), () => "No bridge intent found");
202
+ const bridgeIntent = assertEx6(tx[1].find(isBridgeIntent4), () => "No bridge intent found");
175
203
  const amount = hexToBigInt4(bridgeIntent.destAmount);
176
204
  const srcAddress = getAddress(bridgeIntent.srcAddress);
177
205
  const destAddress = getAddress(bridgeIntent.destAddress);
178
206
  const nonce = hexToBigInt4(await PayloadBuilder3.hash(tx[0]));
179
207
  const preparedTx = await bridge.getFunction("bridgeFromRemote").populateTransaction(srcAddress, destAddress, amount, nonce);
180
208
  await job.log(`[${hash}] built ETH transaction`);
209
+ await job.log(`[${hash}] validating tx runner has sufficient ETH for gas`);
210
+ if (!await validateSufficientRunnerEthBalanceForGas(preparedTx, wallet, job)) {
211
+ throw new Error("Transaction runner does not have sufficient ETH to cover estimated gas (with buffer)");
212
+ }
213
+ await job.log(`[${hash}] validated tx runner has sufficient ETH for gas`);
181
214
  await job.log(`[${hash}] storing ETH preparedTx`);
182
215
  await stateMap.set(hash, {
183
216
  preparedTx
@@ -186,7 +219,8 @@ var createWorker2 = /* @__PURE__ */ __name((connection2, services) => {
186
219
  await job.log(`[${hash}] prepared ETH transaction`);
187
220
  return {};
188
221
  }, {
189
- connection: connection2
222
+ connection: connection2,
223
+ telemetry: telemetry2
190
224
  });
191
225
  worker.on("failed", (job, err) => {
192
226
  console.error(`[${name2}] Job ${job?.id} failed:`, err.message);
@@ -202,21 +236,20 @@ var EthTransactionPreparation = {
202
236
  };
203
237
 
204
238
  // src/queue/workers/EthTransactionSubmission.ts
205
- import { assertEx as assertEx6, isDefined as isDefined3 } from "@xylabs/sdk-js";
239
+ import { assertEx as assertEx7, isDefined as isDefined3 } from "@xylabs/sdk-js";
206
240
  import { PayloadBuilder as PayloadBuilder4 } from "@xyo-network/sdk-js";
207
241
  import { Worker as Worker3 } from "bullmq";
208
242
  var name3 = "Submit ETH Transaction";
209
243
  var queueName3 = "eth-tx-submit";
210
- var createWorker3 = /* @__PURE__ */ __name((connection2, services) => {
211
- const bridge = assertEx6(services?.bridge, () => "bridge service not provided");
212
- const bridgeableToken = assertEx6(services?.bridgeableToken, () => "bridgeableToken service not provided");
213
- const wallet = assertEx6(services?.wallet, () => "wallet service not provided");
214
- const stateMap = assertEx6(services?.ethTxStateMap, () => "ethTxStateMap service not provided");
244
+ var createWorker3 = /* @__PURE__ */ __name((connection2, telemetry2, services) => {
245
+ const bridge = assertEx7(services?.bridge, () => "bridge service not provided");
246
+ const bridgeableToken = assertEx7(services?.bridgeableToken, () => "bridgeableToken service not provided");
247
+ const wallet = assertEx7(services?.wallet, () => "wallet service not provided");
248
+ const stateMap = assertEx7(services?.ethTxStateMap, () => "ethTxStateMap service not provided");
215
249
  const worker = new Worker3(queueName3, async (job) => {
216
250
  const { tx } = job.data;
217
251
  const hash = await PayloadBuilder4.hash(tx[0]);
218
- const state = assertEx6(await stateMap.get(hash), () => `[${hash}] state not found`);
219
- const preparedTx = assertEx6(state?.preparedTx, () => `[${hash}] preparedTx not found`);
252
+ const state = assertEx7(await stateMap.get(hash), () => `[${hash}] state not found`);
220
253
  const { submissionHash: existingSubmissionHash } = state;
221
254
  if (isDefined3(existingSubmissionHash)) {
222
255
  await job.log(`[${hash}] Tx already submitted with submission response hash ${existingSubmissionHash}`);
@@ -225,7 +258,7 @@ var createWorker3 = /* @__PURE__ */ __name((connection2, services) => {
225
258
  };
226
259
  }
227
260
  await job.log(`[${hash}] Submitting ETH tx`);
228
- const submissionHash = assertEx6(await submitEthTransaction(tx, bridgeableToken, bridge, wallet), () => `[${hash}] submissionHash not found in receipt`);
261
+ const submissionHash = assertEx7(await submitEthTransaction(tx, bridgeableToken, bridge, wallet), () => `[${hash}] submissionHash not found in receipt`);
229
262
  await job.log(`[${hash}] Submitted ETH tx and received submission response hash ${submissionHash}`);
230
263
  await job.log(`[${hash}] Storing ETH submissionHash`);
231
264
  state.submissionHash = submissionHash;
@@ -236,6 +269,7 @@ var createWorker3 = /* @__PURE__ */ __name((connection2, services) => {
236
269
  };
237
270
  }, {
238
271
  connection: connection2,
272
+ telemetry: telemetry2,
239
273
  concurrency: 1
240
274
  });
241
275
  worker.on("failed", (job, err) => {
@@ -255,15 +289,14 @@ var EthTransactionSubmission = {
255
289
  import { Worker as Worker4 } from "bullmq";
256
290
  var name4 = "Bridge XL1 to Ethereum";
257
291
  var queueName4 = "xl1-to-eth-bridge";
258
- var createWorker4 = /* @__PURE__ */ __name((connection2) => {
292
+ var createWorker4 = /* @__PURE__ */ __name((connection2, telemetry2) => {
259
293
  const worker = new Worker4(queueName4, async (job) => {
260
294
  await job.log(`[${job.name}] start`);
261
295
  await job.log(`[${job.name}] done`);
262
- return {
263
- ok: true
264
- };
296
+ return {};
265
297
  }, {
266
- connection: connection2
298
+ connection: connection2,
299
+ telemetry: telemetry2
267
300
  });
268
301
  worker.on("failed", (job, err) => {
269
302
  console.error(`[${name4}] Job ${job?.id} failed:`, err.message);
@@ -279,20 +312,20 @@ var Xl1ToEthBridgeParent = {
279
312
  };
280
313
 
281
314
  // src/queue/workers/Xl1TransactionMonitor.ts
282
- import { assertEx as assertEx7, isDefined as isDefined4, isNull } from "@xylabs/sdk-js";
315
+ import { assertEx as assertEx8, isDefined as isDefined4, isNull } from "@xylabs/sdk-js";
283
316
  import { PayloadBuilder as PayloadBuilder5 } from "@xyo-network/sdk-js";
284
317
  import { UnrecoverableError, Worker as Worker5 } from "bullmq";
285
318
  var name5 = "Monitor Submitted XL1 Transaction";
286
319
  var queueName5 = "xl1-tx-monitor";
287
- var createWorker5 = /* @__PURE__ */ __name((connection2, services) => {
288
- const gateway = assertEx7(services?.gateway, () => "gateway service not provided");
289
- const stateMap = assertEx7(services?.xl1TxStateMap, () => "xl1TxStateMap service not provided");
320
+ var createWorker5 = /* @__PURE__ */ __name((connection2, telemetry2, services) => {
321
+ const gateway = assertEx8(services?.gateway, () => "gateway service not provided");
322
+ const stateMap = assertEx8(services?.xl1TxStateMap, () => "xl1TxStateMap service not provided");
290
323
  const worker = new Worker5(queueName5, async (job) => {
291
324
  const { tx } = job.data;
292
325
  const hash = await PayloadBuilder5.hash(tx[0]);
293
- const viewer = assertEx7(gateway.connection.viewer, () => `[${hash}] viewer not defined on gateway`);
294
- const state = assertEx7(await stateMap.get(hash), () => `[${hash}] state not found`);
295
- const submissionHash = assertEx7(state?.submissionHash, () => `[${hash}] submissionHash not found`);
326
+ const viewer = assertEx8(gateway.connection.viewer, () => `[${hash}] viewer not defined on gateway`);
327
+ const state = assertEx8(await stateMap.get(hash), () => `[${hash}] state not found`);
328
+ const submissionHash = assertEx8(state?.submissionHash, () => `[${hash}] submissionHash not found`);
296
329
  await job.log(`[${hash}] Checking for XL1 transaction inclusion on chain`);
297
330
  const foundTx = await viewer.transactionByHash(submissionHash);
298
331
  if (isDefined4(foundTx) && !isNull(foundTx)) {
@@ -309,7 +342,8 @@ var createWorker5 = /* @__PURE__ */ __name((connection2, services) => {
309
342
  await job.log(`[${hash}] Transaction not yet included, retrying later`);
310
343
  throw new Error(`[${hash}] Transaction not yet included`);
311
344
  }, {
312
- connection: connection2
345
+ connection: connection2,
346
+ telemetry: telemetry2
313
347
  });
314
348
  worker.on("failed", (job, err) => {
315
349
  console.error(`[${name5}] Job ${job?.id} failed:`, err.message);
@@ -325,13 +359,13 @@ var Xl1TransactionMonitor = {
325
359
  };
326
360
 
327
361
  // src/queue/workers/Xl1TransactionPreparation.ts
328
- import { assertEx as assertEx8 } from "@xylabs/sdk-js";
362
+ import { assertEx as assertEx9 } from "@xylabs/sdk-js";
329
363
  import { PayloadBuilder as PayloadBuilder6 } from "@xyo-network/sdk-js";
330
364
  import { Worker as Worker6 } from "bullmq";
331
365
  var name6 = "Prepare XL1 Transaction";
332
366
  var queueName6 = "xl1-tx-prepare";
333
- var createWorker6 = /* @__PURE__ */ __name((connection2, services) => {
334
- const stateMap = assertEx8(services?.xl1TxStateMap, () => "xl1TxStateMap service not provided");
367
+ var createWorker6 = /* @__PURE__ */ __name((connection2, telemetry2, services) => {
368
+ const stateMap = assertEx9(services?.xl1TxStateMap, () => "xl1TxStateMap service not provided");
335
369
  const worker = new Worker6(queueName6, async (job) => {
336
370
  const { tx } = job.data;
337
371
  const hash = await PayloadBuilder6.hash(tx[0]);
@@ -343,9 +377,12 @@ var createWorker6 = /* @__PURE__ */ __name((connection2, services) => {
343
377
  });
344
378
  await job.log(`[${hash}] stored XL1 preparedTx`);
345
379
  await job.log(`[${hash}] prepared XL1 transaction`);
346
- return {};
380
+ return {
381
+ preparedTx
382
+ };
347
383
  }, {
348
- connection: connection2
384
+ connection: connection2,
385
+ telemetry: telemetry2
349
386
  });
350
387
  worker.on("failed", (job, err) => {
351
388
  console.error(`[${name6}] Job ${job?.id} failed:`, err.message);
@@ -361,19 +398,19 @@ var Xl1TransactionPreparation = {
361
398
  };
362
399
 
363
400
  // src/queue/workers/Xl1TransactionSubmission.ts
364
- import { assertEx as assertEx9, isDefined as isDefined5 } from "@xylabs/sdk-js";
401
+ import { assertEx as assertEx10, isDefined as isDefined5 } from "@xylabs/sdk-js";
365
402
  import { PayloadBuilder as PayloadBuilder7 } from "@xyo-network/sdk-js";
366
403
  import { Worker as Worker7 } from "bullmq";
367
404
  var name7 = "Submit XL1 Transaction";
368
405
  var queueName7 = "xl1-tx-submit";
369
- var createWorker7 = /* @__PURE__ */ __name((connection2, services) => {
370
- const gateway = assertEx9(services?.gateway, () => "gateway service not provided");
371
- const stateMap = assertEx9(services?.xl1TxStateMap, () => "xl1TxStateMap service not provided");
406
+ var createWorker7 = /* @__PURE__ */ __name((connection2, telemetry2, services) => {
407
+ const gateway = assertEx10(services?.gateway, () => "gateway service not provided");
408
+ const stateMap = assertEx10(services?.xl1TxStateMap, () => "xl1TxStateMap service not provided");
372
409
  const worker = new Worker7(queueName7, async (job) => {
373
410
  const { tx } = job.data;
374
411
  const hash = await PayloadBuilder7.hash(tx[0]);
375
- const state = assertEx9(await stateMap.get(hash), () => `[${hash}] state not found`);
376
- const preparedTx = assertEx9(state?.preparedTx, () => `[${hash}] preparedTx not found`);
412
+ const state = assertEx10(await stateMap.get(hash), () => `[${hash}] state not found`);
413
+ const preparedTx = assertEx10(state?.preparedTx, () => `[${hash}] preparedTx not found`);
377
414
  const { submissionHash: existingSubmissionHash } = state;
378
415
  if (isDefined5(existingSubmissionHash)) {
379
416
  await job.log(`[${hash}] Tx already submitted with submission response hash ${existingSubmissionHash}`);
@@ -392,7 +429,8 @@ var createWorker7 = /* @__PURE__ */ __name((connection2, services) => {
392
429
  submissionHash
393
430
  };
394
431
  }, {
395
- connection: connection2
432
+ connection: connection2,
433
+ telemetry: telemetry2
396
434
  });
397
435
  worker.on("failed", (job, err) => {
398
436
  console.error(`[${name7}] Job ${job?.id} failed:`, err.message);
@@ -508,10 +546,24 @@ var createXl1ToEthBridgeJob = /* @__PURE__ */ __name(async (flowProducer2, tx) =
508
546
  return flow;
509
547
  }, "createXl1ToEthBridgeJob");
510
548
 
549
+ // src/queue/telemetry.ts
550
+ import { isDefined as isDefined6 } from "@xylabs/sdk-js";
551
+ import { BullMQOtel } from "bullmq-otel";
552
+ var telemetry;
553
+ var options = {
554
+ enableMetrics: true
555
+ };
556
+ var getTelemetry = /* @__PURE__ */ __name(() => {
557
+ if (isDefined6(telemetry)) return telemetry;
558
+ telemetry = new BullMQOtel(options);
559
+ return telemetry;
560
+ }, "getTelemetry");
561
+
511
562
  // src/server/addFlowProducer.ts
512
563
  var addFlowProducer = /* @__PURE__ */ __name((app, config) => {
513
564
  const connection2 = getConnection(config);
514
- const flowProducer2 = getFlowProducer(connection2);
565
+ const telemetry2 = getTelemetry();
566
+ const flowProducer2 = getFlowProducer(connection2, telemetry2);
515
567
  app.flowProducer = flowProducer2;
516
568
  return app;
517
569
  }, "addFlowProducer");
@@ -549,14 +601,14 @@ var asToken = /* @__PURE__ */ __name((value) => {
549
601
  }, "asToken");
550
602
 
551
603
  // src/config/getBridgeEscrowAddress.ts
552
- import { asAddress as asAddress2, assertEx as assertEx10 } from "@xylabs/sdk-js";
604
+ import { asAddress as asAddress2, assertEx as assertEx11 } from "@xylabs/sdk-js";
553
605
  var tryGetBridgeEscrowAddress = /* @__PURE__ */ __name((config) => {
554
606
  const address = asAddress2(config.escrowAddress);
555
607
  return address;
556
608
  }, "tryGetBridgeEscrowAddress");
557
609
 
558
610
  // src/config/getBridgeFeesAddress.ts
559
- import { asAddress as asAddress3, assertEx as assertEx11 } from "@xylabs/sdk-js";
611
+ import { asAddress as asAddress3, assertEx as assertEx12 } from "@xylabs/sdk-js";
560
612
  var tryGetBridgeFeesAddress = /* @__PURE__ */ __name((config) => {
561
613
  const address = asAddress3(config.feesAddress);
562
614
  return address;
@@ -584,22 +636,22 @@ var getMinBridgeAmount = /* @__PURE__ */ __name((config) => {
584
636
  }, "getMinBridgeAmount");
585
637
 
586
638
  // src/config/getRemoteChainId.ts
587
- import { assertEx as assertEx12 } from "@xylabs/sdk-js";
639
+ import { assertEx as assertEx13 } from "@xylabs/sdk-js";
588
640
  var getRemoteChainId = /* @__PURE__ */ __name((config) => {
589
- const remoteChainId = assertEx12(asChainId(config.remoteChainId), () => "Invalid remote chain ID in config");
641
+ const remoteChainId = assertEx13(asChainId(config.remoteChainId), () => "Invalid remote chain ID in config");
590
642
  return remoteChainId;
591
643
  }, "getRemoteChainId");
592
644
 
593
645
  // src/config/getRemoteTokenAddress.ts
594
- import { assertEx as assertEx13 } from "@xylabs/sdk-js";
646
+ import { assertEx as assertEx14 } from "@xylabs/sdk-js";
595
647
  var getRemoteTokenAddress = /* @__PURE__ */ __name((config) => {
596
648
  const token = asToken(config.remoteTokenAddress);
597
- return assertEx13(token, () => "Remote token address is not defined in bridge configuration");
649
+ return assertEx14(token, () => "Remote token address is not defined in bridge configuration");
598
650
  }, "getRemoteTokenAddress");
599
651
 
600
652
  // src/config/getBridgeWalletAccount.ts
601
- import { isDefined as isDefined6, isUndefined } from "@xylabs/sdk-js";
602
- import { HDWallet } from "@xyo-network/wallet";
653
+ import { isDefined as isDefined7, isUndefined } from "@xylabs/sdk-js";
654
+ import { HDWallet } from "@xyo-network/sdk-js";
603
655
  import { ADDRESS_INDEX, generateXyoBaseWalletFromPhrase } from "@xyo-network/xl1-sdk";
604
656
  var accountServiceSingleton;
605
657
  var getBridgeWalletAccount = /* @__PURE__ */ __name(async (config) => {
@@ -632,20 +684,20 @@ var getTransferAddresses = /* @__PURE__ */ __name(async (config) => {
632
684
  }, "getTransferAddresses");
633
685
 
634
686
  // src/config/getXl1ChainId.ts
635
- import { assertEx as assertEx14, isDefined as isDefined7 } from "@xylabs/sdk-js";
687
+ import { assertEx as assertEx15, isDefined as isDefined8 } from "@xylabs/sdk-js";
636
688
  var getXl1ChainId = /* @__PURE__ */ __name((config) => {
637
689
  const xl1ChainId = config.xl1ChainId;
638
- if (isDefined7(xl1ChainId)) {
639
- return assertEx14(asChainId(xl1ChainId), () => "Invalid xl1ChainId in bridge config");
690
+ if (isDefined8(xl1ChainId)) {
691
+ return assertEx15(asChainId(xl1ChainId), () => "Invalid xl1ChainId in bridge config");
640
692
  }
641
- return assertEx14(asChainId(config.chain.id), () => "Invalid chain.id in config");
693
+ return assertEx15(asChainId(config.chain.id), () => "Invalid chain.id in config");
642
694
  }, "getXl1ChainId");
643
695
 
644
696
  // src/config/getXl1TokenAddress.ts
645
- import { isDefined as isDefined8 } from "@xylabs/sdk-js";
697
+ import { isDefined as isDefined9 } from "@xylabs/sdk-js";
646
698
  var getXl1TokenAddress = /* @__PURE__ */ __name((config) => {
647
699
  const token = asToken(config.xl1TokenAddress);
648
- if (isDefined8(token)) return token;
700
+ if (isDefined9(token)) return token;
649
701
  return getXl1ChainId(config);
650
702
  }, "getXl1TokenAddress");
651
703
 
@@ -856,7 +908,7 @@ var validateBridgeEstimateExact = /* @__PURE__ */ __name(async (intent, transfer
856
908
  }, "validateBridgeEstimateExact");
857
909
 
858
910
  // src/util/validateBridgeTransaction.ts
859
- import { asAddress as asAddress4, isDefined as isDefined9 } from "@xylabs/sdk-js";
911
+ import { asAddress as asAddress4, isDefined as isDefined10 } from "@xylabs/sdk-js";
860
912
  import { addressesContains, BoundWitnessValidator, payloadHashesContainsAll } from "@xyo-network/boundwitness-validator";
861
913
  import { PayloadBuilder as PayloadBuilder11 } from "@xyo-network/sdk-js";
862
914
  var validateBridgeTransaction = /* @__PURE__ */ __name(async (signedTxBw, intent, transfer, config) => {
@@ -864,7 +916,7 @@ var validateBridgeTransaction = /* @__PURE__ */ __name(async (signedTxBw, intent
864
916
  const chainId = getXl1ChainId(config);
865
917
  if (signedTxBw.chain !== chainId) return false;
866
918
  const errors = await new BoundWitnessValidator(signedTxBw).validate();
867
- if (isDefined9(errors) && errors.length > 0) return false;
919
+ if (isDefined10(errors) && errors.length > 0) return false;
868
920
  const sender = asAddress4(srcAddress, true);
869
921
  if (!addressesContains(signedTxBw, sender)) return false;
870
922
  const hashes = await PayloadBuilder11.hashes([
@@ -932,7 +984,7 @@ var makeBridgeToRemoteRoute = /* @__PURE__ */ __name((config) => {
932
984
 
933
985
  // src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteEstimate.ts
934
986
  import { requestHandlerValidator as requestHandlerValidator4 } from "@xylabs/express";
935
- import { assertEx as assertEx15, toAddress as toAddress3 } from "@xylabs/sdk-js";
987
+ import { assertEx as assertEx16, toAddress as toAddress3 } from "@xylabs/sdk-js";
936
988
  import { PayloadZodStrictOfSchema as PayloadZodStrictOfSchema3 } from "@xyo-network/sdk-js";
937
989
  import { BridgeIntentFieldsZod as BridgeIntentFieldsZod2, BridgeIntentSchema as BridgeIntentSchema3, buildUnsignedTransaction, toXL1BlockNumber, TransactionBoundWitnessZod, TransferZod as TransferZod2 } from "@xyo-network/xl1-sdk";
938
990
  import { z as z3 } from "zod";
@@ -963,7 +1015,7 @@ var makeBridgeToRemoteEstimateRoute = /* @__PURE__ */ __name((config, gateway) =
963
1015
  const { srcAddress, srcAmount, destAddress } = req.body;
964
1016
  const [bridgeIntent, transfer] = await generateBridgeEstimate(srcAddress, srcAmount, destAddress, config);
965
1017
  const sender = toAddress3(srcAddress);
966
- const viewer = assertEx15(gateway.connection.viewer, () => new Error("Viewer not available on gateway connection"));
1018
+ const viewer = assertEx16(gateway.connection.viewer, () => new Error("Viewer not available on gateway connection"));
967
1019
  const currentBlockNumber = await viewer.currentBlockNumber();
968
1020
  const nbf = toXL1BlockNumber(currentBlockNumber, true);
969
1021
  const exp = toXL1BlockNumber(currentBlockNumber + 1e3, true);
@@ -983,7 +1035,7 @@ var makeBridgeToRemoteEstimateRoute = /* @__PURE__ */ __name((config, gateway) =
983
1035
 
984
1036
  // src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteStatus.ts
985
1037
  import { requestHandlerValidator as requestHandlerValidator5 } from "@xylabs/express";
986
- import { asHex as asHex3, isDefined as isDefined10 } from "@xylabs/sdk-js";
1038
+ import { asHex as asHex3, isDefined as isDefined11 } from "@xylabs/sdk-js";
987
1039
  import { PayloadBuilder as PayloadBuilder13, PayloadZodStrictOfSchema as PayloadZodStrictOfSchema4 } from "@xyo-network/sdk-js";
988
1040
  import { asBridgeIntent, BridgeDestinationObservationFieldsZod as BridgeDestinationObservationFieldsZod2, BridgeDestinationObservationSchema as BridgeDestinationObservationSchema2, BridgeIntentFieldsZod as BridgeIntentFieldsZod3, BridgeIntentSchema as BridgeIntentSchema4, BridgeSourceObservationFieldsZod as BridgeSourceObservationFieldsZod2, BridgeSourceObservationSchema as BridgeSourceObservationSchema2, isBridgeIntent as isBridgeIntent5 } from "@xyo-network/xl1-sdk";
989
1041
  import { Queue } from "bullmq";
@@ -1072,7 +1124,7 @@ var makeBridgeToRemoteStatusRoute = /* @__PURE__ */ __name((config) => {
1072
1124
  const result = [];
1073
1125
  const queues = getStatusQueues(config);
1074
1126
  const statusQueueJobs = await getStatusQueueJobs(queues, jobId);
1075
- const tx = Object.values(statusQueueJobs).map((job) => job?.data?.tx).find((tx2) => isDefined10(tx2));
1127
+ const tx = Object.values(statusQueueJobs).map((job) => job?.data?.tx).find((tx2) => isDefined11(tx2));
1076
1128
  if (!tx) return res.sendStatus(404);
1077
1129
  const bridgeIntent = tx[1].find(isBridgeIntent5);
1078
1130
  if (!bridgeIntent) return res.sendStatus(404);
@@ -1080,7 +1132,7 @@ var makeBridgeToRemoteStatusRoute = /* @__PURE__ */ __name((config) => {
1080
1132
  const { xl1TransactionMonitorJob } = statusQueueJobs;
1081
1133
  const xl1MonitorState = xl1TransactionMonitorJob ? await xl1TransactionMonitorJob.getState() : void 0;
1082
1134
  const srcConfirmation = asHex3(jobId);
1083
- if (xl1MonitorState === "completed" && isDefined10(srcConfirmation)) {
1135
+ if (xl1MonitorState === "completed" && isDefined11(srcConfirmation)) {
1084
1136
  const bridgeCommonFieldsZod = z4.object({}).extend(BridgeSourceObservationFieldsZod2.shape);
1085
1137
  const bridgeCommonFields = bridgeCommonFieldsZod.parse(bridgeIntent);
1086
1138
  const observation = {
@@ -1092,9 +1144,9 @@ var makeBridgeToRemoteStatusRoute = /* @__PURE__ */ __name((config) => {
1092
1144
  }
1093
1145
  const { ethTransactionMonitorJob } = statusQueueJobs;
1094
1146
  const ethMonitorState = ethTransactionMonitorJob ? await ethTransactionMonitorJob.getState() : void 0;
1095
- const blockHash = ethTransactionMonitorJob?.returnvalue?.blockHash;
1096
- const destConfirmation = asHex3(blockHash);
1097
- if (ethMonitorState === "completed" && isDefined10(blockHash)) {
1147
+ const submissionHash = ethTransactionMonitorJob?.returnvalue?.submissionHash;
1148
+ const destConfirmation = asHex3(submissionHash);
1149
+ if (ethMonitorState === "completed" && isDefined11(submissionHash)) {
1098
1150
  const bridgeDestinationFieldsZod = z4.object({}).extend(BridgeDestinationObservationFieldsZod2.shape);
1099
1151
  const bridgeDestinationFields = bridgeDestinationFieldsZod.parse({
1100
1152
  ...bridgeIntent,
@@ -1157,10 +1209,10 @@ var getApp = /* @__PURE__ */ __name((config, gateway) => {
1157
1209
  }, "getApp");
1158
1210
 
1159
1211
  // src/services/getServices.ts
1160
- import { assertEx as assertEx16, isDefined as isDefined11 } from "@xylabs/sdk-js";
1212
+ import { assertEx as assertEx17, isDefined as isDefined12 } from "@xylabs/sdk-js";
1161
1213
  import { initEvmProvider } from "@xyo-network/chain-orchestration";
1214
+ import { HDWallet as HDWallet2 } from "@xyo-network/sdk-js";
1162
1215
  import { BridgeableToken__factory, LiquidityPoolBridge__factory } from "@xyo-network/typechain";
1163
- import { HDWallet as HDWallet2 } from "@xyo-network/wallet";
1164
1216
  import { getAddress as getAddress2, Wallet } from "ethers";
1165
1217
 
1166
1218
  // src/services/getIterableMap.ts
@@ -1202,12 +1254,12 @@ var getServices = /* @__PURE__ */ __name(async (context, gateway) => {
1202
1254
  const xl1TxStateMap = await getIterableMap(config, "liquidity_bridge_xl1_to_eth_xl1_tx_state");
1203
1255
  const provider = await initEvmProvider(context);
1204
1256
  const { remoteBridgeContractAddress, remoteChainWalletPrivateKey, remoteTokenAddress, mnemonic } = config;
1205
- const account = isDefined11(mnemonic) ? await HDWallet2.fromPhrase(mnemonic) : await HDWallet2.random();
1257
+ const account = isDefined12(mnemonic) ? await HDWallet2.fromPhrase(mnemonic) : await HDWallet2.random();
1206
1258
  const wallet = new Wallet(remoteChainWalletPrivateKey, provider);
1207
1259
  const bridgeableToken = BridgeableToken__factory.connect(getAddress2(remoteTokenAddress), wallet);
1208
1260
  const bridge = LiquidityPoolBridge__factory.connect(getAddress2(remoteBridgeContractAddress), wallet);
1209
1261
  const bridgeOwner = await bridge.owner();
1210
- assertEx16(bridgeOwner.toLowerCase() === wallet.address.toLowerCase(), () => "Wallet is not the owner of the bridge contract");
1262
+ assertEx17(bridgeOwner.toLowerCase() === wallet.address.toLowerCase(), () => "Wallet is not the owner of the bridge contract");
1211
1263
  return {
1212
1264
  account,
1213
1265
  bridge,
@@ -1223,7 +1275,8 @@ var getServices = /* @__PURE__ */ __name(async (context, gateway) => {
1223
1275
  // src/server/addWorkers.ts
1224
1276
  var addWorkers = /* @__PURE__ */ __name((config, services) => {
1225
1277
  const connection2 = getConnection(config);
1226
- createWorkers(connection2, services);
1278
+ const telemetry2 = getTelemetry();
1279
+ createWorkers(connection2, telemetry2, services);
1227
1280
  }, "addWorkers");
1228
1281
 
1229
1282
  // src/server/server.ts