@xyo-network/chain-bridge 1.19.18 → 1.20.1

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 (134) hide show
  1. package/dist/node/config/getTestGateway.d.ts +4 -0
  2. package/dist/node/config/getTestGateway.d.ts.map +1 -0
  3. package/dist/node/config/index.d.ts +1 -1
  4. package/dist/node/config/index.d.ts.map +1 -1
  5. package/dist/node/index.mjs +700 -506
  6. package/dist/node/index.mjs.map +1 -1
  7. package/dist/node/modules/index.d.ts +0 -1
  8. package/dist/node/modules/index.d.ts.map +1 -1
  9. package/dist/node/queue/flowProducer.d.ts.map +1 -1
  10. package/dist/node/queue/flows/createEthToXl1BridgeJob.d.ts +10 -0
  11. package/dist/node/queue/flows/createEthToXl1BridgeJob.d.ts.map +1 -0
  12. package/dist/node/queue/flows/createXl1ToEthBridgeJob.d.ts.map +1 -1
  13. package/dist/node/queue/flows/index.d.ts +1 -0
  14. package/dist/node/queue/flows/index.d.ts.map +1 -1
  15. package/dist/node/queue/getXl1ToEthQueueJobs.d.ts +20 -0
  16. package/dist/node/queue/getXl1ToEthQueueJobs.d.ts.map +1 -0
  17. package/dist/node/queue/getXl1ToEthQueues.d.ts +14 -0
  18. package/dist/node/queue/getXl1ToEthQueues.d.ts.map +1 -0
  19. package/dist/node/queue/index.d.ts +3 -0
  20. package/dist/node/queue/index.d.ts.map +1 -1
  21. package/dist/node/queue/prefix.d.ts +2 -0
  22. package/dist/node/queue/prefix.d.ts.map +1 -0
  23. package/dist/node/queue/workers/EthToXl1BridgeParent.d.ts +8 -0
  24. package/dist/node/queue/workers/EthToXl1BridgeParent.d.ts.map +1 -0
  25. package/dist/node/queue/workers/EthTransactionMonitor.d.ts +2 -0
  26. package/dist/node/queue/workers/EthTransactionMonitor.d.ts.map +1 -1
  27. package/dist/node/queue/workers/EthTransactionPreparation.d.ts +4 -2
  28. package/dist/node/queue/workers/EthTransactionPreparation.d.ts.map +1 -1
  29. package/dist/node/queue/workers/EthTransactionSubmission.d.ts +2 -0
  30. package/dist/node/queue/workers/EthTransactionSubmission.d.ts.map +1 -1
  31. package/dist/node/queue/workers/EthTransactionSubmissionStorage.d.ts +13 -0
  32. package/dist/node/queue/workers/EthTransactionSubmissionStorage.d.ts.map +1 -0
  33. package/dist/node/queue/workers/Xl1ToEthBridgeParent.d.ts +6 -1
  34. package/dist/node/queue/workers/Xl1ToEthBridgeParent.d.ts.map +1 -1
  35. package/dist/node/queue/workers/Xl1TransactionMonitor.d.ts +4 -0
  36. package/dist/node/queue/workers/Xl1TransactionMonitor.d.ts.map +1 -1
  37. package/dist/node/queue/workers/Xl1TransactionPreparation.d.ts +2 -0
  38. package/dist/node/queue/workers/Xl1TransactionPreparation.d.ts.map +1 -1
  39. package/dist/node/queue/workers/Xl1TransactionSubmission.d.ts +2 -0
  40. package/dist/node/queue/workers/Xl1TransactionSubmission.d.ts.map +1 -1
  41. package/dist/node/queue/workers/Xl1TransactionSubmissionStorage.d.ts +13 -0
  42. package/dist/node/queue/workers/Xl1TransactionSubmissionStorage.d.ts.map +1 -0
  43. package/dist/node/queue/workers/createWorkers.d.ts.map +1 -1
  44. package/dist/node/queue/workers/index.d.ts +3 -0
  45. package/dist/node/queue/workers/index.d.ts.map +1 -1
  46. package/dist/node/queue/workers/util/index.d.ts +0 -3
  47. package/dist/node/queue/workers/util/index.d.ts.map +1 -1
  48. package/dist/node/server/index.d.ts +2 -0
  49. package/dist/node/server/index.d.ts.map +1 -1
  50. package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeToRemote.d.ts.map +1 -1
  51. package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteEstimate.d.ts +1 -1
  52. package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteStatus.d.ts.map +1 -1
  53. package/dist/node/server/server.d.ts.map +1 -1
  54. package/dist/node/services/IBridgeServiceCollection.d.ts +1 -1
  55. package/dist/node/services/IBridgeServiceCollection.d.ts.map +1 -1
  56. package/dist/node/services/TxState.d.ts +0 -7
  57. package/dist/node/services/TxState.d.ts.map +1 -1
  58. package/dist/node/util/index.d.ts +0 -3
  59. package/dist/node/util/index.d.ts.map +1 -1
  60. package/dist/node/validation/AsyncLogger.d.ts.map +1 -0
  61. package/dist/node/validation/index.d.ts +7 -0
  62. package/dist/node/validation/index.d.ts.map +1 -0
  63. package/dist/node/validation/validateBridgeEstimate.d.ts.map +1 -0
  64. package/dist/node/validation/validateBridgeEstimateExact.d.ts.map +1 -0
  65. package/dist/node/validation/validateBridgeTransaction.d.ts.map +1 -0
  66. package/dist/node/validation/validateSufficientLiquiditySourceAllowance.d.ts.map +1 -0
  67. package/dist/node/validation/validateSufficientLiquiditySourceBalance.d.ts.map +1 -0
  68. package/dist/node/validation/validateSufficientRunnerEthBalanceForGas.d.ts.map +1 -0
  69. package/dist/node/validation/validateSufficientXL1SourceAddressBalance.d.ts +15 -0
  70. package/dist/node/validation/validateSufficientXL1SourceAddressBalance.d.ts.map +1 -0
  71. package/package.json +31 -31
  72. package/src/config/getTestGateway.ts +24 -0
  73. package/src/config/index.ts +1 -1
  74. package/src/modules/index.ts +0 -1
  75. package/src/queue/flowProducer.ts +5 -1
  76. package/src/queue/flows/createEthToXl1BridgeJob.ts +71 -0
  77. package/src/queue/flows/createXl1ToEthBridgeJob.ts +48 -20
  78. package/src/queue/flows/index.ts +1 -0
  79. package/src/queue/getXl1ToEthQueueJobs.ts +57 -0
  80. package/src/queue/getXl1ToEthQueues.ts +39 -0
  81. package/src/queue/index.ts +3 -0
  82. package/src/queue/prefix.ts +1 -0
  83. package/src/queue/workers/EthToXl1BridgeParent.ts +40 -0
  84. package/src/queue/workers/EthTransactionMonitor.ts +6 -2
  85. package/src/queue/workers/EthTransactionPreparation.ts +9 -5
  86. package/src/queue/workers/EthTransactionSubmission.ts +4 -12
  87. package/src/queue/workers/EthTransactionSubmissionStorage.ts +76 -0
  88. package/src/queue/workers/Xl1ToEthBridgeParent.ts +8 -3
  89. package/src/queue/workers/Xl1TransactionMonitor.ts +13 -9
  90. package/src/queue/workers/Xl1TransactionPreparation.ts +6 -2
  91. package/src/queue/workers/Xl1TransactionSubmission.ts +8 -9
  92. package/src/queue/workers/Xl1TransactionSubmissionStorage.ts +77 -0
  93. package/src/queue/workers/createWorkers.ts +10 -4
  94. package/src/queue/workers/index.ts +3 -0
  95. package/src/queue/workers/util/index.ts +0 -3
  96. package/src/server/index.ts +3 -2
  97. package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemote.ts +11 -1
  98. package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteStatus.ts +27 -101
  99. package/src/server/server.ts +1 -0
  100. package/src/services/IBridgeServiceCollection.ts +1 -1
  101. package/src/services/TxState.ts +0 -18
  102. package/src/util/index.ts +0 -3
  103. package/src/validation/index.ts +6 -0
  104. package/src/{util → validation}/validateBridgeEstimate.ts +1 -1
  105. package/src/{util → validation}/validateBridgeEstimateExact.ts +1 -1
  106. package/src/{util → validation}/validateBridgeTransaction.ts +1 -2
  107. package/src/validation/validateSufficientXL1SourceAddressBalance.ts +39 -0
  108. package/dist/node/config/getGateway.d.ts +0 -4
  109. package/dist/node/config/getGateway.d.ts.map +0 -1
  110. package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/XL1TransactionCompletionMonitorSentinel.d.ts +0 -60
  111. package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/XL1TransactionCompletionMonitorSentinel.d.ts.map +0 -1
  112. package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/index.d.ts +0 -2
  113. package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/index.d.ts.map +0 -1
  114. package/dist/node/queue/workers/util/AsyncLogger.d.ts.map +0 -1
  115. package/dist/node/queue/workers/util/validateSufficientLiquiditySourceAllowance.d.ts.map +0 -1
  116. package/dist/node/queue/workers/util/validateSufficientLiquiditySourceBalance.d.ts.map +0 -1
  117. package/dist/node/queue/workers/util/validateSufficientRunnerEthBalanceForGas.d.ts.map +0 -1
  118. package/dist/node/util/validateBridgeEstimate.d.ts.map +0 -1
  119. package/dist/node/util/validateBridgeEstimateExact.d.ts.map +0 -1
  120. package/dist/node/util/validateBridgeTransaction.d.ts.map +0 -1
  121. package/src/config/getGateway.ts +0 -23
  122. package/src/modules/XL1TransactionCompletionMonitorSentinel/XL1TransactionCompletionMonitorSentinel.ts +0 -165
  123. package/src/modules/XL1TransactionCompletionMonitorSentinel/index.ts +0 -1
  124. /package/dist/node/{queue/workers/util → validation}/AsyncLogger.d.ts +0 -0
  125. /package/dist/node/{util → validation}/validateBridgeEstimate.d.ts +0 -0
  126. /package/dist/node/{util → validation}/validateBridgeEstimateExact.d.ts +0 -0
  127. /package/dist/node/{util → validation}/validateBridgeTransaction.d.ts +0 -0
  128. /package/dist/node/{queue/workers/util → validation}/validateSufficientLiquiditySourceAllowance.d.ts +0 -0
  129. /package/dist/node/{queue/workers/util → validation}/validateSufficientLiquiditySourceBalance.d.ts +0 -0
  130. /package/dist/node/{queue/workers/util → validation}/validateSufficientRunnerEthBalanceForGas.d.ts +0 -0
  131. /package/src/{queue/workers/util → validation}/AsyncLogger.ts +0 -0
  132. /package/src/{queue/workers/util → validation}/validateSufficientLiquiditySourceAllowance.ts +0 -0
  133. /package/src/{queue/workers/util → validation}/validateSufficientLiquiditySourceBalance.ts +0 -0
  134. /package/src/{queue/workers/util → validation}/validateSufficientRunnerEthBalanceForGas.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyo-network/chain-bridge",
