@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.
- package/dist/node/config/getTestGateway.d.ts +4 -0
- package/dist/node/config/getTestGateway.d.ts.map +1 -0
- package/dist/node/config/index.d.ts +1 -1
- package/dist/node/config/index.d.ts.map +1 -1
- package/dist/node/index.mjs +700 -506
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/modules/index.d.ts +0 -1
- package/dist/node/modules/index.d.ts.map +1 -1
- package/dist/node/queue/flowProducer.d.ts.map +1 -1
- package/dist/node/queue/flows/createEthToXl1BridgeJob.d.ts +10 -0
- package/dist/node/queue/flows/createEthToXl1BridgeJob.d.ts.map +1 -0
- package/dist/node/queue/flows/createXl1ToEthBridgeJob.d.ts.map +1 -1
- package/dist/node/queue/flows/index.d.ts +1 -0
- package/dist/node/queue/flows/index.d.ts.map +1 -1
- package/dist/node/queue/getXl1ToEthQueueJobs.d.ts +20 -0
- package/dist/node/queue/getXl1ToEthQueueJobs.d.ts.map +1 -0
- package/dist/node/queue/getXl1ToEthQueues.d.ts +14 -0
- package/dist/node/queue/getXl1ToEthQueues.d.ts.map +1 -0
- package/dist/node/queue/index.d.ts +3 -0
- package/dist/node/queue/index.d.ts.map +1 -1
- package/dist/node/queue/prefix.d.ts +2 -0
- package/dist/node/queue/prefix.d.ts.map +1 -0
- package/dist/node/queue/workers/EthToXl1BridgeParent.d.ts +8 -0
- package/dist/node/queue/workers/EthToXl1BridgeParent.d.ts.map +1 -0
- package/dist/node/queue/workers/EthTransactionMonitor.d.ts +2 -0
- package/dist/node/queue/workers/EthTransactionMonitor.d.ts.map +1 -1
- package/dist/node/queue/workers/EthTransactionPreparation.d.ts +4 -2
- package/dist/node/queue/workers/EthTransactionPreparation.d.ts.map +1 -1
- package/dist/node/queue/workers/EthTransactionSubmission.d.ts +2 -0
- package/dist/node/queue/workers/EthTransactionSubmission.d.ts.map +1 -1
- package/dist/node/queue/workers/EthTransactionSubmissionStorage.d.ts +13 -0
- package/dist/node/queue/workers/EthTransactionSubmissionStorage.d.ts.map +1 -0
- package/dist/node/queue/workers/Xl1ToEthBridgeParent.d.ts +6 -1
- package/dist/node/queue/workers/Xl1ToEthBridgeParent.d.ts.map +1 -1
- package/dist/node/queue/workers/Xl1TransactionMonitor.d.ts +4 -0
- package/dist/node/queue/workers/Xl1TransactionMonitor.d.ts.map +1 -1
- package/dist/node/queue/workers/Xl1TransactionPreparation.d.ts +2 -0
- package/dist/node/queue/workers/Xl1TransactionPreparation.d.ts.map +1 -1
- package/dist/node/queue/workers/Xl1TransactionSubmission.d.ts +2 -0
- package/dist/node/queue/workers/Xl1TransactionSubmission.d.ts.map +1 -1
- package/dist/node/queue/workers/Xl1TransactionSubmissionStorage.d.ts +13 -0
- package/dist/node/queue/workers/Xl1TransactionSubmissionStorage.d.ts.map +1 -0
- package/dist/node/queue/workers/createWorkers.d.ts.map +1 -1
- package/dist/node/queue/workers/index.d.ts +3 -0
- package/dist/node/queue/workers/index.d.ts.map +1 -1
- package/dist/node/queue/workers/util/index.d.ts +0 -3
- package/dist/node/queue/workers/util/index.d.ts.map +1 -1
- package/dist/node/server/index.d.ts +2 -0
- package/dist/node/server/index.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeToRemote.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/bridgeToRemoteStatus.d.ts.map +1 -1
- package/dist/node/server/server.d.ts.map +1 -1
- package/dist/node/services/IBridgeServiceCollection.d.ts +1 -1
- package/dist/node/services/IBridgeServiceCollection.d.ts.map +1 -1
- package/dist/node/services/TxState.d.ts +0 -7
- package/dist/node/services/TxState.d.ts.map +1 -1
- package/dist/node/util/index.d.ts +0 -3
- package/dist/node/util/index.d.ts.map +1 -1
- package/dist/node/validation/AsyncLogger.d.ts.map +1 -0
- package/dist/node/validation/index.d.ts +7 -0
- package/dist/node/validation/index.d.ts.map +1 -0
- package/dist/node/validation/validateBridgeEstimate.d.ts.map +1 -0
- package/dist/node/validation/validateBridgeEstimateExact.d.ts.map +1 -0
- package/dist/node/validation/validateBridgeTransaction.d.ts.map +1 -0
- package/dist/node/validation/validateSufficientLiquiditySourceAllowance.d.ts.map +1 -0
- package/dist/node/validation/validateSufficientLiquiditySourceBalance.d.ts.map +1 -0
- package/dist/node/validation/validateSufficientRunnerEthBalanceForGas.d.ts.map +1 -0
- package/dist/node/validation/validateSufficientXL1SourceAddressBalance.d.ts +15 -0
- package/dist/node/validation/validateSufficientXL1SourceAddressBalance.d.ts.map +1 -0
- package/package.json +31 -31
- package/src/config/getTestGateway.ts +24 -0
- package/src/config/index.ts +1 -1
- package/src/modules/index.ts +0 -1
- package/src/queue/flowProducer.ts +5 -1
- package/src/queue/flows/createEthToXl1BridgeJob.ts +71 -0
- package/src/queue/flows/createXl1ToEthBridgeJob.ts +48 -20
- package/src/queue/flows/index.ts +1 -0
- package/src/queue/getXl1ToEthQueueJobs.ts +57 -0
- package/src/queue/getXl1ToEthQueues.ts +39 -0
- package/src/queue/index.ts +3 -0
- package/src/queue/prefix.ts +1 -0
- package/src/queue/workers/EthToXl1BridgeParent.ts +40 -0
- package/src/queue/workers/EthTransactionMonitor.ts +6 -2
- package/src/queue/workers/EthTransactionPreparation.ts +9 -5
- package/src/queue/workers/EthTransactionSubmission.ts +4 -12
- package/src/queue/workers/EthTransactionSubmissionStorage.ts +76 -0
- package/src/queue/workers/Xl1ToEthBridgeParent.ts +8 -3
- package/src/queue/workers/Xl1TransactionMonitor.ts +13 -9
- package/src/queue/workers/Xl1TransactionPreparation.ts +6 -2
- package/src/queue/workers/Xl1TransactionSubmission.ts +8 -9
- package/src/queue/workers/Xl1TransactionSubmissionStorage.ts +77 -0
- package/src/queue/workers/createWorkers.ts +10 -4
- package/src/queue/workers/index.ts +3 -0
- package/src/queue/workers/util/index.ts +0 -3
- package/src/server/index.ts +3 -2
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemote.ts +11 -1
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteStatus.ts +27 -101
- package/src/server/server.ts +1 -0
- package/src/services/IBridgeServiceCollection.ts +1 -1
- package/src/services/TxState.ts +0 -18
- package/src/util/index.ts +0 -3
- package/src/validation/index.ts +6 -0
- package/src/{util → validation}/validateBridgeEstimate.ts +1 -1
- package/src/{util → validation}/validateBridgeEstimateExact.ts +1 -1
- package/src/{util → validation}/validateBridgeTransaction.ts +1 -2
- package/src/validation/validateSufficientXL1SourceAddressBalance.ts +39 -0
- package/dist/node/config/getGateway.d.ts +0 -4
- package/dist/node/config/getGateway.d.ts.map +0 -1
- package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/XL1TransactionCompletionMonitorSentinel.d.ts +0 -60
- package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/XL1TransactionCompletionMonitorSentinel.d.ts.map +0 -1
- package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/index.d.ts +0 -2
- package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/index.d.ts.map +0 -1
- package/dist/node/queue/workers/util/AsyncLogger.d.ts.map +0 -1
- package/dist/node/queue/workers/util/validateSufficientLiquiditySourceAllowance.d.ts.map +0 -1
- package/dist/node/queue/workers/util/validateSufficientLiquiditySourceBalance.d.ts.map +0 -1
- package/dist/node/queue/workers/util/validateSufficientRunnerEthBalanceForGas.d.ts.map +0 -1
- package/dist/node/util/validateBridgeEstimate.d.ts.map +0 -1
- package/dist/node/util/validateBridgeEstimateExact.d.ts.map +0 -1
- package/dist/node/util/validateBridgeTransaction.d.ts.map +0 -1
- package/src/config/getGateway.ts +0 -23
- package/src/modules/XL1TransactionCompletionMonitorSentinel/XL1TransactionCompletionMonitorSentinel.ts +0 -165
- package/src/modules/XL1TransactionCompletionMonitorSentinel/index.ts +0 -1
- /package/dist/node/{queue/workers/util → validation}/AsyncLogger.d.ts +0 -0
- /package/dist/node/{util → validation}/validateBridgeEstimate.d.ts +0 -0
- /package/dist/node/{util → validation}/validateBridgeEstimateExact.d.ts +0 -0
- /package/dist/node/{util → validation}/validateBridgeTransaction.d.ts +0 -0
- /package/dist/node/{queue/workers/util → validation}/validateSufficientLiquiditySourceAllowance.d.ts +0 -0
- /package/dist/node/{queue/workers/util → validation}/validateSufficientLiquiditySourceBalance.d.ts +0 -0
- /package/dist/node/{queue/workers/util → validation}/validateSufficientRunnerEthBalanceForGas.d.ts +0 -0
- /package/src/{queue/workers/util → validation}/AsyncLogger.ts +0 -0
- /package/src/{queue/workers/util → validation}/validateSufficientLiquiditySourceAllowance.ts +0 -0
- /package/src/{queue/workers/util → validation}/validateSufficientLiquiditySourceBalance.ts +0 -0
- /package/src/{queue/workers/util → validation}/validateSufficientRunnerEthBalanceForGas.ts +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { assertEx, isDefined } from '@xylabs/sdk-js'
|
|
2
|
+
import { PayloadBuilder } from '@xyo-network/sdk-js'
|
|
3
|
+
import type { SignedHydratedTransaction } from '@xyo-network/xl1-sdk'
|
|
4
|
+
import type { Job } from 'bullmq'
|
|
5
|
+
import { Worker } from 'bullmq'
|
|
6
|
+
import type { BullMQOtel } from 'bullmq-otel'
|
|
7
|
+
import type { Redis } from 'ioredis'
|
|
8
|
+
|
|
9
|
+
import type { EthTxState, IBridgeServiceCollection } from '../../services/index.ts'
|
|
10
|
+
import { prefix } from '../prefix.ts'
|
|
11
|
+
import type { EthTransactionSubmissionJobReturn } from './EthTransactionSubmission.ts'
|
|
12
|
+
import { EthTransactionSubmission } from './EthTransactionSubmission.ts'
|
|
13
|
+
import type { WorkerDescription } from './WorkerDescription.ts'
|
|
14
|
+
|
|
15
|
+
export type EthTransactionSubmissionStorageJobData = { tx: SignedHydratedTransaction }
|
|
16
|
+
export interface EthTransactionSubmissionStorageJobReturn {
|
|
17
|
+
submissionHash: Required<EthTxState>['submissionHash']
|
|
18
|
+
}
|
|
19
|
+
export type EthTransactionSubmissionStorageJob = Job<EthTransactionSubmissionStorageJobData, EthTransactionSubmissionStorageJobReturn>
|
|
20
|
+
|
|
21
|
+
const name = 'Store ETH Transaction Submission'
|
|
22
|
+
const queueName = 'eth-tx-store-submission'
|
|
23
|
+
|
|
24
|
+
const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBridgeServiceCollection) => {
|
|
25
|
+
const stateMap = assertEx(services?.ethTxStateMap, () => 'ethTxStateMap service not provided')
|
|
26
|
+
|
|
27
|
+
const worker = new Worker(
|
|
28
|
+
queueName,
|
|
29
|
+
async (job: EthTransactionSubmissionStorageJob) => {
|
|
30
|
+
const { tx } = job.data
|
|
31
|
+
// Get the hash of the transaction
|
|
32
|
+
const hash = await PayloadBuilder.hash(tx[0])
|
|
33
|
+
|
|
34
|
+
// Get the state of the transaction
|
|
35
|
+
const state = assertEx(await stateMap.get(hash), () => `[${hash}] state not found`)
|
|
36
|
+
|
|
37
|
+
// Idempotency check against re-store
|
|
38
|
+
const { submissionHash: existingSubmissionHash } = state
|
|
39
|
+
if (isDefined(existingSubmissionHash)) {
|
|
40
|
+
await job.log(`[${hash}] submissionHash already stored as ${existingSubmissionHash}`)
|
|
41
|
+
return { submissionHash: existingSubmissionHash }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// In a Flow, this job should be the PARENT and the submit job should be a CHILD.
|
|
45
|
+
// That lets us read the child job’s return value(s) here.
|
|
46
|
+
const childrenValues = await job.getChildrenValues()
|
|
47
|
+
const jobKey = `${prefix}:${EthTransactionSubmission.queueName}:${hash}`
|
|
48
|
+
const childValues = childrenValues?.[jobKey] as EthTransactionSubmissionJobReturn | undefined
|
|
49
|
+
const submissionHash = childValues?.submissionHash
|
|
50
|
+
|
|
51
|
+
const resolvedSubmissionHash = assertEx(submissionHash, () => `[${hash}] child submissionHash not found in children values`)
|
|
52
|
+
|
|
53
|
+
// Store the submission hash in the state
|
|
54
|
+
await job.log(`[${hash}] Storing ETH submissionHash`)
|
|
55
|
+
state.submissionHash = resolvedSubmissionHash
|
|
56
|
+
await stateMap.set(hash, state)
|
|
57
|
+
await job.log(`[${hash}] Stored ETH submissionHash`)
|
|
58
|
+
return { submissionHash: resolvedSubmissionHash }
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
connection, telemetry, prefix,
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
worker.on('failed', (job, err) => {
|
|
66
|
+
console.error(`[${name}] Job ${job?.id} failed:`, err.message)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
worker.on('error', (err) => {
|
|
70
|
+
console.error(`[${name}] Worker error:`, err)
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const EthTransactionSubmissionStorage: WorkerDescription = {
|
|
75
|
+
createWorker, name, queueName,
|
|
76
|
+
}
|
|
@@ -1,25 +1,30 @@
|
|
|
1
|
+
import type { SignedHydratedTransaction } from '@xyo-network/xl1-sdk'
|
|
1
2
|
import type { Job } from 'bullmq'
|
|
2
3
|
import { Worker } from 'bullmq'
|
|
3
4
|
import type { BullMQOtel } from 'bullmq-otel'
|
|
4
5
|
import type { Redis } from 'ioredis'
|
|
5
6
|
|
|
7
|
+
import { prefix } from '../prefix.ts'
|
|
6
8
|
import type { WorkerDescription } from './WorkerDescription.ts'
|
|
7
9
|
|
|
8
|
-
export type Xl1ToEthBridgeParentJobData = {}
|
|
10
|
+
export type Xl1ToEthBridgeParentJobData = { tx: SignedHydratedTransaction }
|
|
9
11
|
export interface Xl1ToEthBridgeParentJobReturn { }
|
|
12
|
+
export type Xl1ToEthBridgeParentJob = Job<Xl1ToEthBridgeParentJobData, Xl1ToEthBridgeParentJobReturn>
|
|
10
13
|
|
|
11
14
|
const name = 'Bridge XL1 to Ethereum'
|
|
12
15
|
const queueName = 'xl1-to-eth-bridge'
|
|
13
16
|
const createWorker = (connection: Redis, telemetry?: BullMQOtel) => {
|
|
14
17
|
const worker = new Worker(
|
|
15
18
|
queueName,
|
|
16
|
-
async (job:
|
|
19
|
+
async (job: Xl1ToEthBridgeParentJob) => {
|
|
17
20
|
await job.log(`[${job.name}] start`)
|
|
18
21
|
// Parent job has no work other than waiting on children
|
|
19
22
|
await job.log(`[${job.name}] done`)
|
|
20
23
|
return {}
|
|
21
24
|
},
|
|
22
|
-
{
|
|
25
|
+
{
|
|
26
|
+
connection, telemetry, prefix,
|
|
27
|
+
},
|
|
23
28
|
)
|
|
24
29
|
|
|
25
30
|
worker.on('failed', (job, err) => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BrandedHash } from '@xylabs/sdk-js'
|
|
1
2
|
import {
|
|
2
3
|
assertEx, isDefined, isNull,
|
|
3
4
|
} from '@xylabs/sdk-js'
|
|
@@ -9,42 +10,43 @@ import type { BullMQOtel } from 'bullmq-otel'
|
|
|
9
10
|
import type { Redis } from 'ioredis'
|
|
10
11
|
|
|
11
12
|
import type { IBridgeServiceCollection } from '../../services/index.ts'
|
|
13
|
+
import { prefix } from '../prefix.ts'
|
|
12
14
|
import type { WorkerDescription } from './WorkerDescription.ts'
|
|
13
15
|
|
|
14
16
|
export type Xl1TransactionMonitorJobData = { tx: SignedHydratedTransaction }
|
|
15
|
-
|
|
16
17
|
export interface Xl1TransactionMonitorJobReturn {
|
|
18
|
+
submissionHash: BrandedHash
|
|
17
19
|
}
|
|
20
|
+
export type Xl1TransactionMonitorJob = Job<Xl1TransactionMonitorJobData, Xl1TransactionMonitorJobReturn>
|
|
18
21
|
|
|
19
22
|
const name = 'Monitor Submitted XL1 Transaction'
|
|
20
23
|
const queueName = 'xl1-tx-monitor'
|
|
21
24
|
const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBridgeServiceCollection) => {
|
|
22
25
|
const gateway = assertEx(services?.gateway, () => 'gateway service not provided')
|
|
23
26
|
const stateMap = assertEx(services?.xl1TxStateMap, () => 'xl1TxStateMap service not provided')
|
|
27
|
+
const viewer = assertEx(gateway.connection.viewer, () => 'viewer not defined on gateway')
|
|
24
28
|
|
|
25
29
|
const worker = new Worker(
|
|
26
30
|
queueName,
|
|
27
|
-
async (job:
|
|
31
|
+
async (job: Xl1TransactionMonitorJob) => {
|
|
28
32
|
const { tx } = job.data
|
|
29
33
|
// Get the hash of the transaction
|
|
30
34
|
const hash = await PayloadBuilder.hash(tx[0])
|
|
31
35
|
// Get the state of the transaction
|
|
32
|
-
const viewer = assertEx(gateway.connection.viewer, () => `[${hash}] viewer not defined on gateway`)
|
|
33
36
|
const state = assertEx(await stateMap.get(hash), () => `[${hash}] state not found`)
|
|
34
|
-
const submissionHash = assertEx(state
|
|
37
|
+
const submissionHash = assertEx(state.submissionHash, () => `[${hash}] submissionHash not found`)
|
|
35
38
|
|
|
36
39
|
// Check for transaction inclusion on chain
|
|
37
40
|
await job.log(`[${hash}] Checking for XL1 transaction inclusion on chain`)
|
|
38
|
-
const foundTx = await viewer.
|
|
41
|
+
const foundTx = await viewer.transaction.byHash(submissionHash)
|
|
39
42
|
// const foundTx = await viewer.transaction.byHash(submissionHash)
|
|
40
43
|
|
|
41
44
|
// Transaction found on chain
|
|
42
45
|
if (isDefined(foundTx) && !isNull(foundTx)) {
|
|
43
46
|
await job.log(`[${hash}] Found transaction on chain`)
|
|
44
47
|
// Store the block hash
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return {}
|
|
48
|
+
const submissionHash = await PayloadBuilder.hash(foundTx[0])
|
|
49
|
+
return { submissionHash }
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
// Check for transaction expiration
|
|
@@ -61,7 +63,9 @@ const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBri
|
|
|
61
63
|
await job.log(`[${hash}] Transaction not yet included, retrying later`)
|
|
62
64
|
throw new Error(`[${hash}] Transaction not yet included`)
|
|
63
65
|
},
|
|
64
|
-
{
|
|
66
|
+
{
|
|
67
|
+
connection, telemetry, prefix,
|
|
68
|
+
},
|
|
65
69
|
)
|
|
66
70
|
|
|
67
71
|
worker.on('failed', (job, err) => {
|
|
@@ -7,10 +7,12 @@ 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 Xl1TransactionPreparationJobData = { tx: SignedHydratedTransaction }
|
|
13
14
|
export interface Xl1TransactionPreparationJobReturn { preparedTx: SignedHydratedTransaction }
|
|
15
|
+
export type Xl1TransactionPreparationJob = Job<Xl1TransactionPreparationJobData, Xl1TransactionPreparationJobReturn>
|
|
14
16
|
|
|
15
17
|
const name = 'Prepare XL1 Transaction'
|
|
16
18
|
const queueName = 'xl1-tx-prepare'
|
|
@@ -19,7 +21,7 @@ const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBri
|
|
|
19
21
|
|
|
20
22
|
const worker = new Worker(
|
|
21
23
|
queueName,
|
|
22
|
-
async (job:
|
|
24
|
+
async (job: Xl1TransactionPreparationJob) => {
|
|
23
25
|
const { tx } = job.data
|
|
24
26
|
const hash = await PayloadBuilder.hash(tx[0])
|
|
25
27
|
await job.log(`[${hash}] preparing XL1 transaction`)
|
|
@@ -30,7 +32,9 @@ const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBri
|
|
|
30
32
|
await job.log(`[${hash}] prepared XL1 transaction`)
|
|
31
33
|
return { preparedTx }
|
|
32
34
|
},
|
|
33
|
-
{
|
|
35
|
+
{
|
|
36
|
+
connection, telemetry, prefix,
|
|
37
|
+
},
|
|
34
38
|
)
|
|
35
39
|
|
|
36
40
|
worker.on('failed', (job, err) => {
|
|
@@ -7,24 +7,26 @@ import type { BullMQOtel } from 'bullmq-otel'
|
|
|
7
7
|
import type { Redis } from 'ioredis'
|
|
8
8
|
|
|
9
9
|
import type { IBridgeServiceCollection, Xl1TxState } from '../../services/index.ts'
|
|
10
|
+
import { prefix } from '../prefix.ts'
|
|
10
11
|
import { submitXl1Transaction } from './util/index.ts'
|
|
11
12
|
import type { WorkerDescription } from './WorkerDescription.ts'
|
|
12
13
|
|
|
13
14
|
export type Xl1TransactionSubmissionJobData = { tx: SignedHydratedTransaction }
|
|
14
|
-
|
|
15
15
|
export interface Xl1TransactionSubmissionJobReturn {
|
|
16
16
|
submissionHash: Required<Xl1TxState>['submissionHash']
|
|
17
17
|
}
|
|
18
|
+
export type Xl1TransactionSubmissionJob = Job<Xl1TransactionSubmissionJobData, Xl1TransactionSubmissionJobReturn>
|
|
18
19
|
|
|
19
20
|
const name = 'Submit XL1 Transaction'
|
|
20
21
|
const queueName = 'xl1-tx-submit'
|
|
22
|
+
|
|
21
23
|
const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBridgeServiceCollection) => {
|
|
22
24
|
const gateway = assertEx(services?.gateway, () => 'gateway service not provided')
|
|
23
25
|
const stateMap = assertEx(services?.xl1TxStateMap, () => 'xl1TxStateMap service not provided')
|
|
24
26
|
|
|
25
27
|
const worker = new Worker(
|
|
26
28
|
queueName,
|
|
27
|
-
async (job:
|
|
29
|
+
async (job: Xl1TransactionSubmissionJob) => {
|
|
28
30
|
const { tx } = job.data
|
|
29
31
|
// Get the hash of the transaction
|
|
30
32
|
const hash = await PayloadBuilder.hash(tx[0])
|
|
@@ -47,15 +49,12 @@ const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBri
|
|
|
47
49
|
// assertEx(submissionHash === hash, () => `[${hash}] Submitted transaction hash ${submissionHash} does not match expected hash`)
|
|
48
50
|
await job.log(`[${hash}] Submitted XL1 tx`)
|
|
49
51
|
|
|
50
|
-
//
|
|
51
|
-
await job.log(`[${hash}] Storing XL1 submissionHash`)
|
|
52
|
-
state.submissionHash = submissionHash
|
|
53
|
-
await stateMap.set(hash, state)
|
|
54
|
-
await job.log(`[${hash}] Stored XL1 submissionHash`)
|
|
55
|
-
|
|
52
|
+
// This worker intentionally does NOT store state as subsequent steps will do that.
|
|
56
53
|
return { submissionHash }
|
|
57
54
|
},
|
|
58
|
-
{
|
|
55
|
+
{
|
|
56
|
+
connection, telemetry, prefix,
|
|
57
|
+
},
|
|
59
58
|
)
|
|
60
59
|
|
|
61
60
|
worker.on('failed', (job, err) => {
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { assertEx, isDefined } from '@xylabs/sdk-js'
|
|
2
|
+
import { PayloadBuilder } from '@xyo-network/sdk-js'
|
|
3
|
+
import { type SignedHydratedTransaction } from '@xyo-network/xl1-sdk'
|
|
4
|
+
import type { Job } from 'bullmq'
|
|
5
|
+
import { Worker } from 'bullmq'
|
|
6
|
+
import type { BullMQOtel } from 'bullmq-otel'
|
|
7
|
+
import type { Redis } from 'ioredis'
|
|
8
|
+
|
|
9
|
+
import type { IBridgeServiceCollection, Xl1TxState } from '../../services/index.ts'
|
|
10
|
+
import { prefix } from '../prefix.ts'
|
|
11
|
+
import type { WorkerDescription } from './WorkerDescription.ts'
|
|
12
|
+
import type { Xl1TransactionSubmissionJobReturn } from './Xl1TransactionSubmission.ts'
|
|
13
|
+
import { Xl1TransactionSubmission } from './Xl1TransactionSubmission.ts'
|
|
14
|
+
|
|
15
|
+
export type Xl1TransactionSubmissionStorageJobData = { tx: SignedHydratedTransaction }
|
|
16
|
+
export interface Xl1TransactionSubmissionStorageJobReturn {
|
|
17
|
+
submissionHash: Required<Xl1TxState>['submissionHash']
|
|
18
|
+
}
|
|
19
|
+
export type Xl1TransactionSubmissionStorageJob = Job<Xl1TransactionSubmissionStorageJobData, Xl1TransactionSubmissionStorageJobReturn>
|
|
20
|
+
|
|
21
|
+
const name = 'Store XL1 Transaction Submission'
|
|
22
|
+
const queueName = 'xl1-tx-store-submission'
|
|
23
|
+
|
|
24
|
+
const createWorker = (connection: Redis, telemetry?: BullMQOtel, services?: IBridgeServiceCollection) => {
|
|
25
|
+
const stateMap = assertEx(services?.xl1TxStateMap, () => 'xl1TxStateMap service not provided')
|
|
26
|
+
|
|
27
|
+
const worker = new Worker(
|
|
28
|
+
queueName,
|
|
29
|
+
async (job: Xl1TransactionSubmissionStorageJob) => {
|
|
30
|
+
const { tx } = job.data
|
|
31
|
+
// Get the hash of the transaction
|
|
32
|
+
const hash = await PayloadBuilder.hash(tx[0])
|
|
33
|
+
|
|
34
|
+
// Get the state of the transaction
|
|
35
|
+
const state = assertEx(await stateMap.get(hash), () => `[${hash}] state not found`)
|
|
36
|
+
|
|
37
|
+
// Idempotency check against re-store
|
|
38
|
+
const { submissionHash: existingSubmissionHash } = state
|
|
39
|
+
if (isDefined(existingSubmissionHash)) {
|
|
40
|
+
await job.log(`[${hash}] submissionHash already stored as ${existingSubmissionHash}`)
|
|
41
|
+
return { submissionHash: existingSubmissionHash }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// In a Flow, this job should be the PARENT and the submit job should be a CHILD.
|
|
45
|
+
// That lets us read the child job’s return value(s) here.
|
|
46
|
+
const childrenValues = await job.getChildrenValues()
|
|
47
|
+
const jobKey = `${prefix}:${Xl1TransactionSubmission.queueName}:${hash}`
|
|
48
|
+
const childValues = childrenValues?.[jobKey] as Xl1TransactionSubmissionJobReturn | undefined
|
|
49
|
+
const submissionHash = childValues?.submissionHash
|
|
50
|
+
|
|
51
|
+
const resolvedSubmissionHash = assertEx(submissionHash, () => `[${hash}] child submissionHash not found in children values`)
|
|
52
|
+
|
|
53
|
+
// Store the submission hash in the state
|
|
54
|
+
await job.log(`[${hash}] Storing XL1 submissionHash`)
|
|
55
|
+
state.submissionHash = resolvedSubmissionHash
|
|
56
|
+
await stateMap.set(hash, state)
|
|
57
|
+
await job.log(`[${hash}] Stored XL1 submissionHash`)
|
|
58
|
+
|
|
59
|
+
return { submissionHash: resolvedSubmissionHash }
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
connection, telemetry, prefix,
|
|
63
|
+
},
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
worker.on('failed', (job, err) => {
|
|
67
|
+
console.error(`[${name}] Job ${job?.id} failed:`, err.message)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
worker.on('error', (err) => {
|
|
71
|
+
console.error(`[${name}] Worker error:`, err)
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const Xl1TransactionSubmissionStorage: WorkerDescription = {
|
|
76
|
+
createWorker, name, queueName,
|
|
77
|
+
}
|
|
@@ -6,18 +6,24 @@ import {
|
|
|
6
6
|
EthTransactionMonitor,
|
|
7
7
|
EthTransactionPreparation,
|
|
8
8
|
EthTransactionSubmission,
|
|
9
|
+
EthTransactionSubmissionStorage,
|
|
9
10
|
Xl1ToEthBridgeParent,
|
|
10
11
|
Xl1TransactionMonitor,
|
|
11
12
|
Xl1TransactionPreparation,
|
|
12
13
|
Xl1TransactionSubmission,
|
|
14
|
+
Xl1TransactionSubmissionStorage,
|
|
13
15
|
} from './index.ts'
|
|
14
16
|
|
|
15
17
|
export const createWorkers = (connection: Redis, telemetry: BullMQOtel, services: IBridgeServiceCollection) => {
|
|
18
|
+
// TODO: Uncomment when EthToXl1 flow is ready
|
|
19
|
+
// EthToXl1BridgeParent.createWorker(connection, telemetry)
|
|
20
|
+
EthTransactionMonitor.createWorker(connection, telemetry, services)
|
|
21
|
+
EthTransactionPreparation.createWorker(connection, telemetry, services)
|
|
22
|
+
EthTransactionSubmission.createWorker(connection, telemetry, services)
|
|
23
|
+
EthTransactionSubmissionStorage.createWorker(connection, telemetry, services)
|
|
16
24
|
Xl1ToEthBridgeParent.createWorker(connection, telemetry)
|
|
25
|
+
Xl1TransactionMonitor.createWorker(connection, telemetry, services)
|
|
17
26
|
Xl1TransactionPreparation.createWorker(connection, telemetry, services)
|
|
18
27
|
Xl1TransactionSubmission.createWorker(connection, telemetry, services)
|
|
19
|
-
|
|
20
|
-
EthTransactionPreparation.createWorker(connection, telemetry, services)
|
|
21
|
-
EthTransactionSubmission.createWorker(connection, telemetry, services)
|
|
22
|
-
EthTransactionMonitor.createWorker(connection, telemetry, services)
|
|
28
|
+
Xl1TransactionSubmissionStorage.createWorker(connection, telemetry, services)
|
|
23
29
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export * from './createWorkers.ts'
|
|
2
|
+
export * from './EthToXl1BridgeParent.ts'
|
|
2
3
|
export * from './EthTransactionMonitor.ts'
|
|
3
4
|
export * from './EthTransactionPreparation.ts'
|
|
4
5
|
export * from './EthTransactionSubmission.ts'
|
|
6
|
+
export * from './EthTransactionSubmissionStorage.ts'
|
|
5
7
|
export * from './Xl1ToEthBridgeParent.ts'
|
|
6
8
|
export * from './Xl1TransactionMonitor.ts'
|
|
7
9
|
export * from './Xl1TransactionPreparation.ts'
|
|
8
10
|
export * from './Xl1TransactionSubmission.ts'
|
|
11
|
+
export * from './Xl1TransactionSubmissionStorage.ts'
|
|
@@ -1,5 +1,2 @@
|
|
|
1
1
|
export * from './submitEthTransaction.ts'
|
|
2
2
|
export * from './submitXl1Transaction.ts'
|
|
3
|
-
export * from './validateSufficientLiquiditySourceAllowance.ts'
|
|
4
|
-
export * from './validateSufficientLiquiditySourceBalance.ts'
|
|
5
|
-
export * from './validateSufficientRunnerEthBalanceForGas.ts'
|
package/src/server/index.ts
CHANGED
|
@@ -4,6 +4,8 @@ export * from './server.ts'
|
|
|
4
4
|
// import type { NodeInstance } from '@xyo-network/sdk-js'
|
|
5
5
|
import type { FlowProducer } from 'bullmq'
|
|
6
6
|
|
|
7
|
+
import type { IBridgeServiceCollection } from '../services/index.ts'
|
|
8
|
+
|
|
7
9
|
// import type { IBridgeServiceCollection } from '../services/index.ts'
|
|
8
10
|
|
|
9
11
|
declare global {
|
|
@@ -11,8 +13,7 @@ declare global {
|
|
|
11
13
|
namespace Express {
|
|
12
14
|
interface Application {
|
|
13
15
|
flowProducer: FlowProducer
|
|
14
|
-
|
|
15
|
-
// services: IBridgeServiceCollection
|
|
16
|
+
services: IBridgeServiceCollection
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
}
|
|
@@ -13,7 +13,9 @@ import {
|
|
|
13
13
|
import { z } from 'zod'
|
|
14
14
|
|
|
15
15
|
import { createXl1ToEthBridgeJob } from '../../../../../queue/index.ts'
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
validateBridgeEstimateExact, validateBridgeTransaction, validateSufficientXL1SourceAddressBalance,
|
|
18
|
+
} from '../../../../../validation/index.ts'
|
|
17
19
|
import { getRemoteChainIdZod } from '../pathParams/index.ts'
|
|
18
20
|
|
|
19
21
|
export const BridgeToRemoteBodyZod = z.tuple([
|
|
@@ -38,6 +40,7 @@ export const makeBridgeToRemoteRoute = (config: BridgeConfig): RouteDefinition =
|
|
|
38
40
|
handlers: validateRequest(async (req, res) => {
|
|
39
41
|
const [signedTxBw, bridgeIntent, transfer] = req.body
|
|
40
42
|
const { flowProducer } = req.app
|
|
43
|
+
const { gateway } = req.app.services
|
|
41
44
|
|
|
42
45
|
// Validate request
|
|
43
46
|
const transactionValid = await validateBridgeTransaction(signedTxBw, bridgeIntent, transfer, config)
|
|
@@ -53,6 +56,13 @@ export const makeBridgeToRemoteRoute = (config: BridgeConfig): RouteDefinition =
|
|
|
53
56
|
return
|
|
54
57
|
}
|
|
55
58
|
|
|
59
|
+
// Validate sufficient balance
|
|
60
|
+
const sufficientBalance = await validateSufficientXL1SourceAddressBalance(bridgeIntent, gateway, config)
|
|
61
|
+
if (!sufficientBalance) {
|
|
62
|
+
res.status(400).send()
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
56
66
|
// Submit to job queue
|
|
57
67
|
const singedHydratedTransaction: SignedHydratedTransaction = [signedTxBw, [transfer, bridgeIntent]]
|
|
58
68
|
await createXl1ToEthBridgeJob(flowProducer, singedHydratedTransaction)
|
|
@@ -3,21 +3,14 @@ import { requestHandlerValidator } from '@xylabs/express'
|
|
|
3
3
|
import { asHex, isDefined } from '@xylabs/sdk-js'
|
|
4
4
|
import type { BridgeConfig } from '@xyo-network/chain-orchestration'
|
|
5
5
|
import { PayloadBuilder, PayloadZodStrictOfSchema } from '@xyo-network/sdk-js'
|
|
6
|
-
import type {
|
|
7
|
-
BridgeDestinationObservation, BridgeSourceObservation, SignedHydratedTransaction,
|
|
8
|
-
} from '@xyo-network/xl1-sdk'
|
|
6
|
+
import type { BridgeDestinationObservation, BridgeSourceObservation } from '@xyo-network/xl1-sdk'
|
|
9
7
|
import {
|
|
10
8
|
asBridgeIntent, BridgeDestinationObservationFieldsZod, BridgeDestinationObservationSchema, BridgeIntentFieldsZod, BridgeIntentSchema,
|
|
11
9
|
BridgeSourceObservationFieldsZod, BridgeSourceObservationSchema, isBridgeIntent,
|
|
12
10
|
} from '@xyo-network/xl1-sdk'
|
|
13
|
-
import type { Job } from 'bullmq'
|
|
14
|
-
import { Queue } from 'bullmq'
|
|
15
11
|
import { z } from 'zod'
|
|
16
12
|
|
|
17
|
-
import {
|
|
18
|
-
EthTransactionMonitor, EthTransactionPreparation, EthTransactionSubmission, getConnection, Xl1ToEthBridgeParent, Xl1TransactionMonitor,
|
|
19
|
-
Xl1TransactionPreparation, Xl1TransactionSubmission,
|
|
20
|
-
} from '../../../../../queue/index.ts'
|
|
13
|
+
import { getStatusQueueJobs, getXl1ToEthQueues } from '../../../../../queue/index.ts'
|
|
21
14
|
import { getRemoteChainIdZod } from '../pathParams/index.ts'
|
|
22
15
|
|
|
23
16
|
const BridgeIntentResponseZod = PayloadZodStrictOfSchema(BridgeIntentSchema)
|
|
@@ -37,78 +30,6 @@ export const BridgeToRemoteStatusResponseZod = z.union([
|
|
|
37
30
|
])
|
|
38
31
|
export type BridgeToRemoteStatusResponse = z.infer<typeof BridgeToRemoteStatusResponseZod>
|
|
39
32
|
|
|
40
|
-
interface StatusQueues {
|
|
41
|
-
ethTransactionMonitor: Queue
|
|
42
|
-
ethTransactionPreparation: Queue
|
|
43
|
-
ethTransactionSubmission: Queue
|
|
44
|
-
xl1ToEthBridgeParent: Queue
|
|
45
|
-
xl1TransactionMonitor: Queue
|
|
46
|
-
xl1TransactionPreparation: Queue
|
|
47
|
-
xl1TransactionSubmission: Queue
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
let statusQueues: StatusQueues | undefined
|
|
51
|
-
|
|
52
|
-
const getStatusQueues = (config: BridgeConfig): StatusQueues => {
|
|
53
|
-
if (statusQueues) return statusQueues
|
|
54
|
-
const connection = getConnection(config)
|
|
55
|
-
statusQueues = {
|
|
56
|
-
ethTransactionMonitor: new Queue(EthTransactionMonitor.queueName, { connection }),
|
|
57
|
-
ethTransactionPreparation: new Queue(EthTransactionPreparation.queueName, { connection }),
|
|
58
|
-
ethTransactionSubmission: new Queue(EthTransactionSubmission.queueName, { connection }),
|
|
59
|
-
xl1ToEthBridgeParent: new Queue(Xl1ToEthBridgeParent.queueName, { connection }),
|
|
60
|
-
xl1TransactionMonitor: new Queue(Xl1TransactionMonitor.queueName, { connection }),
|
|
61
|
-
xl1TransactionPreparation: new Queue(Xl1TransactionPreparation.queueName, { connection }),
|
|
62
|
-
xl1TransactionSubmission: new Queue(Xl1TransactionSubmission.queueName, { connection }),
|
|
63
|
-
}
|
|
64
|
-
return statusQueues
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
interface StatusQueueJobs {
|
|
68
|
-
ethTransactionMonitorJob?: Job
|
|
69
|
-
ethTransactionPreparationJob?: Job
|
|
70
|
-
ethTransactionSubmissionJob?: Job
|
|
71
|
-
xl1ToEthBridgeParentJob?: Job
|
|
72
|
-
xl1TransactionMonitorJob?: Job
|
|
73
|
-
xl1TransactionPreparationJob?: Job
|
|
74
|
-
xl1TransactionSubmissionJob?: Job
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Checks all the relevant status queues for a job with the given id and returns the jobs found in an object
|
|
79
|
-
* @param queues The status queues to check for jobs
|
|
80
|
-
* @param jobId The job id to look for in the queues, which is the same as the tx hash of the bridge transaction
|
|
81
|
-
* @returns An object containing the jobs found in the status queues corresponding to the given job id
|
|
82
|
-
*/
|
|
83
|
-
const getStatusQueueJobs = async (queues: StatusQueues, jobId: string): Promise<StatusQueueJobs> => {
|
|
84
|
-
const [
|
|
85
|
-
ethTransactionMonitorJob,
|
|
86
|
-
ethTransactionPreparationJob,
|
|
87
|
-
ethTransactionSubmissionJob,
|
|
88
|
-
xl1ToEthBridgeParentJob,
|
|
89
|
-
xl1TransactionMonitorJob,
|
|
90
|
-
xl1TransactionPreparationJob,
|
|
91
|
-
xl1TransactionSubmissionJob,
|
|
92
|
-
] = await Promise.all([
|
|
93
|
-
queues.ethTransactionMonitor.getJob(jobId),
|
|
94
|
-
queues.ethTransactionPreparation.getJob(jobId),
|
|
95
|
-
queues.ethTransactionSubmission.getJob(jobId),
|
|
96
|
-
queues.xl1ToEthBridgeParent.getJob(jobId),
|
|
97
|
-
queues.xl1TransactionMonitor.getJob(jobId),
|
|
98
|
-
queues.xl1TransactionPreparation.getJob(jobId),
|
|
99
|
-
queues.xl1TransactionSubmission.getJob(jobId),
|
|
100
|
-
])
|
|
101
|
-
return {
|
|
102
|
-
ethTransactionMonitorJob,
|
|
103
|
-
ethTransactionPreparationJob,
|
|
104
|
-
ethTransactionSubmissionJob,
|
|
105
|
-
xl1ToEthBridgeParentJob,
|
|
106
|
-
xl1TransactionMonitorJob,
|
|
107
|
-
xl1TransactionPreparationJob,
|
|
108
|
-
xl1TransactionSubmissionJob,
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
33
|
export const makeBridgeToRemoteStatusRoute = (config: BridgeConfig): RouteDefinition => {
|
|
113
34
|
const params = z.object({
|
|
114
35
|
chainId: getRemoteChainIdZod(config),
|
|
@@ -122,18 +43,18 @@ export const makeBridgeToRemoteStatusRoute = (config: BridgeConfig): RouteDefini
|
|
|
122
43
|
path: '/bridge/chains/:chainId/bridgeToRemote/status/:nonce',
|
|
123
44
|
handlers: validateRequest(async (req, res) => {
|
|
124
45
|
const jobId = req.params.nonce
|
|
125
|
-
const result: z.infer<typeof BridgeToRemoteStatusResponseZod> = [] as
|
|
126
|
-
const queues =
|
|
46
|
+
const result: z.infer<typeof BridgeToRemoteStatusResponseZod> = [] as z.infer<typeof BridgeToRemoteStatusResponseZod>
|
|
47
|
+
const queues = getXl1ToEthQueues(config)
|
|
127
48
|
|
|
128
49
|
const statusQueueJobs = await getStatusQueueJobs(queues, jobId)
|
|
129
50
|
|
|
130
|
-
// Check for the transaction hash in
|
|
131
|
-
const tx =
|
|
51
|
+
// Check for the transaction hash in the parent job
|
|
52
|
+
const tx = statusQueueJobs.xl1ToEthBridgeParentJob?.data?.tx
|
|
132
53
|
|
|
133
|
-
// If the
|
|
54
|
+
// If the job does not exist return Not Found
|
|
134
55
|
if (!tx) return res.sendStatus(404)
|
|
135
56
|
|
|
136
|
-
// If the
|
|
57
|
+
// If the tx is not the right shape for bridging return Not Found
|
|
137
58
|
const bridgeIntent = tx[1].find(isBridgeIntent)
|
|
138
59
|
if (!bridgeIntent) return res.sendStatus(404)
|
|
139
60
|
|
|
@@ -143,26 +64,31 @@ export const makeBridgeToRemoteStatusRoute = (config: BridgeConfig): RouteDefini
|
|
|
143
64
|
// Check the state of the XL1 monitor job to determine if we can include the source observation
|
|
144
65
|
const { xl1TransactionMonitorJob } = statusQueueJobs
|
|
145
66
|
const xl1MonitorState = xl1TransactionMonitorJob ? await xl1TransactionMonitorJob.getState() : undefined
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
67
|
+
if (xl1MonitorState === 'completed') {
|
|
68
|
+
const srcConfirmation = xl1TransactionMonitorJob?.returnvalue?.submissionHash
|
|
69
|
+
if (isDefined(srcConfirmation)) {
|
|
70
|
+
const schema = BridgeSourceObservationSchema
|
|
71
|
+
const bridgeSourceObservationFields = BridgeSourceObservationFieldsZod.parse(bridgeIntent)
|
|
72
|
+
const observation: BridgeSourceObservation = {
|
|
73
|
+
schema, ...bridgeSourceObservationFields, srcConfirmation,
|
|
74
|
+
}
|
|
75
|
+
result[1] = observation
|
|
152
76
|
}
|
|
153
|
-
result[1] = observation
|
|
154
77
|
}
|
|
155
78
|
|
|
156
79
|
// Check the state of the ETH monitor job to determine if we can include the destination observation
|
|
157
80
|
const { ethTransactionMonitorJob } = statusQueueJobs
|
|
158
81
|
const ethMonitorState = ethTransactionMonitorJob ? await ethTransactionMonitorJob.getState() : undefined
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
82
|
+
if (ethMonitorState === 'completed') {
|
|
83
|
+
const destConfirmation = asHex(ethTransactionMonitorJob?.returnvalue?.submissionHash)
|
|
84
|
+
if (isDefined(destConfirmation)) {
|
|
85
|
+
const schema = BridgeDestinationObservationSchema
|
|
86
|
+
const bridgeDestinationObservationFields = BridgeDestinationObservationFieldsZod.parse(bridgeIntent)
|
|
87
|
+
const observation: BridgeDestinationObservation = {
|
|
88
|
+
schema, ...bridgeDestinationObservationFields, destConfirmation,
|
|
89
|
+
}
|
|
90
|
+
result[2] = observation
|
|
91
|
+
}
|
|
166
92
|
}
|
|
167
93
|
|
|
168
94
|
res.json(result)
|
package/src/server/server.ts
CHANGED
|
@@ -13,6 +13,7 @@ export const getServer = async (context: BridgeConfigContext, gateway: XyoGatewa
|
|
|
13
13
|
const { port } = config
|
|
14
14
|
const app = getApp(config, gateway)
|
|
15
15
|
const services = await getServices(context, gateway)
|
|
16
|
+
app.services = services
|
|
16
17
|
addWorkers(config, services)
|
|
17
18
|
const server = app.listen(port, hostname, () => logger?.log(`[Bridge] Server listening at http://${hostname}:${port}`))
|
|
18
19
|
server.setTimeout(20_000)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Hash } from '@xylabs/sdk-js'
|
|
2
|
-
import type { AccountInstance } from '@xyo-network/
|
|
2
|
+
import type { AccountInstance } from '@xyo-network/sdk-js'
|
|
3
3
|
import type { BridgeableToken, LiquidityPoolBridge } from '@xyo-network/typechain'
|
|
4
4
|
import type { IterableMap, XyoGatewayRunner } from '@xyo-network/xl1-sdk'
|
|
5
5
|
import type { Provider, Wallet } from 'ethers'
|
package/src/services/TxState.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { isDefined } from '@xylabs/sdk-js'
|
|
2
|
-
|
|
3
1
|
export interface TxState<TTx, TTxHash extends string = string, TConfHash extends string = string> {
|
|
4
2
|
/**
|
|
5
3
|
* The confirmation hash of the transaction
|
|
@@ -14,19 +12,3 @@ export interface TxState<TTx, TTxHash extends string = string, TConfHash extends
|
|
|
14
12
|
*/
|
|
15
13
|
submissionHash?: TTxHash
|
|
16
14
|
}
|
|
17
|
-
|
|
18
|
-
export type TxCompletionStates = 'pendingSubmission' | 'submitted' | 'confirmed' | 'failed'
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Determines the transaction state based on the TxState object
|
|
22
|
-
* @param state The transaction state
|
|
23
|
-
* @returns The state of the transaction
|
|
24
|
-
*/
|
|
25
|
-
export const getTransactionCompletionState = <T>(state: TxState<T>): TxCompletionStates => {
|
|
26
|
-
// Prepared, submitted, and confirmed
|
|
27
|
-
if (isDefined(state.preparedTx) && isDefined(state.submissionHash) && isDefined(state.confirmationHash)) return 'confirmed'
|
|
28
|
-
// Prepared and submitted
|
|
29
|
-
if (isDefined(state.preparedTx) && isDefined(state.submissionHash)) return 'submitted'
|
|
30
|
-
// Prepared
|
|
31
|
-
return 'pendingSubmission'
|
|
32
|
-
}
|