@xyo-network/chain-bridge 1.20.15 → 1.20.17
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/README.md +9 -75
- package/dist/node/index.mjs +44 -0
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/queue/flows/createXl1ToEthBridgeJob/getJobIdForXl1ToEthBridgeJob.d.ts +1 -1
- package/dist/node/queue/flows/createXl1ToEthBridgeJob/getJobIdForXl1ToEthBridgeJob.d.ts.map +1 -1
- package/dist/node/server/routes/addProbeRoutes.d.ts +3 -0
- package/dist/node/server/routes/addProbeRoutes.d.ts.map +1 -0
- package/dist/node/server/routes/addRoutes.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeConfig.d.ts +7 -7
- package/dist/node/server/routes/{healthz → livez}/get.d.ts +1 -1
- package/dist/node/server/routes/livez/get.d.ts.map +1 -0
- package/dist/node/server/routes/livez/index.d.ts.map +1 -0
- package/dist/node/server/routes/readyz/get.d.ts +4 -0
- package/dist/node/server/routes/readyz/get.d.ts.map +1 -0
- package/dist/node/server/routes/readyz/index.d.ts +2 -0
- package/dist/node/server/routes/readyz/index.d.ts.map +1 -0
- package/dist/node/server/routes/startupz/get.d.ts +4 -0
- package/dist/node/server/routes/startupz/get.d.ts.map +1 -0
- package/dist/node/server/routes/startupz/index.d.ts +2 -0
- package/dist/node/server/routes/startupz/index.d.ts.map +1 -0
- package/package.json +143 -54
- package/dist/node/server/routes/healthz/get.d.ts.map +0 -1
- package/dist/node/server/routes/healthz/index.d.ts.map +0 -1
- package/src/BridgeActor.ts +0 -51
- package/src/config/asChainId.ts +0 -7
- package/src/config/asToken.ts +0 -7
- package/src/config/getBridgeEscrowAddress.ts +0 -13
- package/src/config/getBridgeFeesAddress.ts +0 -13
- package/src/config/getBridgeSettings.ts +0 -24
- package/src/config/getBridgeWalletAccount.ts +0 -37
- package/src/config/getFeeStructure.ts +0 -8
- package/src/config/getMaxBridgeAmount.ts +0 -7
- package/src/config/getMinBridgeAmount.ts +0 -7
- package/src/config/getRemoteChainId.ts +0 -10
- package/src/config/getRemoteTokenAddress.ts +0 -10
- package/src/config/getTestGateway.ts +0 -24
- package/src/config/getTransferAddresses.ts +0 -17
- package/src/config/getXl1ChainId.ts +0 -13
- package/src/config/getXl1TokenAddress.ts +0 -12
- package/src/config/index.ts +0 -15
- package/src/index.ts +0 -1
- package/src/interface/index.ts +0 -4
- package/src/interface/interface/ChainBridgeRelayInterface.ts +0 -9
- package/src/interface/interface/IntentIndexerInterface.ts +0 -8
- package/src/interface/interface/LockingProcessorInterface.ts +0 -10
- package/src/interface/interface/ObservationIndexerInterface.ts +0 -12
- package/src/interface/interface/Params.ts +0 -26
- package/src/interface/interface/RelayInterface.ts +0 -8
- package/src/interface/interface/index.ts +0 -6
- package/src/interface/repository/RepositoryInterface.ts +0 -28
- package/src/interface/repository/index.ts +0 -1
- package/src/interface/service/Observer/ERC20TransferObserver/ERC20TransferObserver.ts +0 -180
- package/src/interface/service/Observer/ERC20TransferObserver/index.ts +0 -1
- package/src/interface/service/Observer/LiquidityPoolBridgeObserver/LiquidityPoolBridgeObserver.ts +0 -210
- package/src/interface/service/Observer/LiquidityPoolBridgeObserver/index.ts +0 -1
- package/src/interface/service/Observer/Observer.ts +0 -48
- package/src/interface/service/Observer/index.ts +0 -1
- package/src/interface/service/Relay/ChainBridgeRelay/ChainBridgeRelayInterface.ts +0 -11
- package/src/interface/service/Relay/ChainBridgeRelay/ChainBridgeRelayService.ts +0 -116
- package/src/interface/service/Relay/ChainBridgeRelay/index.ts +0 -1
- package/src/interface/service/Relay/LiquidityPoolBridgeRelay/LiquidityPoolBridgeRelay.ts +0 -227
- package/src/interface/service/Relay/LiquidityPoolBridgeRelay/index.ts +0 -1
- package/src/interface/service/Relay/index.ts +0 -1
- package/src/interface/service/index.ts +0 -2
- package/src/interface/util/getBridgeIntentIdentifier.ts +0 -18
- package/src/interface/util/index.ts +0 -1
- package/src/modules/EVMLiquidityBridgeTransactionCompletionMonitorSentinel/EVMLiquidityBridgeTransactionCompletionMonitorSentinel.ts +0 -235
- package/src/modules/EVMLiquidityBridgeTransactionCompletionMonitorSentinel/index.ts +0 -1
- package/src/modules/index.ts +0 -1
- package/src/queue/connection.ts +0 -16
- package/src/queue/flowProducer.ts +0 -16
- package/src/queue/flows/createEthToXl1BridgeJob.ts +0 -71
- package/src/queue/flows/createXl1ToEthBridgeJob/createXl1ToEthBridgeJob.ts +0 -127
- package/src/queue/flows/createXl1ToEthBridgeJob/getJobIdForXl1ToEthBridgeJob.ts +0 -18
- package/src/queue/flows/createXl1ToEthBridgeJob/getXl1ToEthBridgeJob.ts +0 -11
- package/src/queue/flows/createXl1ToEthBridgeJob/index.ts +0 -3
- package/src/queue/flows/index.ts +0 -2
- package/src/queue/getXl1ToEthQueueJobs.ts +0 -57
- package/src/queue/getXl1ToEthQueues.ts +0 -39
- package/src/queue/index.ts +0 -8
- package/src/queue/prefix.ts +0 -1
- package/src/queue/telemetry.ts +0 -12
- package/src/queue/workers/EthToXl1BridgeParent.ts +0 -40
- package/src/queue/workers/EthTransactionMonitor.ts +0 -59
- package/src/queue/workers/EthTransactionPreparation.ts +0 -83
- package/src/queue/workers/EthTransactionSubmission.ts +0 -63
- package/src/queue/workers/EthTransactionSubmissionStorage.ts +0 -76
- package/src/queue/workers/WorkerDescription.ts +0 -10
- package/src/queue/workers/Xl1ToEthBridgeParent.ts +0 -41
- package/src/queue/workers/Xl1TransactionJobData.ts +0 -12
- package/src/queue/workers/Xl1TransactionMonitor.ts +0 -82
- package/src/queue/workers/Xl1TransactionPreparation.ts +0 -52
- package/src/queue/workers/Xl1TransactionSubmission.ts +0 -70
- package/src/queue/workers/Xl1TransactionSubmissionStorage.ts +0 -77
- package/src/queue/workers/createWorkers.ts +0 -29
- package/src/queue/workers/index.ts +0 -11
- package/src/queue/workers/util/index.ts +0 -2
- package/src/queue/workers/util/submitEthTransaction.ts +0 -32
- package/src/queue/workers/util/submitXl1Transaction.ts +0 -26
- package/src/server/addFlowProducer.ts +0 -14
- package/src/server/addWorkers.ts +0 -13
- package/src/server/app.ts +0 -20
- package/src/server/index.ts +0 -19
- package/src/server/instrumentation.ts +0 -15
- package/src/server/routes/addRoutes.ts +0 -9
- package/src/server/routes/bridge/addBridgeRoutes.ts +0 -12
- package/src/server/routes/bridge/index.ts +0 -1
- package/src/server/routes/bridge/routeDefinitions/getRouteDefinitions.ts +0 -18
- package/src/server/routes/bridge/routeDefinitions/index.ts +0 -1
- package/src/server/routes/bridge/routeDefinitions/pathParams/ChainIdPathParam.ts +0 -21
- package/src/server/routes/bridge/routeDefinitions/pathParams/index.ts +0 -1
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeConfig.ts +0 -46
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeFromRemoteStatus.ts +0 -58
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemote.ts +0 -93
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteEstimate.ts +0 -69
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteMaxEstimate.ts +0 -64
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteStatus.ts +0 -98
- package/src/server/routes/bridge/routeDefinitions/routes/index.ts +0 -6
- package/src/server/routes/healthz/get.ts +0 -20
- package/src/server/routes/healthz/index.ts +0 -1
- package/src/server/routes/index.ts +0 -1
- package/src/server/server.ts +0 -21
- package/src/services/EthTxState.ts +0 -5
- package/src/services/IBridgeServiceCollection.ts +0 -19
- package/src/services/TxState.ts +0 -14
- package/src/services/Xl1TxState.ts +0 -9
- package/src/services/getIterableMap.ts +0 -34
- package/src/services/getServices.ts +0 -41
- package/src/services/index.ts +0 -5
- package/src/util/BridgeFees.ts +0 -16
- package/src/util/bridgeFeesAsBigInt.ts +0 -15
- package/src/util/calculateBridgeFees.ts +0 -33
- package/src/util/calculateMaxBridgeAmount.ts +0 -22
- package/src/util/createBridgeTransfer.ts +0 -31
- package/src/util/generateBridgeEstimate.ts +0 -55
- package/src/util/getConfigFromEnv.ts +0 -15
- package/src/util/index.ts +0 -7
- package/src/validation/AsyncLogger.ts +0 -5
- package/src/validation/index.ts +0 -6
- package/src/validation/validateBridgeEstimate.ts +0 -60
- package/src/validation/validateBridgeEstimateExact.ts +0 -39
- package/src/validation/validateBridgeTransaction.ts +0 -53
- package/src/validation/validateSufficientLiquiditySourceAllowance.ts +0 -39
- package/src/validation/validateSufficientLiquiditySourceBalance.ts +0 -38
- package/src/validation/validateSufficientRunnerEthBalanceForGas.ts +0 -57
- package/src/validation/validateSufficientXL1SourceAddressBalance.ts +0 -39
- /package/dist/node/server/routes/{healthz → livez}/index.d.ts +0 -0
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Hex } from '@xylabs/sdk-js'
|
|
2
|
-
import { isDefined } from '@xylabs/sdk-js'
|
|
3
|
-
import type { BridgeConfig } from '@xyo-network/chain-orchestration'
|
|
4
|
-
|
|
5
|
-
import { asToken } from './asToken.ts'
|
|
6
|
-
import { getXl1ChainId } from './getXl1ChainId.ts'
|
|
7
|
-
|
|
8
|
-
export const getXl1TokenAddress = (config: BridgeConfig): Hex => {
|
|
9
|
-
const token = asToken(config.xl1TokenAddress)
|
|
10
|
-
if (isDefined(token)) return token
|
|
11
|
-
return getXl1ChainId(config)
|
|
12
|
-
}
|
package/src/config/index.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export * from './asChainId.ts'
|
|
2
|
-
export * from './asToken.ts'
|
|
3
|
-
export * from './getBridgeEscrowAddress.ts'
|
|
4
|
-
export * from './getBridgeFeesAddress.ts'
|
|
5
|
-
export * from './getBridgeSettings.ts'
|
|
6
|
-
export * from './getBridgeWalletAccount.ts'
|
|
7
|
-
export * from './getFeeStructure.ts'
|
|
8
|
-
export * from './getMaxBridgeAmount.ts'
|
|
9
|
-
export * from './getMinBridgeAmount.ts'
|
|
10
|
-
export * from './getRemoteChainId.ts'
|
|
11
|
-
export * from './getRemoteTokenAddress.ts'
|
|
12
|
-
export * from './getTestGateway.ts'
|
|
13
|
-
export * from './getTransferAddresses.ts'
|
|
14
|
-
export * from './getXl1ChainId.ts'
|
|
15
|
-
export * from './getXl1TokenAddress.ts'
|
package/src/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './BridgeActor.ts'
|
package/src/interface/index.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { BridgeDestinationObservation, BridgeIntent } from '@xyo-network/xl1-sdk'
|
|
2
|
-
|
|
3
|
-
import type { AsynchronousRelayInterface, SynchronousRelayInterface } from './RelayInterface.ts'
|
|
4
|
-
|
|
5
|
-
export interface AsynchronousChainBridgeRelayInterface extends AsynchronousRelayInterface<BridgeIntent, BridgeDestinationObservation> {}
|
|
6
|
-
|
|
7
|
-
export interface SynchronousChainBridgeRelayInterface extends SynchronousRelayInterface<BridgeIntent, BridgeDestinationObservation> {}
|
|
8
|
-
|
|
9
|
-
export interface ChainBridgeRelayInterface extends AsynchronousChainBridgeRelayInterface, SynchronousChainBridgeRelayInterface {}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { Address, Hex } from '@xylabs/sdk-js'
|
|
2
|
-
|
|
3
|
-
export interface IntentIndexerInterface<T> {
|
|
4
|
-
addIntent(intent: T): Promise<boolean>
|
|
5
|
-
getIntentByNonce(nonce: Hex): Promise<T | undefined>
|
|
6
|
-
getIntentsForDestination(dest: Address): Promise<T[]>
|
|
7
|
-
getIntentsForSource(src: Address): Promise<T[]>
|
|
8
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { Address } from '@xylabs/sdk-js'
|
|
2
|
-
|
|
3
|
-
export interface LockingProcessorInterface<T> {
|
|
4
|
-
isLocked(intent: T): Promise<Address | null>
|
|
5
|
-
lock(processor: Address, intent: T): Promise<boolean>
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export interface UnlockingProcessorInterface<T> extends LockingProcessorInterface<T> {
|
|
9
|
-
unlock(processor: Address, intent: T): Promise<boolean>
|
|
10
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
BridgeDestinationObservation, BridgeIntent, BridgeSourceObservation,
|
|
3
|
-
} from '@xyo-network/xl1-sdk'
|
|
4
|
-
|
|
5
|
-
export interface ObservationIndexerInterface<
|
|
6
|
-
TObservation extends BridgeSourceObservation | BridgeDestinationObservation,
|
|
7
|
-
TIntent extends BridgeIntent = BridgeIntent,
|
|
8
|
-
> {
|
|
9
|
-
addObservation(observation: TObservation, intent: TIntent): Promise<boolean>
|
|
10
|
-
getIntentForObservation(observation: TObservation): Promise<TIntent | null>
|
|
11
|
-
getObservationForIntent(intent: TIntent): Promise<TObservation | null>
|
|
12
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { type BaseAccountableServiceParams } from '@xyo-network/chain-services'
|
|
2
|
-
import type {
|
|
3
|
-
BridgeDestinationObservation, BridgeIntent, BridgeSourceObservation,
|
|
4
|
-
} from '@xyo-network/xl1-sdk'
|
|
5
|
-
|
|
6
|
-
import type { ChainBridgeRelayInterface } from './ChainBridgeRelayInterface.ts'
|
|
7
|
-
import type { IntentIndexerInterface } from './IntentIndexerInterface.ts'
|
|
8
|
-
import type { LockingProcessorInterface, UnlockingProcessorInterface } from './LockingProcessorInterface.ts'
|
|
9
|
-
import type { ObservationIndexerInterface } from './ObservationIndexerInterface.ts'
|
|
10
|
-
|
|
11
|
-
export interface BridgeIntentIndexerInterface extends IntentIndexerInterface<BridgeIntent> {}
|
|
12
|
-
export interface BridgeSourceObservationIndexerInterface extends ObservationIndexerInterface<BridgeSourceObservation> {}
|
|
13
|
-
export interface BridgeDestinationObservationIndexerInterface extends ObservationIndexerInterface<BridgeDestinationObservation> {}
|
|
14
|
-
export interface LockingBridgeIntentProcessorInterface extends LockingProcessorInterface<BridgeIntent> {}
|
|
15
|
-
export interface UnlockingBridgeIntentProcessorInterface extends UnlockingProcessorInterface<BridgeIntent> {}
|
|
16
|
-
|
|
17
|
-
export type BridgeServiceCollection = {
|
|
18
|
-
destinationObservations: BridgeDestinationObservationIndexerInterface
|
|
19
|
-
destinationRelay: ChainBridgeRelayInterface
|
|
20
|
-
intentProcessed: LockingBridgeIntentProcessorInterface
|
|
21
|
-
intentProcessing: UnlockingBridgeIntentProcessorInterface
|
|
22
|
-
intents: BridgeIntentIndexerInterface
|
|
23
|
-
sourceObservations: BridgeSourceObservationIndexerInterface
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export type BridgeServiceParams = BaseAccountableServiceParams & BridgeServiceCollection
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { Address } from '@xylabs/sdk-js'
|
|
2
|
-
import type {
|
|
3
|
-
BridgeDestinationObservation, BridgeIntent, BridgeSourceObservation,
|
|
4
|
-
} from '@xyo-network/xl1-sdk'
|
|
5
|
-
|
|
6
|
-
export interface IntentRepository {
|
|
7
|
-
getBridgeIntents(src: Address, nonce?: string): Promise<BridgeIntent[]>
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface SourceObservationRepository {
|
|
11
|
-
getBridgeSourceObservation(intent: BridgeIntent): Promise<BridgeSourceObservation[]>
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface DestinationObservationRepository {
|
|
15
|
-
getBridgeDestinationObservation(intent: BridgeIntent): Promise<BridgeDestinationObservation[]>
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface IntentProcessingRepository {
|
|
19
|
-
isIntentProcessing(intent: BridgeIntent): Promise<boolean>
|
|
20
|
-
markIntentProcessed(intent: BridgeIntent): Promise<void>
|
|
21
|
-
markIntentProcessing(intent: BridgeIntent): Promise<void>
|
|
22
|
-
unmarkIntentProcessing(intent: BridgeIntent): Promise<void>
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface IntentProcessedRepository {
|
|
26
|
-
isIntentProcessed(intent: BridgeIntent): Promise<boolean>
|
|
27
|
-
markIntentProcessed(intent: BridgeIntent): Promise<void>
|
|
28
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './RepositoryInterface.ts'
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import type { Address } from '@xylabs/sdk-js'
|
|
2
|
-
import {
|
|
3
|
-
asAddress, asHex, hexToBigInt, isBigInt, isNull, isUndefined,
|
|
4
|
-
toAddress,
|
|
5
|
-
} from '@xylabs/sdk-js'
|
|
6
|
-
import type { BridgeDestinationObservation, BridgeSourceObservation } from '@xyo-network/xl1-sdk'
|
|
7
|
-
import {
|
|
8
|
-
BridgeDestinationObservationSchema, BridgeSourceObservationSchema, XYO_ZERO_ADDRESS,
|
|
9
|
-
} from '@xyo-network/xl1-sdk'
|
|
10
|
-
import type { EventLog, WebSocketProvider } from 'ethers'
|
|
11
|
-
import { Contract } from 'ethers'
|
|
12
|
-
import { getAddress } from 'ethers/address'
|
|
13
|
-
|
|
14
|
-
import type { BridgeServiceParams } from '../../../interface/index.ts'
|
|
15
|
-
import { AbstractBridgeObserverService } from '../Observer.ts'
|
|
16
|
-
|
|
17
|
-
export type ERC20TransferObserverParams = BridgeServiceParams & {
|
|
18
|
-
/**
|
|
19
|
-
* An ethers.js WebSocketProvider connected to the Ethereum network to monitor for ERC-20 transfers.
|
|
20
|
-
*/
|
|
21
|
-
provider: WebSocketProvider
|
|
22
|
-
/**
|
|
23
|
-
* The ERC-20 token contract address to monitor (e.g., XYO, USDC).
|
|
24
|
-
*/
|
|
25
|
-
tokenAddress: string
|
|
26
|
-
/**
|
|
27
|
-
* The address to watch for incoming or outgoing ERC-20 token transfers.
|
|
28
|
-
*/
|
|
29
|
-
watchAddress: string
|
|
30
|
-
/**
|
|
31
|
-
* Specify whether to watch for 'incoming' or 'outgoing' types of transfers.
|
|
32
|
-
*/
|
|
33
|
-
watchDirection: 'incoming' | 'outgoing'
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Minimal ERC-20 ABI only with Transfer event
|
|
37
|
-
const ERC20_ABI = [
|
|
38
|
-
'event Transfer(address indexed from, address indexed to, uint256 value)',
|
|
39
|
-
]
|
|
40
|
-
|
|
41
|
-
export class ERC20TransferObserver extends AbstractBridgeObserverService<ERC20TransferObserverParams> {
|
|
42
|
-
moniker = 'ERC20TransferObserver'
|
|
43
|
-
protected get tokenAddress(): Address {
|
|
44
|
-
return toAddress(this.params.tokenAddress)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
override async createHandler() {
|
|
48
|
-
const {
|
|
49
|
-
provider, tokenAddress, watchAddress, watchDirection,
|
|
50
|
-
} = this.params
|
|
51
|
-
// The custodial wallet to watch for transfers
|
|
52
|
-
const normalizedWatchAddress = getAddress(watchAddress)
|
|
53
|
-
|
|
54
|
-
// Create a Contract for the ERC-20 token
|
|
55
|
-
const token = new Contract(getAddress(tokenAddress), ERC20_ABI, provider)
|
|
56
|
-
|
|
57
|
-
// Listen for transfers involving WATCH_ADDRESS
|
|
58
|
-
const filterIncoming = token.filters.Transfer(null, normalizedWatchAddress)
|
|
59
|
-
const filterOutgoing = token.filters.Transfer(normalizedWatchAddress, null)
|
|
60
|
-
|
|
61
|
-
// Pick correct filter + direction
|
|
62
|
-
const filter = watchDirection === 'incoming' ? filterIncoming : filterOutgoing
|
|
63
|
-
|
|
64
|
-
// Replay old logs
|
|
65
|
-
const currentBlock = await provider.getBlockNumber()
|
|
66
|
-
const pastEvents = await token.queryFilter(filter, 0, currentBlock)
|
|
67
|
-
for (const ev of pastEvents) {
|
|
68
|
-
const {
|
|
69
|
-
from, to, value,
|
|
70
|
-
} = (ev as EventLog)?.args
|
|
71
|
-
await (watchDirection === 'incoming' ? this.handleTransfer(from, value, 'incoming') : this.handleTransfer(to, value, 'outgoing'))
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Watch for new events
|
|
75
|
-
if (watchDirection === 'incoming') {
|
|
76
|
-
await token.on(filterIncoming, (ev: EventLog) => {
|
|
77
|
-
// Sanitize event log
|
|
78
|
-
const { from, value } = ev.args
|
|
79
|
-
if (isUndefined(from) || isUndefined(value)) return
|
|
80
|
-
const sender = asAddress(from)
|
|
81
|
-
// Ignore mints
|
|
82
|
-
if (isUndefined(sender) || sender === XYO_ZERO_ADDRESS) return
|
|
83
|
-
// Ensure value is bigint and non-zero
|
|
84
|
-
if (!isBigInt(value) || value === 0n) return
|
|
85
|
-
// Handle transfer
|
|
86
|
-
this.handleTransfer(sender, value, 'incoming').catch(console.error)
|
|
87
|
-
})
|
|
88
|
-
} else if (watchDirection === 'outgoing') {
|
|
89
|
-
await token.on(filterOutgoing, (ev: EventLog) => {
|
|
90
|
-
// Sanitize event log
|
|
91
|
-
const { to, value } = ev.args
|
|
92
|
-
if (isUndefined(to) || isUndefined(value)) return
|
|
93
|
-
const receiver = asAddress(to)
|
|
94
|
-
// Ignore burns
|
|
95
|
-
if (isUndefined(receiver) || receiver === XYO_ZERO_ADDRESS) return
|
|
96
|
-
// Ensure value is bigint and non-zero
|
|
97
|
-
if (!isBigInt(value) || value === 0n) return
|
|
98
|
-
this.handleTransfer(receiver, value, 'outgoing').catch(console.error)
|
|
99
|
-
})
|
|
100
|
-
} else {
|
|
101
|
-
throw new Error(`Invalid watchDirection: ${watchDirection}`)
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
private async handleTransfer(account: Address, value: bigint, direction: 'incoming' | 'outgoing'): Promise<void> {
|
|
106
|
-
if (direction === 'incoming') {
|
|
107
|
-
const sender = asAddress(account)
|
|
108
|
-
if (isUndefined (sender) || sender === XYO_ZERO_ADDRESS) return
|
|
109
|
-
const intents = await this.intents.getIntentsForSource(sender)
|
|
110
|
-
if (intents.length === 0) return
|
|
111
|
-
// Find the intent that matches the transfer amount (chain and token are implicit to provider and intents were already indexed by address)
|
|
112
|
-
const intent = intents.findLast((i) => {
|
|
113
|
-
try {
|
|
114
|
-
// Source address matches intent
|
|
115
|
-
const address = asAddress(i.srcAddress)
|
|
116
|
-
if (isUndefined(address) || address !== sender) return false
|
|
117
|
-
// Source token must match
|
|
118
|
-
const token = asHex(i.srcToken)
|
|
119
|
-
if (isUndefined(token) || token !== this.tokenAddress) return false
|
|
120
|
-
// Source amount must match
|
|
121
|
-
const hexAmount = asHex(i.srcAmount)
|
|
122
|
-
if (isUndefined(hexAmount)) return false
|
|
123
|
-
const amount = hexToBigInt(hexAmount)
|
|
124
|
-
if (amount !== value) return false
|
|
125
|
-
// Otherwise matches
|
|
126
|
-
return true
|
|
127
|
-
} catch {
|
|
128
|
-
return false
|
|
129
|
-
}
|
|
130
|
-
})
|
|
131
|
-
if (isUndefined(intent)) return
|
|
132
|
-
// Found matching intent, check if observation already exists
|
|
133
|
-
const observations = this.sourceObservations
|
|
134
|
-
const existing = await observations.getObservationForIntent(intent)
|
|
135
|
-
// Only add if observation not already existing
|
|
136
|
-
if (isUndefined(existing) || isNull(existing)) {
|
|
137
|
-
const { schema, ...rest } = intent
|
|
138
|
-
const observation: BridgeSourceObservation = { schema: BridgeSourceObservationSchema, ...rest }
|
|
139
|
-
await observations.addObservation(observation, intent)
|
|
140
|
-
}
|
|
141
|
-
} else if (direction === 'outgoing') {
|
|
142
|
-
const receiver = asAddress(account)
|
|
143
|
-
if (isUndefined (receiver) || receiver === XYO_ZERO_ADDRESS) return
|
|
144
|
-
const intents = await this.intents.getIntentsForDestination(receiver)
|
|
145
|
-
if (intents.length === 0) return
|
|
146
|
-
// Find the intent that matches the transfer amount (chain and token are implicit to provider and intents were already indexed by address)
|
|
147
|
-
const intent = intents.findLast((i) => {
|
|
148
|
-
try {
|
|
149
|
-
// Source address matches intent
|
|
150
|
-
const address = asAddress(i.destAddress)
|
|
151
|
-
if (isUndefined(address) || address !== receiver) return false
|
|
152
|
-
// Source token must match
|
|
153
|
-
const token = asHex(i.destToken)
|
|
154
|
-
if (isUndefined(token) || token !== this.tokenAddress) return false
|
|
155
|
-
// Source amount must match
|
|
156
|
-
const hexAmount = asHex(i.destAmount)
|
|
157
|
-
if (isUndefined(hexAmount)) return false
|
|
158
|
-
const amount = hexToBigInt(hexAmount)
|
|
159
|
-
if (amount !== value) return false
|
|
160
|
-
// Otherwise matches
|
|
161
|
-
return true
|
|
162
|
-
} catch {
|
|
163
|
-
return false
|
|
164
|
-
}
|
|
165
|
-
})
|
|
166
|
-
if (isUndefined(intent)) return
|
|
167
|
-
// Found matching intent, check if observation already exists
|
|
168
|
-
const observations = this.destinationObservations
|
|
169
|
-
const existing = await observations.getObservationForIntent(intent)
|
|
170
|
-
// Only add if observation not already existing
|
|
171
|
-
if (isUndefined(existing) || isNull(existing)) {
|
|
172
|
-
const { schema, ...rest } = intent
|
|
173
|
-
const observation: BridgeDestinationObservation = { schema: BridgeDestinationObservationSchema, ...rest }
|
|
174
|
-
await observations.addObservation(observation, intent)
|
|
175
|
-
}
|
|
176
|
-
} else {
|
|
177
|
-
throw new Error(`Invalid direction: ${direction}`)
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './ERC20TransferObserver.ts'
|
package/src/interface/service/Observer/LiquidityPoolBridgeObserver/LiquidityPoolBridgeObserver.ts
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import type { Address, Hex } from '@xylabs/sdk-js'
|
|
2
|
-
import {
|
|
3
|
-
asAddress, asHex, assertEx, hexFromBigInt, hexToBigInt, isNull, isUndefined, toAddress,
|
|
4
|
-
} from '@xylabs/sdk-js'
|
|
5
|
-
import { PayloadBuilder } from '@xyo-network/sdk-js'
|
|
6
|
-
import type { ILiquidityPoolBridge } from '@xyo-network/typechain'
|
|
7
|
-
import { ILiquidityPoolBridge__factory } from '@xyo-network/typechain'
|
|
8
|
-
import type {
|
|
9
|
-
BridgeDestinationObservation, BridgeIntent, BridgeSourceObservation,
|
|
10
|
-
} from '@xyo-network/xl1-sdk'
|
|
11
|
-
import {
|
|
12
|
-
BridgeDestinationObservationSchema, BridgeIntentSchema, BridgeSourceObservationSchema,
|
|
13
|
-
} from '@xyo-network/xl1-sdk'
|
|
14
|
-
import type { ContractEventPayload, WebSocketProvider } from 'ethers'
|
|
15
|
-
import { getAddress } from 'ethers'
|
|
16
|
-
|
|
17
|
-
import type { BridgeServiceParams } from '../../../interface/index.ts'
|
|
18
|
-
import { AbstractBridgeObserverService } from '../Observer.ts'
|
|
19
|
-
|
|
20
|
-
export type LiquidityPoolBridgeObserverParams = BridgeServiceParams & {
|
|
21
|
-
/**
|
|
22
|
-
* The address to watch for incoming or outgoing ERC-20 token transfers.
|
|
23
|
-
*/
|
|
24
|
-
bridgeAddress: Address
|
|
25
|
-
/**
|
|
26
|
-
* An ethers.js WebSocketProvider connected to the Ethereum network to monitor for ERC-20 transfers.
|
|
27
|
-
*/
|
|
28
|
-
provider: WebSocketProvider
|
|
29
|
-
/**
|
|
30
|
-
* The block number to start monitoring from.
|
|
31
|
-
*/
|
|
32
|
-
startBlock?: number
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export class LiquidityPoolBridgeObserver extends AbstractBridgeObserverService<LiquidityPoolBridgeObserverParams> {
|
|
36
|
-
moniker = 'LiquidityPoolBridgeObserver'
|
|
37
|
-
protected _bridge: ILiquidityPoolBridge | undefined
|
|
38
|
-
protected _bridgeChainId: Hex | undefined
|
|
39
|
-
protected _bridgeRemoteChainId: Hex | undefined
|
|
40
|
-
protected _bridgeTokenAddress: Address | undefined
|
|
41
|
-
|
|
42
|
-
protected get bridge(): ILiquidityPoolBridge {
|
|
43
|
-
return assertEx(this._bridge, () => new Error('Bridge contract not initialized'))
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
protected get bridgeChainId(): Hex {
|
|
47
|
-
return assertEx(this._bridgeChainId, () => new Error('Bridge chain ID not initialized'))
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
protected get bridgeRemoteChainId(): Hex {
|
|
51
|
-
return assertEx(this._bridgeRemoteChainId, () => new Error('Bridge remote chain ID not initialized'))
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
protected get bridgeTokenAddress(): Address {
|
|
55
|
-
return assertEx(this._bridgeTokenAddress, () => new Error('Bridge token address not initialized'))
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
protected get provider(): WebSocketProvider {
|
|
59
|
-
return assertEx(this.params.provider, () => new Error('Provider not initialized'))
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
protected get startBlock(): number {
|
|
63
|
-
return isUndefined(this.params.startBlock) ? 0 : this.params.startBlock
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
override async createHandler() {
|
|
67
|
-
const { provider, bridgeAddress } = this.params
|
|
68
|
-
|
|
69
|
-
// Connect to the bridge contract
|
|
70
|
-
this._bridge = ILiquidityPoolBridge__factory.connect(getAddress(bridgeAddress), provider)
|
|
71
|
-
|
|
72
|
-
// Parse bridge network chain ID
|
|
73
|
-
const network = await provider.getNetwork()
|
|
74
|
-
this._bridgeChainId = assertEx(hexFromBigInt(network.chainId), () => new Error('Failed to parse bridgeChainId'))
|
|
75
|
-
|
|
76
|
-
// Parse bridge token address
|
|
77
|
-
const tokenAddress = await this.bridge.token()
|
|
78
|
-
this._bridgeTokenAddress = toAddress(tokenAddress)
|
|
79
|
-
|
|
80
|
-
// Parse bridge remote chain ID
|
|
81
|
-
const bridgeRemoteChain = await this.bridge.remoteChain()
|
|
82
|
-
this._bridgeRemoteChainId = asHex(bridgeRemoteChain)
|
|
83
|
-
|
|
84
|
-
// Grab the current block number to avoid processing old events
|
|
85
|
-
const currentBlock = await provider.getBlockNumber()
|
|
86
|
-
const manualIndexThroughBlockNumber = Math.max(currentBlock, this.startBlock)
|
|
87
|
-
|
|
88
|
-
// Watch for & process new events
|
|
89
|
-
await this.bridge.on(this.bridge.getEvent('BridgedToRemote'), (id, from, to, amount, remoteChain, args) => {
|
|
90
|
-
const contractEvent = args as unknown as ContractEventPayload
|
|
91
|
-
if (contractEvent?.log?.blockNumber <= manualIndexThroughBlockNumber) return
|
|
92
|
-
this.handleBridgeToRemote(id, from, to, amount, remoteChain).catch(console.error)
|
|
93
|
-
})
|
|
94
|
-
await this.bridge.on(this.bridge.getEvent('BridgedFromRemote'), (id, from, to, amount, remoteChain, args) => {
|
|
95
|
-
const contractEvent = args as unknown as ContractEventPayload
|
|
96
|
-
if (contractEvent?.log?.blockNumber <= manualIndexThroughBlockNumber) return
|
|
97
|
-
this.handleBridgeFromRemote(id, from, to, amount, remoteChain).catch(console.error)
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
// Process old events
|
|
101
|
-
await this.processOldEvents(this.startBlock, manualIndexThroughBlockNumber)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
private async handleBridgeFromRemote(id: bigint, from: string, to: string, value: bigint, remoteChain: string): Promise<void> {
|
|
105
|
-
const srcAddress = asAddress(from)
|
|
106
|
-
const destAddress = asAddress(to)
|
|
107
|
-
const remoteChainId = asHex(remoteChain)
|
|
108
|
-
if (isUndefined (srcAddress) || isUndefined (destAddress) || isUndefined (remoteChainId)) return
|
|
109
|
-
|
|
110
|
-
const intents = await this.intents.getIntentsForDestination(destAddress)
|
|
111
|
-
if (intents.length === 0) return
|
|
112
|
-
// Find the intent that matches the transfer amount (chain and token are implicit to provider and intents were already indexed by address)
|
|
113
|
-
const intent = intents.findLast((i) => {
|
|
114
|
-
try {
|
|
115
|
-
// TODO: Add source to event signature to capture intent
|
|
116
|
-
// Source address matches intent
|
|
117
|
-
// const intentSrcAddress = asAddress(i.srcAddress)
|
|
118
|
-
// if (isUndefined(intentSrcAddress) || intentSrcAddress !== srcAddress) return false
|
|
119
|
-
// Destination address matches intent
|
|
120
|
-
const intentDestAddress = asAddress(i.destAddress)
|
|
121
|
-
if (isUndefined(intentDestAddress) || intentDestAddress !== destAddress) return false
|
|
122
|
-
|
|
123
|
-
// Source token matches intent
|
|
124
|
-
const intentSrcToken = i.srcToken
|
|
125
|
-
if (isUndefined(intentSrcToken) || intentSrcToken !== this.bridgeRemoteChainId) return false
|
|
126
|
-
// Destination token matches intent
|
|
127
|
-
const intentDestToken = asHex(i.destToken)
|
|
128
|
-
if (isUndefined(intentDestToken) || intentDestToken !== this.bridgeTokenAddress) return false
|
|
129
|
-
|
|
130
|
-
// Destination amount must match
|
|
131
|
-
const intentDestAmountHex = asHex(i.destAmount)
|
|
132
|
-
if (isUndefined(intentDestAmountHex)) return false
|
|
133
|
-
const intentDestAmountBigInt = hexToBigInt(intentDestAmountHex)
|
|
134
|
-
if (intentDestAmountBigInt !== value) return false
|
|
135
|
-
|
|
136
|
-
// Otherwise matches
|
|
137
|
-
return true
|
|
138
|
-
} catch {
|
|
139
|
-
return false
|
|
140
|
-
}
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
if (isUndefined(intent)) return
|
|
144
|
-
// Found matching intent, check if observation already exists
|
|
145
|
-
const observations = this.destinationObservations
|
|
146
|
-
const existing = await observations.getObservationForIntent(intent)
|
|
147
|
-
// Only add if observation not already existing
|
|
148
|
-
if (isUndefined(existing) || isNull(existing)) {
|
|
149
|
-
const { schema, ...rest } = intent
|
|
150
|
-
const observation: BridgeDestinationObservation = { schema: BridgeDestinationObservationSchema, ...rest }
|
|
151
|
-
await observations.addObservation(observation, intent)
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
private async handleBridgeToRemote(id: bigint, from: string, to: string, value: bigint, remoteChain: string): Promise<void> {
|
|
156
|
-
const srcAddress = asAddress(from)
|
|
157
|
-
const destAddress = asAddress(to)
|
|
158
|
-
const remoteChainId = asHex(remoteChain)
|
|
159
|
-
if (isUndefined (srcAddress) || isUndefined (destAddress) || isUndefined (remoteChainId)) return
|
|
160
|
-
if (remoteChainId != this.bridgeRemoteChainId) return
|
|
161
|
-
|
|
162
|
-
// If we don't have an intent for this nonce already
|
|
163
|
-
const nonce = hexFromBigInt(id)
|
|
164
|
-
let intent = await this.intents.getIntentByNonce(nonce)
|
|
165
|
-
if (isUndefined(intent)) {
|
|
166
|
-
// Create observation for intent if none exists
|
|
167
|
-
intent = new PayloadBuilder<BridgeIntent>({ schema: BridgeIntentSchema }).fields({
|
|
168
|
-
nonce,
|
|
169
|
-
dest: this.bridgeRemoteChainId,
|
|
170
|
-
destAddress,
|
|
171
|
-
destAmount: hexFromBigInt(value),
|
|
172
|
-
destToken: this.bridgeRemoteChainId,
|
|
173
|
-
src: this.bridgeChainId,
|
|
174
|
-
srcAddress,
|
|
175
|
-
srcAmount: hexFromBigInt(value),
|
|
176
|
-
srcToken: this.bridgeTokenAddress,
|
|
177
|
-
}).build()
|
|
178
|
-
await this.intents.addIntent(intent)
|
|
179
|
-
}
|
|
180
|
-
// Ensure we have an intent to match against
|
|
181
|
-
if (isUndefined(intent)) return
|
|
182
|
-
// Found matching intent, check if observation already exists
|
|
183
|
-
const observations = this.sourceObservations
|
|
184
|
-
const existing = await observations.getObservationForIntent(intent)
|
|
185
|
-
// Only add if observation not already existing
|
|
186
|
-
if (isUndefined(existing) || isNull(existing)) {
|
|
187
|
-
const { schema, ...rest } = intent
|
|
188
|
-
const observation: BridgeSourceObservation = { schema: BridgeSourceObservationSchema, ...rest }
|
|
189
|
-
await observations.addObservation(observation, intent)
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private async processOldEvents(startBlock: number, endBlock: number): Promise<void> {
|
|
194
|
-
const bridgedToRemote = await this.bridge.queryFilter(this.bridge.filters.BridgedToRemote(), startBlock, endBlock)
|
|
195
|
-
for (const log of bridgedToRemote) {
|
|
196
|
-
const {
|
|
197
|
-
id, srcAddress, destAddress, amount, destToken,
|
|
198
|
-
} = log.args
|
|
199
|
-
await this.handleBridgeToRemote(id, srcAddress, destAddress, amount, destToken)
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const bridgedFromRemote = await this.bridge.queryFilter(this.bridge.filters.BridgedFromRemote(), startBlock, endBlock)
|
|
203
|
-
for (const log of bridgedFromRemote) {
|
|
204
|
-
const {
|
|
205
|
-
id, srcAddress, destAddress, amount, srcToken,
|
|
206
|
-
} = log.args
|
|
207
|
-
await this.handleBridgeFromRemote(id, srcAddress, destAddress, amount, srcToken)
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './LiquidityPoolBridgeObserver.ts'
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { assertEx } from '@xylabs/sdk-js'
|
|
2
|
-
import { AbstractCreatableProvider } from '@xyo-network/xl1-sdk'
|
|
3
|
-
|
|
4
|
-
import type {
|
|
5
|
-
BridgeDestinationObservationIndexerInterface, BridgeIntentIndexerInterface, BridgeServiceParams,
|
|
6
|
-
BridgeSourceObservationIndexerInterface,
|
|
7
|
-
ChainBridgeRelayInterface,
|
|
8
|
-
LockingBridgeIntentProcessorInterface, UnlockingBridgeIntentProcessorInterface,
|
|
9
|
-
} from '../../interface/index.ts'
|
|
10
|
-
|
|
11
|
-
export interface BridgeObserverInterface {
|
|
12
|
-
// TODO:
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export abstract class AbstractBridgeObserverService<TParams extends BridgeServiceParams = BridgeServiceParams>
|
|
16
|
-
extends AbstractCreatableProvider<TParams> implements BridgeObserverInterface {
|
|
17
|
-
protected get account() {
|
|
18
|
-
return assertEx(this.params.account, () => 'account is required')
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
protected get destinationObservations(): BridgeDestinationObservationIndexerInterface {
|
|
22
|
-
return assertEx(this.params.destinationObservations, () => 'destinationObservations is required')
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
protected get destinationRelay(): ChainBridgeRelayInterface {
|
|
26
|
-
return assertEx(this.params.destinationRelay, () => 'destinationRelay is required')
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
protected get intentProcessed(): LockingBridgeIntentProcessorInterface {
|
|
30
|
-
return assertEx(this.params.intentProcessed, () => 'intentProcessed is required')
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
protected get intentProcessing(): UnlockingBridgeIntentProcessorInterface {
|
|
34
|
-
return assertEx(this.params.intentProcessing, () => 'intentProcessing is required')
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
protected get intents(): BridgeIntentIndexerInterface {
|
|
38
|
-
return assertEx(this.params.intents, () => 'intents is required')
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
protected get sourceObservations(): BridgeSourceObservationIndexerInterface {
|
|
42
|
-
return assertEx(this.params.sourceObservations, () => 'sourceObservations is required')
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async process(): Promise<void> {
|
|
46
|
-
await Promise.resolve()
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './Observer.ts'
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { BridgeDestinationObservation, BridgeIntent } from '@xyo-network/xl1-sdk'
|
|
2
|
-
|
|
3
|
-
import type { AsynchronousRelayInterface, SynchronousRelayInterface } from '../../../interface/index.ts'
|
|
4
|
-
|
|
5
|
-
export interface BlockingChainBridgeRelay extends SynchronousRelayInterface<BridgeIntent, BridgeDestinationObservation> {}
|
|
6
|
-
|
|
7
|
-
export interface ChainBridgeRelay extends AsynchronousRelayInterface<BridgeIntent, BridgeDestinationObservation> {}
|
|
8
|
-
|
|
9
|
-
export interface ChainBridgeRelayInterface extends
|
|
10
|
-
AsynchronousRelayInterface<BridgeIntent, BridgeDestinationObservation>,
|
|
11
|
-
SynchronousRelayInterface<BridgeIntent, BridgeDestinationObservation> {}
|