3
- "version": "1.19.18",
3
+ "version": "1.20.1",
4
4
  "description": "XYO Layer One Bridge",
5
5
  "homepage": "https://xylabs.com",
6
6
  "bugs": {
@@ -49,22 +49,22 @@
49
49
  "types": "tsc --noEmit -p tsconfig.test.json"
50
50
  },
51
51
  "dependencies": {
52
- "@opentelemetry/instrumentation": "~0.212.0",
53
- "@opentelemetry/instrumentation-express": "~0.60.0",
54
- "@opentelemetry/instrumentation-http": "~0.212.0",
52
+ "@opentelemetry/instrumentation": "~0.213.0",
53
+ "@opentelemetry/instrumentation-express": "~0.61.0",
54
+ "@opentelemetry/instrumentation-http": "~0.213.0",
55
55
  "@xylabs/express": "~5.0.80",
56
56
  "@xylabs/mongo": "~5.0.80",
57
57
  "@xylabs/sdk-js": "~5.0.80",
58
- "@xyo-network/boundwitness-validator": "~5.3.10",
59
- "@xyo-network/chain-orchestration": "~1.19.18",
60
- "@xyo-network/chain-protocol": "~1.19.18",
61
- "@xyo-network/chain-services": "~1.19.18",
62
- "@xyo-network/sdk-js": "~5.3.10",
63
- "@xyo-network/sentinel-abstract": "~5.3.10",
64
- "@xyo-network/sentinel-model": "~5.3.10",
65
- "@xyo-network/typechain": "~4.1.1",
66
- "@xyo-network/wallet-model": "~5.3.10",
67
- "@xyo-network/xl1-sdk": "~1.24.29",
58
+ "@xyo-network/boundwitness-validator": "~5.3.15",
59
+ "@xyo-network/chain-orchestration": "~1.20.1",
60
+ "@xyo-network/chain-protocol": "~1.20.1",
61
+ "@xyo-network/chain-services": "~1.20.1",
62
+ "@xyo-network/sdk-js": "~5.3.15",
63
+ "@xyo-network/sentinel-abstract": "~5.3.15",
64
+ "@xyo-network/sentinel-model": "~5.3.15",
65
+ "@xyo-network/typechain": "~4.1.2",
66
+ "@xyo-network/wallet-model": "~5.3.15",
67
+ "@xyo-network/xl1-sdk": "~1.25.18",
68
68
  "async-mutex": "~0.5.0",
69
69
  "bullmq": "~5.70.1",
70
70
  "bullmq-otel": "~1.3.0",
@@ -82,31 +82,31 @@
82
82
  "@types/cors": "~2.8.19",
83
83
  "@types/express": "5.0.6",
84
84
  "@types/express-serve-static-core": "~5.1.1",
85
- "@types/node": "~25.3.0",
85
+ "@types/node": "~25.3.3",
86
86
  "@xylabs/mongo": "~5.0.80",
87
87
  "@xylabs/sdk-js": "~5.0.80",
88
88
  "@xylabs/ts-scripts-yarn3": "~7.3.2",
89
89
  "@xylabs/tsconfig": "~7.3.2",
90
90
  "@xylabs/vitest-extended": "~5.0.80",
91
- "@xyo-network/account": "~5.3.10",
92
- "@xyo-network/account-model": "~5.3.10",
93
- "@xyo-network/archivist-abstract": "~5.3.10",
94
- "@xyo-network/archivist-mongodb": "~5.3.10",
95
- "@xyo-network/archivist-view": "~5.3.10",
91
+ "@xyo-network/account": "~5.3.15",
92
+ "@xyo-network/account-model": "~5.3.15",
93
+ "@xyo-network/archivist-abstract": "~5.3.15",
94
+ "@xyo-network/archivist-mongodb": "~5.3.15",
95
+ "@xyo-network/archivist-view": "~5.3.15",
96
96
  "@xyo-network/bios": "~7.2.1",
97
97
  "@xyo-network/bios-model": "~7.2.1",
98
- "@xyo-network/boundwitness-builder": "~5.3.10",
99
- "@xyo-network/chain-protocol": "~1.19.18",
100
- "@xyo-network/chain-services": "~1.19.18",
101
- "@xyo-network/chain-telemetry": "~1.19.18",
102
- "@xyo-network/module-abstract": "~5.3.10",
103
- "@xyo-network/module-abstract-mongodb": "~5.3.10",
104
- "@xyo-network/node-memory": "~5.3.10",
105
- "@xyo-network/sdk-js": "~5.3.10",
106
- "@xyo-network/sentinel-memory": "~5.3.10",
107
- "@xyo-network/xl1-sdk": "~1.24.29",
98
+ "@xyo-network/boundwitness-builder": "~5.3.15",
99
+ "@xyo-network/chain-protocol": "~1.20.1",
100
+ "@xyo-network/chain-services": "~1.20.1",
101
+ "@xyo-network/chain-telemetry": "~1.20.1",
102
+ "@xyo-network/module-abstract": "~5.3.15",
103
+ "@xyo-network/module-abstract-mongodb": "~5.3.15",
104
+ "@xyo-network/node-memory": "~5.3.15",
105
+ "@xyo-network/sdk-js": "~5.3.15",
106
+ "@xyo-network/sentinel-memory": "~5.3.15",
107
+ "@xyo-network/xl1-sdk": "~1.25.18",
108
108
  "async-mutex": "~0.5.0",
109
- "axios": "~1.13.5",
109
+ "axios": "~1.13.6",
110
110
  "dotenv": "~17.3.1",
111
111
  "eslint": "^9.39.3",
112
112
  "ethers": "^6.16.0",
@@ -0,0 +1,24 @@
1
+ import { assertEx, isDefined } from '@xylabs/sdk-js'
2
+ import { basicRemoteRunnerLocator, type BridgeConfig } from '@xyo-network/chain-orchestration'
3
+ import { HDWallet } from '@xyo-network/sdk-js'
4
+ import type { XyoGatewayRunner } from '@xyo-network/xl1-sdk'
5
+ import {
6
+ ADDRESS_INDEX, generateXyoBaseWalletFromPhrase, HttpRpcRemoteConfigZod, XyoGatewayRunnerMoniker,
7
+ } from '@xyo-network/xl1-sdk'
8
+
9
+ let gatewayInstance: XyoGatewayRunner | undefined
10
+
11
+ export const getTestGateway = async (config: BridgeConfig): Promise<XyoGatewayRunner> => {
12
+ if (isDefined(gatewayInstance)) return gatewayInstance
13
+ const { mnemonic } = config
14
+ const httpRpcConfig = HttpRpcRemoteConfigZod.safeParse(config.remote?.rpc)
15
+ const endpoint = assertEx(
16
+ httpRpcConfig.success ? assertEx(httpRpcConfig.data.url, () => 'RPC URL is required for gateway [no httpConfig]') : undefined,
17
+ () => 'RPC URL is required for gateway',
18
+ )
19
+ const walletPhrase = isDefined(mnemonic) ? mnemonic : HDWallet.generateMnemonic()
20
+ const wallet = await generateXyoBaseWalletFromPhrase(walletPhrase)
21
+ const signerAccount = await wallet.derivePath(ADDRESS_INDEX.XYO)
22
+ const locator = await basicRemoteRunnerLocator('test', { rpc: { protocol: 'http', url: endpoint } }, signerAccount)
23
+ return await locator.getInstance<XyoGatewayRunner>(XyoGatewayRunnerMoniker)
24
+ }
@@ -5,11 +5,11 @@ export * from './getBridgeFeesAddress.ts'
5
5
  export * from './getBridgeSettings.ts'
6
6
  export * from './getBridgeWalletAccount.ts'
7
7
  export * from './getFeeStructure.ts'
8
- export * from './getGateway.ts'
9
8
  export * from './getMaxBridgeAmount.ts'
10
9
  export * from './getMinBridgeAmount.ts'
11
10
  export * from './getRemoteChainId.ts'
12
11
  export * from './getRemoteTokenAddress.ts'
12
+ export * from './getTestGateway.ts'
13
13
  export * from './getTransferAddresses.ts'
14
14
  export * from './getXl1ChainId.ts'
15
15
  export * from './getXl1TokenAddress.ts'
@@ -1,2 +1 @@
1
1
  export * from './EVMLiquidityBridgeTransactionCompletionMonitorSentinel/index.ts'
2
- export * from './XL1TransactionCompletionMonitorSentinel/index.ts'
@@ -3,10 +3,14 @@ import { FlowProducer } from 'bullmq'
3
3
  import type { BullMQOtel } from 'bullmq-otel'
4
4
  import type { Redis } from 'ioredis'
5
5
 
6
+ import { prefix } from './prefix.ts'
7
+
6
8
  let flowProducer: FlowProducer | undefined
7
9
 
8
10
  export const getFlowProducer = (connection: Redis, telemetry?: BullMQOtel) => {
9
11
  if (isDefined(flowProducer)) return flowProducer
10
- flowProducer = new FlowProducer({ connection, telemetry })
12
+ flowProducer = new FlowProducer({
13
+ connection, telemetry, prefix,
14
+ })
11
15
  return flowProducer
12
16
  }
@@ -0,0 +1,71 @@
1
+ import { PayloadBuilder } from '@xyo-network/sdk-js'
2
+ import type { SignedHydratedTransaction } from '@xyo-network/xl1-sdk'
3
+ import type { FlowProducer } from 'bullmq'
4
+
5
+ import {
6
+ EthToXl1BridgeParent, Xl1TransactionMonitor, Xl1TransactionPreparation, Xl1TransactionSubmission,
7
+ Xl1TransactionSubmissionStorage,
8
+ } from '../workers/index.ts'
9
+
10
+ /**
11
+ * Creates a job flow for bridging a transaction from Ethereum to XL1.
12
+ * @param flowProducer The flow producer to run the job
13
+ * @param tx The bridge transaction
14
+ * @returns The JobNode representing the ETH to XL1 bridge job
15
+ */
16
+ export const createEthToXl1BridgeJob = async (
17
+ flowProducer: FlowProducer,
18
+ tx: SignedHydratedTransaction,
19
+ ) => {
20
+ const jobId = await PayloadBuilder.hash(tx[0])
21
+ const flow = await flowProducer.add({
22
+ // Step 0 (runs first as parent job)
23
+ name: EthToXl1BridgeParent.name,
24
+ queueName: EthToXl1BridgeParent.queueName,
25
+ data: { tx },
26
+ opts: { jobId },
27
+ children: [
28
+ {
29
+ // Step 4
30
+ name: Xl1TransactionMonitor.name,
31
+ queueName: Xl1TransactionMonitor.queueName,
32
+ data: { tx },
33
+ opts: {
34
+ jobId, attempts: 60, backoff: { type: 'fixed', delay: 5000 },
35
+ },
36
+ children: [
37
+ {
38
+ // Step 3
39
+ name: Xl1TransactionSubmissionStorage.name,
40
+ queueName: Xl1TransactionSubmissionStorage.queueName,
41
+ data: { tx },
42
+ opts: {
43
+ jobId, attempts: 60, backoff: { type: 'fixed', delay: 5000 },
44
+ },
45
+ children: [
46
+ {
47
+ // Step 2
48
+ name: Xl1TransactionSubmission.name,
49
+ queueName: Xl1TransactionSubmission.queueName,
50
+ data: { tx },
51
+ opts: { jobId },
52
+ children: [
53
+ {
54
+ // Step 1 (runs first as deepest child)
55
+ name: Xl1TransactionPreparation.name,
56
+ queueName: Xl1TransactionPreparation.queueName,
57
+ data: { tx },
58
+ opts: {
59
+ jobId, attempts: 60, backoff: { type: 'fixed', delay: 5000 },
60
+ },
61
+ },
62
+ ],
63
+ },
64
+ ],
65
+ },
66
+ ],
67
+ },
68
+ ],
69
+ })
70
+ return flow
71
+ }
@@ -3,8 +3,8 @@ import type { SignedHydratedTransaction } from '@xyo-network/xl1-sdk'
3
3
  import type { FlowProducer } from 'bullmq'
4
4
 
5
5
  import {
6
- EthTransactionMonitor, EthTransactionPreparation, EthTransactionSubmission, Xl1ToEthBridgeParent, Xl1TransactionMonitor, Xl1TransactionPreparation,
7
- Xl1TransactionSubmission,
6
+ EthTransactionMonitor, EthTransactionPreparation, EthTransactionSubmission, EthTransactionSubmissionStorage, Xl1ToEthBridgeParent, Xl1TransactionMonitor,
7
+ Xl1TransactionPreparation, Xl1TransactionSubmission, Xl1TransactionSubmissionStorage,
8
8
  } from '../workers/index.ts'
9
9
 
10
10
  /**
@@ -19,13 +19,14 @@ export const createXl1ToEthBridgeJob = async (
19
19
  ) => {
20
20
  const jobId = await PayloadBuilder.hash(tx[0])
21
21
  const flow = await flowProducer.add({
22
+ // Step 0 (runs first as parent job)
22
23
  name: Xl1ToEthBridgeParent.name,
23
24
  queueName: Xl1ToEthBridgeParent.queueName,
24
25
  data: { tx },
25
26
  opts: { jobId },
26
27
  children: [
27
28
  {
28
- // Step 6 (runs after child completes)
29
+ // Step 8
29
30
  name: EthTransactionMonitor.name,
30
31
  queueName: EthTransactionMonitor.queueName,
31
32
  data: { tx },
@@ -34,40 +35,67 @@ export const createXl1ToEthBridgeJob = async (
34
35
  },
35
36
  children: [
36
37
  {
37
- // Step 5
38
- name: EthTransactionSubmission.name,
39
- queueName: EthTransactionSubmission.queueName,
38
+ // Step 7
39
+ name: EthTransactionSubmissionStorage.name,
40
+ queueName: EthTransactionSubmissionStorage.queueName,
40
41
  data: { tx },
42
+ opts: {
43
+ jobId, attempts: 60, backoff: { type: 'fixed', delay: 5000 },
44
+ },
41
45
  children: [
42
46
  {
43
- // Step 4
44
- name: EthTransactionPreparation.name,
45
- queueName: EthTransactionPreparation.queueName,
47
+ // Step 6
48
+ name: EthTransactionSubmission.name,
49
+ queueName: EthTransactionSubmission.queueName,
46
50
  data: { tx },
47
51
  opts: { jobId },
48
52
  children: [
49
53
  {
50
- // Step 3
51
- name: Xl1TransactionMonitor.name,
52
- queueName: Xl1TransactionMonitor.queueName,
54
+ // Step 5
55
+ name: EthTransactionPreparation.name,
56
+ queueName: EthTransactionPreparation.queueName,
53
57
  data: { tx },
54
58
  opts: {
55
59
  jobId, attempts: 60, backoff: { type: 'fixed', delay: 5000 },
56
60
  },
57
61
  children: [
58
62
  {
59
- // Step 2
60
- name: Xl1TransactionSubmission.name,
61
- queueName: Xl1TransactionSubmission.queueName,
63
+ // Step 4
64
+ name: Xl1TransactionMonitor.name,
65
+ queueName: Xl1TransactionMonitor.queueName,
62
66
  data: { tx },
63
- opts: { jobId },
67
+ opts: {
68
+ jobId, attempts: 60, backoff: { type: 'fixed', delay: 5000 },
69
+ },
64
70
  children: [
65
71
  {
66
- // Step 1 (runs first as deepest child)
67
- name: Xl1TransactionPreparation.name,
68
- queueName: Xl1TransactionPreparation.queueName,
72
+ // Step 3
73
+ name: Xl1TransactionSubmissionStorage.name,
74
+ queueName: Xl1TransactionSubmissionStorage.queueName,
69
75
  data: { tx },
70
- opts: { jobId },
76
+ opts: {
77
+ jobId, attempts: 60, backoff: { type: 'fixed', delay: 5000 },
78
+ },
79
+ children: [
80
+ {
81
+ // Step 2
82
+ name: Xl1TransactionSubmission.name,
83
+ queueName: Xl1TransactionSubmission.queueName,
84
+ data: { tx },
85
+ opts: { jobId },
86
+ children: [
87
+ {
88
+ // Step 1 (runs first as deepest child)
89
+ name: Xl1TransactionPreparation.name,
90
+ queueName: Xl1TransactionPreparation.queueName,
91
+ data: { tx },
92
+ opts: {
93
+ jobId, attempts: 60, backoff: { type: 'fixed', delay: 5000 },
94
+ },
95
+ },
96
+ ],
97
+ },
98
+ ],
71
99
  },
72
100
  ],
73
101
  },
@@ -1 +1,2 @@
1
+ export * from './createEthToXl1BridgeJob.ts'
1
2
  export * from './createXl1ToEthBridgeJob.ts'
@@ -0,0 +1,57 @@
1
+ import type { Xl1ToEthQueues } from './getXl1ToEthQueues.ts'
2
+ import type {
3
+ EthTransactionMonitorJob, EthTransactionPreparationJob,
4
+ EthTransactionSubmissionJob,
5
+ Xl1ToEthBridgeParentJob,
6
+ Xl1TransactionMonitorJob, Xl1TransactionPreparationJob, Xl1TransactionSubmissionJob,
7
+ Xl1TransactionSubmissionStorageJob,
8
+ } from './workers/index.ts'
9
+
10
+ export interface StatusQueueJobs {
11
+ ethTransactionMonitorJob?: EthTransactionMonitorJob
12
+ ethTransactionPreparationJob?: EthTransactionPreparationJob
13
+ ethTransactionSubmissionJob?: EthTransactionSubmissionJob
14
+ xl1ToEthBridgeParentJob?: Xl1ToEthBridgeParentJob
15
+ xl1TransactionMonitorJob?: Xl1TransactionMonitorJob
16
+ xl1TransactionPreparationJob?: Xl1TransactionPreparationJob
17
+ xl1TransactionSubmissionJob?: Xl1TransactionSubmissionJob
18
+ xl1TransactionSubmissionStorageJob?: Xl1TransactionSubmissionStorageJob
19
+ }
20
+
21
+ /**
22
+ * Checks all the relevant status queues for a job with the given id and returns the jobs found in an object
23
+ * @param queues The status queues to check for jobs
24
+ * @param jobId The job id to look for in the queues, which is the same as the tx hash of the bridge transaction
25
+ * @returns An object containing the jobs found in the status queues corresponding to the given job id
26
+ */
27
+ export const getStatusQueueJobs = async (queues: Xl1ToEthQueues, jobId: string): Promise<StatusQueueJobs> => {
28
+ const [
29
+ ethTransactionMonitorJob,
30
+ ethTransactionPreparationJob,
31
+ ethTransactionSubmissionJob,
32
+ xl1ToEthBridgeParentJob,
33
+ xl1TransactionMonitorJob,
34
+ xl1TransactionPreparationJob,
35
+ xl1TransactionSubmissionJob,
36
+ xl1TransactionSubmissionStorageJob,
37
+ ] = await Promise.all([
38
+ queues.ethTransactionMonitor.getJob(jobId),
39
+ queues.ethTransactionPreparation.getJob(jobId),
40
+ queues.ethTransactionSubmission.getJob(jobId),
41
+ queues.xl1ToEthBridgeParent.getJob(jobId),
42
+ queues.xl1TransactionMonitor.getJob(jobId),
43
+ queues.xl1TransactionPreparation.getJob(jobId),
44
+ queues.xl1TransactionSubmission.getJob(jobId),
45
+ queues.xl1TransactionSubmissionStorage.getJob(jobId),
46
+ ])
47
+ return {
48
+ ethTransactionMonitorJob,
49
+ ethTransactionPreparationJob,
50
+ ethTransactionSubmissionJob,
51
+ xl1ToEthBridgeParentJob,
52
+ xl1TransactionMonitorJob,
53
+ xl1TransactionPreparationJob,
54
+ xl1TransactionSubmissionStorageJob,
55
+ xl1TransactionSubmissionJob,
56
+ }
57
+ }
@@ -0,0 +1,39 @@
1
+ import type { BridgeConfig } from '@xyo-network/chain-orchestration'
2
+ import { Queue } from 'bullmq'
3
+
4
+ import { getConnection } from './connection.ts'
5
+ import { prefix } from './prefix.ts'
6
+ import {
7
+ EthTransactionMonitor, EthTransactionPreparation, EthTransactionSubmission, Xl1ToEthBridgeParent, Xl1TransactionMonitor, Xl1TransactionPreparation,
8
+ Xl1TransactionSubmission,
9
+ Xl1TransactionSubmissionStorage,
10
+ } from './workers/index.ts'
11
+
12
+ export interface Xl1ToEthQueues {
13
+ ethTransactionMonitor: Queue
14
+ ethTransactionPreparation: Queue
15
+ ethTransactionSubmission: Queue
16
+ xl1ToEthBridgeParent: Queue
17
+ xl1TransactionMonitor: Queue
18
+ xl1TransactionPreparation: Queue
19
+ xl1TransactionSubmission: Queue
20
+ xl1TransactionSubmissionStorage: Queue
21
+ }
22
+
23
+ let xl1ToEthQueues: Xl1ToEthQueues | undefined
24
+
25
+ export const getXl1ToEthQueues = (config: BridgeConfig): Xl1ToEthQueues => {
26
+ if (xl1ToEthQueues) return xl1ToEthQueues
27
+ const connection = getConnection(config)
28
+ xl1ToEthQueues = {
29
+ ethTransactionMonitor: new Queue(EthTransactionMonitor.queueName, { connection, prefix }),
30
+ ethTransactionPreparation: new Queue(EthTransactionPreparation.queueName, { connection, prefix }),
31
+ ethTransactionSubmission: new Queue(EthTransactionSubmission.queueName, { connection, prefix }),
32
+ xl1ToEthBridgeParent: new Queue(Xl1ToEthBridgeParent.queueName, { connection, prefix }),
33
+ xl1TransactionMonitor: new Queue(Xl1TransactionMonitor.queueName, { connection, prefix }),
34
+ xl1TransactionPreparation: new Queue(Xl1TransactionPreparation.queueName, { connection, prefix }),
35
+ xl1TransactionSubmission: new Queue(Xl1TransactionSubmission.queueName, { connection, prefix }),
36
+ xl1TransactionSubmissionStorage: new Queue(Xl1TransactionSubmissionStorage.queueName, { connection, prefix }),
37
+ }
38
+ return xl1ToEthQueues
39
+ }
@@ -1,5 +1,8 @@
1
1
  export * from './connection.ts'
2
2
  export * from './flowProducer.ts'
3
3
  export * from './flows/index.ts'
4
+ export * from './getXl1ToEthQueueJobs.ts'
5
+ export * from './getXl1ToEthQueues.ts'
6
+ export * from './prefix.ts'
4
7
  export * from './telemetry.ts'
5
8
  export * from './workers/index.ts'
@@ -0,0 +1 @@
1
+ export const prefix = 'xl1-bridge'
@@ -0,0 +1,40 @@
1
+ import type { Job } from 'bullmq'
2
+ import { Worker } from 'bullmq'
3
+ import type { BullMQOtel } from 'bullmq-otel'
4
+ import type { Redis } from 'ioredis'
5
+
6
+ import { prefix } from '../prefix.ts'
7
+ import type { WorkerDescription } from './WorkerDescription.ts'
8
+
9
+ export type EthToXl1BridgeParentJobData = {}
10
+ export interface EthToXl1BridgeParentJobReturn { }
11
+ export type EthToXl1BridgeParentJob = Job<EthToXl1BridgeParentJobData, EthToXl1BridgeParentJobReturn>
12
+
13
+ const name = 'Bridge Ethereum to XL1'
14
+ const queueName = 'eth-to-xl1-bridge'
15
+ const createWorker = (connection: Redis, telemetry?: BullMQOtel) => {
16
+ const worker = new Worker(
17
+ queueName,
18
+ async (job: EthToXl1BridgeParentJob) => {
19
+ await job.log(`[${job.name}] start`)
20
+ // Parent job has no work other than waiting on children
21
+ await job.log(`[${job.name}] done`)
22
+ return {}
23
+ },
24
+ {
25
+ connection, telemetry, prefix,
26
+ },
27
+ )
28
+
29
+ worker.on('failed', (job, err) => {
30
+ console.error(`[${name}] Job ${job?.id} failed:`, err.message)
31
+ })
32
+
33
+ worker.on('error', (err) => {
34
+ console.error(`[${name}] Worker error:`, err)
35
+ })
36
+ }
37
+
38
+ export const EthToXl1BridgeParent: WorkerDescription = {
39
+ createWorker, name, queueName,
40
+ }
@@ -7,6 +7,7 @@ import type { BullMQOtel } from 'bullmq-otel'
7
7
  import type { Redis } from 'ioredis'
8
8
 
9
9
  import type { IBridgeServiceCollection } from '../../services/index.ts'
10
+ import { prefix } from '../prefix.ts'
10
11
  import type { WorkerDescription } from './WorkerDescription.ts'
11
12
 
12
13
  export type EthTransactionMonitorJobData = { tx: SignedHydratedTransaction }
@@ -15,6 +16,7 @@ export interface EthTransactionMonitorJobReturn {
15
16
  blockNumber: number
16
17
  submissionHash: string
17
18
  }
19
+ export type EthTransactionMonitorJob = Job<EthTransactionMonitorJobData, EthTransactionMonitorJobReturn>
18
20
 
19
21
  const name = 'Monitor Submitted ETH Transaction'
20
22
  const queueName = 'eth-tx-monitor'
@@ -24,7 +26,7 @@ const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBri
24
26
 
25
27
  const worker = new Worker(
26
28
  queueName,
27
- async (job: Job<EthTransactionMonitorJobData, EthTransactionMonitorJobReturn>) => {
29
+ async (job: EthTransactionMonitorJob) => {
28
30
  const { tx } = job.data
29
31
  const hash = await PayloadBuilder.hash(tx[0])
30
32
  const state = assertEx(await stateMap.get(hash), () => 'State not found')
@@ -38,7 +40,9 @@ const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBri
38
40
  blockHash, blockNumber, submissionHash,
39
41
  }
40
42
  },
41
- { connection, telemetry },
43
+ {
44
+ connection, telemetry, prefix,
45
+ },
42
46
  )
43
47
 
44
48
  worker.on('failed', (job, err) => {
@@ -10,11 +10,13 @@ import type { Redis } from 'ioredis'
10
10
  import type { IBridgeServiceCollection } from '../../services/index.ts'
11
11
  import {
12
12
  validateSufficientLiquiditySourceAllowance, validateSufficientLiquiditySourceBalance, validateSufficientRunnerEthBalanceForGas,
13
- } from './util/index.ts'
13
+ } from '../../validation/index.ts'
14
+ import { prefix } from '../prefix.ts'
14
15
  import type { WorkerDescription } from './WorkerDescription.ts'
15
16
 
16
- export type EthTransactionPrepareJobData = { tx: SignedHydratedTransaction }
17
- export type EthTransactionPrepareJobReturn = Record<string, never>
17
+ export type EthTransactionPreparationJobData = { tx: SignedHydratedTransaction }
18
+ export type EthTransactionPreparationJobReturn = Record<string, never>
19
+ export type EthTransactionPreparationJob = Job<EthTransactionPreparationJobData, EthTransactionPreparationJobReturn>
18
20
 
19
21
  const name = 'Prepare ETH Transaction'
20
22
  const queueName = 'eth-tx-prepare'
@@ -27,7 +29,7 @@ export const createWorker = (connection: Redis, telemetry?: BullMQOtel, services
27
29
 
28
30
  const worker = new Worker(
29
31
  queueName,
30
- async (job: Job<EthTransactionPrepareJobData, EthTransactionPrepareJobReturn>) => {
32
+ async (job: EthTransactionPreparationJob) => {
31
33
  const { tx } = job.data
32
34
  const hash = await PayloadBuilder.hash(tx[0])
33
35
  await job.log(`[${hash}] preparing ETH transaction`)
@@ -60,7 +62,9 @@ export const createWorker = (connection: Redis, telemetry?: BullMQOtel, services
60
62
  await job.log(`[${hash}] prepared ETH transaction`)
61
63
  return {}
62
64
  },
63
- { connection, telemetry },
65
+ {
66
+ connection, telemetry, prefix,
67
+ },
64
68
  )
65
69
 
66
70
  worker.on('failed', (job, err) => {
@@ -7,14 +7,15 @@ import type { BullMQOtel } from 'bullmq-otel'
7
7
  import type { Redis } from 'ioredis'
8
8
 
9
9
  import type { EthTxState, IBridgeServiceCollection } from '../../services/index.ts'
10
+ import { prefix } from '../prefix.ts'
10
11
  import { submitEthTransaction } from './util/index.ts'
11
12
  import type { WorkerDescription } from './WorkerDescription.ts'
12
13
 
13
14
  export type EthTransactionSubmissionJobData = { tx: SignedHydratedTransaction }
14
-
15
15
  export interface EthTransactionSubmissionJobReturn {
16
16
  submissionHash: Required<EthTxState>['submissionHash']
17
17
  }
18
+ export type EthTransactionSubmissionJob = Job<EthTransactionSubmissionJobData, EthTransactionSubmissionJobReturn>
18
19
 
19
20
  const name = 'Submit ETH Transaction'
20
21
  const queueName = 'eth-tx-submit'
@@ -26,7 +27,7 @@ const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBri
26
27
 
27
28
  const worker = new Worker(
28
29
  queueName,
29
- async (job: Job<EthTransactionSubmissionJobData, EthTransactionSubmissionJobReturn>) => {
30
+ async (job: EthTransactionSubmissionJob) => {
30
31
  const { tx } = job.data
31
32
  const hash = await PayloadBuilder.hash(tx[0])
32
33
  const state = assertEx(await stateMap.get(hash), () => `[${hash}] state not found`)
@@ -40,21 +41,12 @@ const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBri
40
41
 
41
42
  // Submit the transaction to the Ethereum network
42
43
  await job.log(`[${hash}] Submitting ETH tx`)
43
-
44
44
  const submissionHash = assertEx(await submitEthTransaction(tx, bridgeableToken, bridge, wallet), () => `[${hash}] submissionHash not found in receipt`)
45
-
46
45
  await job.log(`[${hash}] Submitted ETH tx and received submission response hash ${submissionHash}`)
47
-
48
- // Store the submission hash in the state
49
- await job.log(`[${hash}] Storing ETH submissionHash`)
50
- state.submissionHash = submissionHash
51
- await stateMap.set(hash, state)
52
- await job.log(`[${hash}] Stored ETH submissionHash`)
53
-
54
46
  return { submissionHash }
55
47
  },
56
48
  {
57
- connection, telemetry, concurrency: 1,
49
+ connection, telemetry, concurrency: 1, prefix,
58
50
  },
59
51
  )
60
52