@xyo-network/chain-bridge 1.17.2 → 1.17.6
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/asChainId.d.ts +3 -0
- package/dist/node/config/asChainId.d.ts.map +1 -0
- package/dist/node/config/asToken.d.ts +3 -0
- package/dist/node/config/asToken.d.ts.map +1 -0
- package/dist/node/config/getBridgeEscrowAddress.d.ts +5 -0
- package/dist/node/config/getBridgeEscrowAddress.d.ts.map +1 -0
- package/dist/node/config/getBridgeFeesAddress.d.ts +5 -0
- package/dist/node/config/getBridgeFeesAddress.d.ts.map +1 -0
- package/dist/node/config/getBridgeSettings.d.ts +3 -0
- package/dist/node/config/getBridgeSettings.d.ts.map +1 -0
- package/dist/node/config/getBridgeWalletAccount.d.ts +6 -0
- package/dist/node/config/getBridgeWalletAccount.d.ts.map +1 -0
- package/dist/node/config/getFeeStructure.d.ts +4 -0
- package/dist/node/config/getFeeStructure.d.ts.map +1 -0
- package/dist/node/config/getGateway.d.ts +3 -0
- package/dist/node/config/getGateway.d.ts.map +1 -0
- package/dist/node/config/getMaxBridgeAmount.d.ts +4 -0
- package/dist/node/config/getMaxBridgeAmount.d.ts.map +1 -0
- package/dist/node/config/getMinBridgeAmount.d.ts +4 -0
- package/dist/node/config/getMinBridgeAmount.d.ts.map +1 -0
- package/dist/node/config/getRemoteChainId.d.ts +4 -0
- package/dist/node/config/getRemoteChainId.d.ts.map +1 -0
- package/dist/node/config/getRemoteTokenAddress.d.ts +4 -0
- package/dist/node/config/getRemoteTokenAddress.d.ts.map +1 -0
- package/dist/node/config/getTransferAddresses.d.ts +8 -0
- package/dist/node/config/getTransferAddresses.d.ts.map +1 -0
- package/dist/node/config/getXl1ChainId.d.ts +4 -0
- package/dist/node/config/getXl1ChainId.d.ts.map +1 -0
- package/dist/node/config/getXl1TokenAddress.d.ts +4 -0
- package/dist/node/config/getXl1TokenAddress.d.ts.map +1 -0
- package/dist/node/config/index.d.ts +16 -0
- package/dist/node/config/index.d.ts.map +1 -0
- package/dist/node/index.mjs +1155 -206
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/interface/service/Observer/LiquidityPoolBridgeObserver/LiquidityPoolBridgeObserver.d.ts.map +1 -1
- package/dist/node/manifest/getLocator.d.ts.map +1 -1
- package/dist/node/manifest/public/index.d.ts +0 -4
- package/dist/node/manifest/public/index.d.ts.map +1 -1
- package/dist/node/modules/EVMLiquidityBridgeTransactionCompletionMonitorSentinel/EVMLiquidityBridgeTransactionCompletionMonitorSentinel.d.ts +77 -0
- package/dist/node/modules/EVMLiquidityBridgeTransactionCompletionMonitorSentinel/EVMLiquidityBridgeTransactionCompletionMonitorSentinel.d.ts.map +1 -0
- package/dist/node/modules/EVMLiquidityBridgeTransactionCompletionMonitorSentinel/index.d.ts +2 -0
- package/dist/node/modules/EVMLiquidityBridgeTransactionCompletionMonitorSentinel/index.d.ts.map +1 -0
- package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/XL1TransactionCompletionMonitorSentinel.d.ts +56 -0
- package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/XL1TransactionCompletionMonitorSentinel.d.ts.map +1 -0
- package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/index.d.ts +2 -0
- package/dist/node/modules/XL1TransactionCompletionMonitorSentinel/index.d.ts.map +1 -0
- package/dist/node/modules/index.d.ts +2 -1
- package/dist/node/modules/index.d.ts.map +1 -1
- package/dist/node/server/app.d.ts +3 -1
- package/dist/node/server/app.d.ts.map +1 -1
- package/dist/node/server/routes/addRoutes.d.ts +2 -1
- package/dist/node/server/routes/addRoutes.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/addBridgeRoutes.d.ts +2 -1
- package/dist/node/server/routes/bridge/addBridgeRoutes.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/getRouteDefinitions.d.ts +2 -1
- package/dist/node/server/routes/bridge/routeDefinitions/getRouteDefinitions.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/pathParams/ChainIdPathParam.d.ts +2 -1
- package/dist/node/server/routes/bridge/routeDefinitions/pathParams/ChainIdPathParam.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeConfig.d.ts +4 -0
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeConfig.d.ts.map +1 -0
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeFromRemoteStatus.d.ts +2 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeFromRemoteStatus.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeToRemote.d.ts +2 -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 +2 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteEstimate.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteStatus.d.ts +2 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteStatus.d.ts.map +1 -1
- package/dist/node/server/routes/bridge/routeDefinitions/routes/index.d.ts +1 -0
- package/dist/node/server/routes/bridge/routeDefinitions/routes/index.d.ts.map +1 -1
- package/dist/node/server/routes/index.d.ts +0 -2
- package/dist/node/server/routes/index.d.ts.map +1 -1
- package/dist/node/server/server.d.ts +1 -1
- package/dist/node/server/server.d.ts.map +1 -1
- package/dist/node/util/calculateBridgeFees.d.ts +10 -0
- package/dist/node/util/calculateBridgeFees.d.ts.map +1 -0
- package/dist/node/util/generateBridgeEstimate.d.ts +5 -0
- package/dist/node/util/generateBridgeEstimate.d.ts.map +1 -0
- package/dist/node/util/index.d.ts +6 -0
- package/dist/node/util/index.d.ts.map +1 -0
- package/dist/node/util/validateBridgeEstimate.d.ts +13 -0
- package/dist/node/util/validateBridgeEstimate.d.ts.map +1 -0
- package/dist/node/util/validateBridgeEstimateExact.d.ts +12 -0
- package/dist/node/util/validateBridgeEstimateExact.d.ts.map +1 -0
- package/dist/node/util/validateBridgeTransaction.d.ts +15 -0
- package/dist/node/util/validateBridgeTransaction.d.ts.map +1 -0
- package/package.json +31 -15
- package/src/config/asChainId.ts +7 -0
- package/src/config/asToken.ts +7 -0
- package/src/config/getBridgeEscrowAddress.ts +13 -0
- package/src/config/getBridgeFeesAddress.ts +13 -0
- package/src/config/getBridgeSettings.ts +24 -0
- package/src/config/getBridgeWalletAccount.ts +34 -0
- package/src/config/getFeeStructure.ts +8 -0
- package/src/config/getGateway.ts +19 -0
- package/src/config/getMaxBridgeAmount.ts +7 -0
- package/src/config/getMinBridgeAmount.ts +7 -0
- package/src/config/getRemoteChainId.ts +10 -0
- package/src/config/getRemoteTokenAddress.ts +10 -0
- package/src/config/getTransferAddresses.ts +17 -0
- package/src/config/getXl1ChainId.ts +13 -0
- package/src/config/getXl1TokenAddress.ts +12 -0
- package/src/config/index.ts +15 -0
- package/src/interface/service/Observer/LiquidityPoolBridgeObserver/LiquidityPoolBridgeObserver.ts +1 -2
- package/src/manifest/getLocator.ts +97 -34
- package/src/manifest/public/Ethereum.json +24 -64
- package/src/manifest/public/XL1.json +24 -64
- package/src/manifest/public/index.ts +0 -6
- package/src/modules/EVMLiquidityBridgeTransactionCompletionMonitorSentinel/EVMLiquidityBridgeTransactionCompletionMonitorSentinel.ts +234 -0
- package/src/modules/EVMLiquidityBridgeTransactionCompletionMonitorSentinel/index.ts +1 -0
- package/src/modules/XL1TransactionCompletionMonitorSentinel/XL1TransactionCompletionMonitorSentinel.ts +166 -0
- package/src/modules/XL1TransactionCompletionMonitorSentinel/index.ts +1 -0
- package/src/modules/index.ts +2 -1
- package/src/server/app.ts +5 -4
- package/src/server/routes/addRoutes.ts +3 -2
- package/src/server/routes/bridge/addBridgeRoutes.ts +3 -2
- package/src/server/routes/bridge/routeDefinitions/getRouteDefinitions.ts +8 -6
- package/src/server/routes/bridge/routeDefinitions/pathParams/ChainIdPathParam.ts +16 -13
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeConfig.ts +43 -0
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeFromRemoteStatus.ts +40 -37
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemote.ts +68 -45
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteEstimate.ts +48 -75
- package/src/server/routes/bridge/routeDefinitions/routes/bridgeToRemoteStatus.ts +95 -47
- package/src/server/routes/bridge/routeDefinitions/routes/index.ts +1 -0
- package/src/server/routes/index.ts +0 -2
- package/src/server/server.ts +37 -31
- package/src/util/calculateBridgeFees.ts +39 -0
- package/src/util/generateBridgeEstimate.ts +64 -0
- package/src/util/index.ts +5 -0
- package/src/util/validateBridgeEstimate.ts +60 -0
- package/src/util/validateBridgeEstimateExact.ts +34 -0
- package/src/util/validateBridgeTransaction.ts +40 -0
- package/dist/node/modules/XL1toEvmBridgeSentinel/XL1toEvmBridgeSentinel.d.ts +0 -47
- package/dist/node/modules/XL1toEvmBridgeSentinel/XL1toEvmBridgeSentinel.d.ts.map +0 -1
- package/dist/node/modules/XL1toEvmBridgeSentinel/index.d.ts +0 -2
- package/dist/node/modules/XL1toEvmBridgeSentinel/index.d.ts.map +0 -1
- package/dist/node/server/routes/address/AddressPathParams.d.ts +0 -4
- package/dist/node/server/routes/address/AddressPathParams.d.ts.map +0 -1
- package/dist/node/server/routes/address/addNodeRoutes.d.ts +0 -3
- package/dist/node/server/routes/address/addNodeRoutes.d.ts.map +0 -1
- package/dist/node/server/routes/address/get/get.d.ts +0 -4
- package/dist/node/server/routes/address/get/get.d.ts.map +0 -1
- package/dist/node/server/routes/address/get/index.d.ts +0 -2
- package/dist/node/server/routes/address/get/index.d.ts.map +0 -1
- package/dist/node/server/routes/address/index.d.ts +0 -2
- package/dist/node/server/routes/address/index.d.ts.map +0 -1
- package/dist/node/server/routes/address/post/getQueryConfig.d.ts +0 -6
- package/dist/node/server/routes/address/post/getQueryConfig.d.ts.map +0 -1
- package/dist/node/server/routes/address/post/index.d.ts +0 -2
- package/dist/node/server/routes/address/post/index.d.ts.map +0 -1
- package/dist/node/server/routes/address/post/post.d.ts +0 -8
- package/dist/node/server/routes/address/post/post.d.ts.map +0 -1
- package/src/manifest/public/Chain.json +0 -32
- package/src/modules/XL1toEvmBridgeSentinel/XL1toEvmBridgeSentinel.ts +0 -156
- package/src/modules/XL1toEvmBridgeSentinel/index.ts +0 -1
- package/src/server/routes/address/AddressPathParams.ts +0 -3
- package/src/server/routes/address/addNodeRoutes.ts +0 -21
- package/src/server/routes/address/get/get.ts +0 -30
- package/src/server/routes/address/get/index.ts +0 -1
- package/src/server/routes/address/index.ts +0 -1
- package/src/server/routes/address/post/getQueryConfig.ts +0 -23
- package/src/server/routes/address/post/index.ts +0 -1
- package/src/server/routes/address/post/post.ts +0 -77
|
@@ -1,83 +1,56 @@
|
|
|
1
1
|
import type { RouteDefinition } from '@xylabs/express'
|
|
2
2
|
import { requestHandlerValidator } from '@xylabs/express'
|
|
3
|
-
import {
|
|
4
|
-
hexToBigInt, toAddress, toHex,
|
|
5
|
-
} from '@xylabs/sdk-js'
|
|
6
|
-
import { createTransferPayload } from '@xyo-network/chain-protocol'
|
|
7
|
-
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
3
|
+
import { assertEx, toAddress } from '@xylabs/sdk-js'
|
|
8
4
|
import { PayloadZodLooseOfSchema, PayloadZodStrictOfSchema } from '@xyo-network/payload-model'
|
|
9
|
-
import type {
|
|
10
|
-
BridgeIntent, BridgeIntentFields, ChainId, Transfer,
|
|
11
|
-
} from '@xyo-network/xl1-protocol'
|
|
12
5
|
import {
|
|
13
|
-
BridgeIntentFieldsZod, BridgeIntentSchema, TransferSchema,
|
|
6
|
+
BridgeIntentFieldsZod, BridgeIntentSchema, toXL1BlockNumber, TransactionBoundWitnessZod, TransferSchema,
|
|
14
7
|
} from '@xyo-network/xl1-protocol'
|
|
15
|
-
import {
|
|
8
|
+
import { buildUnsignedTransaction, type Config } from '@xyo-network/xl1-protocol-sdk'
|
|
16
9
|
import { z } from 'zod'
|
|
17
10
|
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
srcAddress,
|
|
64
|
-
srcAmount,
|
|
65
|
-
srcToken: xl1ChainId,
|
|
66
|
-
|
|
67
|
-
// Destination
|
|
68
|
-
dest: remoteChainId,
|
|
69
|
-
destAddress,
|
|
70
|
-
destAmount,
|
|
71
|
-
destToken: bridgeableTokenContract,
|
|
72
|
-
nonce,
|
|
73
|
-
}
|
|
74
|
-
const bridgeIntent: BridgeIntent = new PayloadBuilder<BridgeIntent>({ schema: BridgeIntentSchema }).fields(bridgeIntentFields).build()
|
|
75
|
-
|
|
76
|
-
const transfer: Transfer = createTransferPayload(sender, {
|
|
77
|
-
[bridgeEscrowAddress]: destAmountBigInt,
|
|
78
|
-
[bridgeFeesAddress]: feeAmount,
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
res.json([bridgeIntent, transfer])
|
|
82
|
-
}),
|
|
11
|
+
import { getGateway, getXl1ChainId } from '../../../../../config/index.ts'
|
|
12
|
+
import { generateBridgeEstimate } from '../../../../../util/index.ts'
|
|
13
|
+
import { getRemoteChainIdZod } from '../pathParams/index.ts'
|
|
14
|
+
|
|
15
|
+
export const makeBridgeToRemoteEstimateRoute = (config: Config): RouteDefinition => {
|
|
16
|
+
const params = z.object({ chainId: getRemoteChainIdZod(config) })
|
|
17
|
+
const body = BridgeIntentFieldsZod.pick({
|
|
18
|
+
destAddress: true,
|
|
19
|
+
srcAddress: true,
|
|
20
|
+
srcAmount: true,
|
|
21
|
+
})
|
|
22
|
+
const response = z.tuple([
|
|
23
|
+
TransactionBoundWitnessZod,
|
|
24
|
+
PayloadZodStrictOfSchema(BridgeIntentSchema).extend(BridgeIntentFieldsZod.shape),
|
|
25
|
+
PayloadZodLooseOfSchema(TransferSchema),
|
|
26
|
+
])
|
|
27
|
+
const validateRequest = requestHandlerValidator({
|
|
28
|
+
params, body, response,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
method: 'post',
|
|
33
|
+
path: '/bridge/chains/:chainId/bridgeToRemote/estimate',
|
|
34
|
+
handlers: validateRequest(async (req, res) => {
|
|
35
|
+
const xl1ChainId = getXl1ChainId(config)
|
|
36
|
+
const {
|
|
37
|
+
srcAddress, srcAmount, destAddress,
|
|
38
|
+
} = req.body
|
|
39
|
+
const [bridgeIntent, transfer] = await generateBridgeEstimate(srcAddress, srcAmount, destAddress, config)
|
|
40
|
+
const sender = toAddress(srcAddress)
|
|
41
|
+
|
|
42
|
+
// Use viewer to get current block
|
|
43
|
+
const gateway = await getGateway(config)
|
|
44
|
+
const viewer = assertEx(gateway.connectionInstance.viewer, () => new Error('Viewer not available on gateway connection'))
|
|
45
|
+
const currentBlockNumber = await viewer.currentBlockNumber()
|
|
46
|
+
// Calculate nbf/exp
|
|
47
|
+
const nbf = toXL1BlockNumber(currentBlockNumber, true)
|
|
48
|
+
const exp = toXL1BlockNumber(currentBlockNumber + 1000, true)
|
|
49
|
+
// Build unsigned transaction representing the transfer that will be signed by srcAddress
|
|
50
|
+
const [txBw] = await buildUnsignedTransaction(xl1ChainId, [transfer], [bridgeIntent], nbf, exp, sender)
|
|
51
|
+
|
|
52
|
+
// Return the TX to the caller for signing
|
|
53
|
+
res.json([txBw, bridgeIntent, transfer])
|
|
54
|
+
}),
|
|
55
|
+
}
|
|
83
56
|
}
|
|
@@ -1,55 +1,103 @@
|
|
|
1
1
|
import type { RouteDefinition } from '@xylabs/express'
|
|
2
2
|
import { requestHandlerValidator } from '@xylabs/express'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
asAddress, asHex, toHex,
|
|
5
|
+
} from '@xylabs/sdk-js'
|
|
4
6
|
import { PayloadZodStrictOfSchema } from '@xyo-network/payload-model'
|
|
5
|
-
import type { BridgeDestinationObservation } from '@xyo-network/xl1-protocol'
|
|
7
|
+
import type { BridgeDestinationObservation, BridgeSourceObservation } from '@xyo-network/xl1-protocol'
|
|
6
8
|
import {
|
|
7
|
-
BridgeDestinationObservationFieldsZod,
|
|
8
|
-
|
|
9
|
+
BridgeDestinationObservationFieldsZod, BridgeDestinationObservationSchema, BridgeIntentFieldsZod, BridgeIntentSchema, BridgeSourceObservationFieldsZod,
|
|
10
|
+
BridgeSourceObservationSchema,
|
|
9
11
|
} from '@xyo-network/xl1-protocol'
|
|
12
|
+
import type { Config } from '@xyo-network/xl1-protocol-sdk'
|
|
10
13
|
import { z } from 'zod'
|
|
11
14
|
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
15
|
+
import { getBridgeSettings } from '../../../../../config/index.ts'
|
|
16
|
+
import { generateBridgeEstimate } from '../../../../../util/index.ts'
|
|
17
|
+
import { getRemoteChainIdZod } from '../pathParams/index.ts'
|
|
18
|
+
|
|
19
|
+
export const makeBridgeToRemoteStatusRoute = (config: Config): RouteDefinition => {
|
|
20
|
+
const params = z.object({
|
|
21
|
+
chainId: getRemoteChainIdZod(config),
|
|
22
|
+
nonce: z.string().nonempty(),
|
|
23
|
+
})
|
|
24
|
+
const query = z.object({ mockStatus: z.coerce.number().default(0) })
|
|
25
|
+
const response = z.union([
|
|
26
|
+
z.tuple([]),
|
|
27
|
+
z.tuple([PayloadZodStrictOfSchema(BridgeIntentSchema).extend(BridgeIntentFieldsZod.shape)]),
|
|
28
|
+
z.tuple([
|
|
29
|
+
PayloadZodStrictOfSchema(BridgeIntentSchema).extend(BridgeIntentFieldsZod.shape),
|
|
30
|
+
PayloadZodStrictOfSchema(BridgeSourceObservationSchema).extend(BridgeSourceObservationFieldsZod.shape),
|
|
31
|
+
]),
|
|
32
|
+
z.tuple([
|
|
33
|
+
PayloadZodStrictOfSchema(BridgeIntentSchema).extend(BridgeIntentFieldsZod.shape),
|
|
34
|
+
PayloadZodStrictOfSchema(BridgeSourceObservationSchema).extend(BridgeSourceObservationFieldsZod.shape),
|
|
35
|
+
PayloadZodStrictOfSchema(BridgeDestinationObservationSchema).extend(BridgeDestinationObservationFieldsZod.shape),
|
|
36
|
+
]),
|
|
37
|
+
])
|
|
38
|
+
|
|
39
|
+
const validateRequest = requestHandlerValidator({
|
|
40
|
+
params, query, response,
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
method: 'get',
|
|
45
|
+
path: '/bridge/chains/:chainId/bridgeToRemote/status/:nonce',
|
|
46
|
+
handlers: validateRequest(async (req, res) => {
|
|
47
|
+
const { chainId } = req.params
|
|
48
|
+
const { mockStatus = 0 } = req.query
|
|
49
|
+
const result: z.infer<typeof response> = [] as unknown as z.infer<typeof response>
|
|
50
|
+
|
|
51
|
+
const {
|
|
52
|
+
remoteTokenAddress, xl1ChainId, xl1TokenAddress,
|
|
53
|
+
} = await getBridgeSettings(config)
|
|
54
|
+
|
|
55
|
+
const src = xl1ChainId
|
|
56
|
+
const srcAddress = asAddress('2222222222222222222222222222222222222222', true)
|
|
57
|
+
const srcAmount = asHex('0x200', true)
|
|
58
|
+
const srcToken = xl1TokenAddress
|
|
59
|
+
|
|
60
|
+
const dest = chainId
|
|
61
|
+
const destAddress = asAddress('3333333333333333333333333333333333333333', true)
|
|
62
|
+
const destAmount = asHex('0x100', true)
|
|
63
|
+
const destToken = remoteTokenAddress
|
|
64
|
+
|
|
65
|
+
if (mockStatus === 0) return res.sendStatus(404)
|
|
66
|
+
if (mockStatus > 0) {
|
|
67
|
+
const [observation] = await generateBridgeEstimate(srcAddress, srcAmount, destAddress, config, req.params.nonce)
|
|
68
|
+
result[0] = observation
|
|
69
|
+
}
|
|
70
|
+
if (mockStatus > 1) {
|
|
71
|
+
const observation: BridgeSourceObservation = {
|
|
72
|
+
schema: BridgeSourceObservationSchema,
|
|
73
|
+
dest,
|
|
74
|
+
destAddress,
|
|
75
|
+
destAmount,
|
|
76
|
+
destToken,
|
|
77
|
+
src,
|
|
78
|
+
srcAddress,
|
|
79
|
+
srcAmount,
|
|
80
|
+
srcToken,
|
|
81
|
+
}
|
|
82
|
+
result[1] = observation
|
|
83
|
+
}
|
|
84
|
+
if (mockStatus > 2) {
|
|
85
|
+
const observation: BridgeDestinationObservation = {
|
|
86
|
+
schema: BridgeDestinationObservationSchema,
|
|
87
|
+
dest,
|
|
88
|
+
destAddress,
|
|
89
|
+
destAmount,
|
|
90
|
+
destToken,
|
|
91
|
+
src,
|
|
92
|
+
srcAddress,
|
|
93
|
+
srcAmount,
|
|
94
|
+
srcToken,
|
|
95
|
+
destConfirmation: toHex('0x9999'),
|
|
96
|
+
}
|
|
97
|
+
result[2] = observation
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
res.json(result)
|
|
101
|
+
}),
|
|
102
|
+
}
|
|
55
103
|
}
|
package/src/server/server.ts
CHANGED
|
@@ -1,33 +1,39 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
assertEx, isDefined, isString, type Logger,
|
|
3
|
+
} from '@xylabs/sdk-js'
|
|
4
|
+
import { boot } from '@xyo-network/bios'
|
|
5
|
+
import type { BiosExternalInterface } from '@xyo-network/bios-model'
|
|
2
6
|
import type { NodeInstance } from '@xyo-network/node-model'
|
|
7
|
+
import { HDWallet } from '@xyo-network/wallet'
|
|
3
8
|
import { type Config } from '@xyo-network/xl1-protocol-sdk'
|
|
4
9
|
|
|
10
|
+
import { getNode } from '../manifest/index.ts'
|
|
5
11
|
import { getApp } from './app.ts'
|
|
6
12
|
|
|
7
13
|
const hostname = '::'
|
|
8
14
|
// const hostname = '0.0.0.0'
|
|
9
15
|
|
|
10
16
|
// TODO: Make nodejs version of bios support round tripping mnemonic between boots
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
const getSeedPhrase = async (bios: BiosExternalInterface, config: Config, logger?: Logger): Promise<string> => {
|
|
18
|
+
const storedSeedPhrase = await bios.seedPhraseStore.get('os')
|
|
19
|
+
logger?.debug(`[Bridge] Stored mnemonic: ${storedSeedPhrase}`)
|
|
20
|
+
const { mnemonic } = config.api
|
|
21
|
+
if (isString(storedSeedPhrase) && isString(mnemonic)) {
|
|
22
|
+
logger?.warn('[Bridge] Stored mnemonic does not match supplied. Updating stored mnemonic to supplied.')
|
|
23
|
+
await bios.seedPhraseStore.set('os', mnemonic)
|
|
24
|
+
} else {
|
|
25
|
+
let seedPhrase: string
|
|
26
|
+
if (isString(mnemonic)) {
|
|
27
|
+
seedPhrase = mnemonic
|
|
28
|
+
} else {
|
|
29
|
+
seedPhrase = HDWallet.generateMnemonic()
|
|
30
|
+
logger?.log('[Bridge] No mnemonic provided, using random mnemonic. This is not recommended for production use.')
|
|
31
|
+
logger?.log(`[Bridge] Mnemonic: ${seedPhrase}`)
|
|
32
|
+
}
|
|
33
|
+
await bios.seedPhraseStore.set('os', seedPhrase)
|
|
34
|
+
}
|
|
35
|
+
return assertEx(await bios.seedPhraseStore.get('os'), () => 'Unable to acquire mnemonic from bios')
|
|
36
|
+
}
|
|
31
37
|
|
|
32
38
|
interface GetServerContext {
|
|
33
39
|
config: Config
|
|
@@ -36,16 +42,16 @@ interface GetServerContext {
|
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
export const getServer = async (context: GetServerContext) => {
|
|
39
|
-
const { logger } = context
|
|
40
|
-
const { port } =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const app = getApp()
|
|
45
|
+
const { logger, config } = context
|
|
46
|
+
const { port, mnemonic } = config.bridge
|
|
47
|
+
const bios = await boot()
|
|
48
|
+
const seedPhrase = isDefined(mnemonic) ? mnemonic : await getSeedPhrase(bios, config, logger)
|
|
49
|
+
const wallet = await HDWallet.fromPhrase(seedPhrase)
|
|
50
|
+
const nodeContext = {
|
|
51
|
+
wallet, logger, config,
|
|
52
|
+
}
|
|
53
|
+
const node = context.node ?? await getNode(nodeContext)
|
|
54
|
+
const app = getApp(node, config)
|
|
49
55
|
const server = app.listen(port, hostname, () => logger?.log(`[Bridge] Server listening at http://${hostname}:${port}`))
|
|
50
56
|
server.setTimeout(20_000)
|
|
51
57
|
return server
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Hex } from '@xylabs/sdk-js'
|
|
2
|
+
import { hexToBigInt, toHex } from '@xylabs/sdk-js'
|
|
3
|
+
import type { Config } from '@xyo-network/xl1-protocol-sdk'
|
|
4
|
+
|
|
5
|
+
export type FeeStructure = Pick<Config['bridge'], 'feeFixed' | 'feeRateBasisPoints'>
|
|
6
|
+
|
|
7
|
+
export interface FeeCalculationResult {
|
|
8
|
+
destAmount: Hex
|
|
9
|
+
feeFixed: Hex
|
|
10
|
+
feeVariable: Hex
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const calculateBridgeFees = (srcAmount: Hex, feeStructure: FeeStructure): FeeCalculationResult => {
|
|
14
|
+
const { feeFixed, feeRateBasisPoints } = feeStructure
|
|
15
|
+
|
|
16
|
+
// Format source input
|
|
17
|
+
const srcAmountBigInt = hexToBigInt(srcAmount)
|
|
18
|
+
|
|
19
|
+
// Calculate fixed fee
|
|
20
|
+
const feeFixedBigInt = hexToBigInt(feeFixed)
|
|
21
|
+
|
|
22
|
+
// Integer-safe basis point calculation (floor division)
|
|
23
|
+
const feeVariableBigInt
|
|
24
|
+
= (srcAmountBigInt * BigInt(feeRateBasisPoints)) / 10_000n
|
|
25
|
+
const feeVariable = toHex(feeVariableBigInt)
|
|
26
|
+
|
|
27
|
+
// Calculate total fee
|
|
28
|
+
const feeTotalBigInt = feeFixedBigInt + feeVariableBigInt
|
|
29
|
+
|
|
30
|
+
// Calculate destination amount
|
|
31
|
+
const destAmountBigInt = srcAmountBigInt > feeTotalBigInt ? srcAmountBigInt - feeTotalBigInt : 0n
|
|
32
|
+
const destAmount = toHex(destAmountBigInt)
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
destAmount,
|
|
36
|
+
feeFixed,
|
|
37
|
+
feeVariable,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Hex } from '@xylabs/sdk-js'
|
|
2
|
+
import { hexToBigInt, toAddress } from '@xylabs/sdk-js'
|
|
3
|
+
import { createTransferPayload } from '@xyo-network/chain-protocol'
|
|
4
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
5
|
+
import type {
|
|
6
|
+
BridgeIntent, BridgeIntentFields, Transfer,
|
|
7
|
+
} from '@xyo-network/xl1-protocol'
|
|
8
|
+
import { BridgeIntentSchema } from '@xyo-network/xl1-protocol'
|
|
9
|
+
import { type Config } from '@xyo-network/xl1-protocol-sdk'
|
|
10
|
+
import { v4 } from 'uuid'
|
|
11
|
+
|
|
12
|
+
import { getBridgeSettings } from '../config/index.ts'
|
|
13
|
+
import { calculateBridgeFees } from './calculateBridgeFees.ts'
|
|
14
|
+
|
|
15
|
+
export const generateBridgeEstimate = async (
|
|
16
|
+
srcAddress: Hex,
|
|
17
|
+
srcAmount: Hex,
|
|
18
|
+
destAddress: Hex,
|
|
19
|
+
config: Config,
|
|
20
|
+
nonceOverride?: string,
|
|
21
|
+
): Promise<[BridgeIntent, Transfer]> => {
|
|
22
|
+
const {
|
|
23
|
+
escrowAddress, feeFixed, feeRateBasisPoints, feesAddress, remoteChainId, remoteTokenAddress, xl1ChainId, xl1TokenAddress,
|
|
24
|
+
} = await getBridgeSettings(config)
|
|
25
|
+
|
|
26
|
+
const sender = toAddress(srcAddress)
|
|
27
|
+
|
|
28
|
+
// Calculate fees and destination amount
|
|
29
|
+
const fees = calculateBridgeFees(srcAmount, { feeFixed, feeRateBasisPoints })
|
|
30
|
+
const {
|
|
31
|
+
destAmount, feeFixed: feeFixedAmount, feeVariable,
|
|
32
|
+
} = fees
|
|
33
|
+
|
|
34
|
+
// Generate a unique nonce for the bridge intent
|
|
35
|
+
const nonce = nonceOverride ?? v4()
|
|
36
|
+
|
|
37
|
+
// Build the bridge intent
|
|
38
|
+
const bridgeIntentFields: BridgeIntentFields = {
|
|
39
|
+
// Source
|
|
40
|
+
src: xl1ChainId,
|
|
41
|
+
srcAddress: sender,
|
|
42
|
+
srcAmount,
|
|
43
|
+
srcToken: xl1TokenAddress,
|
|
44
|
+
|
|
45
|
+
// Destination
|
|
46
|
+
dest: remoteChainId,
|
|
47
|
+
destAddress,
|
|
48
|
+
destAmount,
|
|
49
|
+
destToken: remoteTokenAddress,
|
|
50
|
+
nonce,
|
|
51
|
+
}
|
|
52
|
+
const bridgeIntent: BridgeIntent = new PayloadBuilder<BridgeIntent>({ schema: BridgeIntentSchema }).fields(bridgeIntentFields).build()
|
|
53
|
+
|
|
54
|
+
// Build the transfer
|
|
55
|
+
const context = {
|
|
56
|
+
destAmount, feeFixed: feeFixedAmount, feeVariable,
|
|
57
|
+
}
|
|
58
|
+
const transfer: Transfer = createTransferPayload(sender, {
|
|
59
|
+
[escrowAddress]: hexToBigInt(destAmount),
|
|
60
|
+
[feesAddress]: hexToBigInt(feeFixedAmount) + hexToBigInt(feeVariable),
|
|
61
|
+
}, context)
|
|
62
|
+
|
|
63
|
+
return [bridgeIntent, transfer]
|
|
64
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { hexToBigInt, isUndefined } from '@xylabs/sdk-js'
|
|
2
|
+
import type { BridgeIntent, Transfer } from '@xyo-network/xl1-protocol'
|
|
3
|
+
import { type Config } from '@xyo-network/xl1-protocol-sdk'
|
|
4
|
+
|
|
5
|
+
import { getBridgeSettings } from '../config/index.ts'
|
|
6
|
+
import { calculateBridgeFees } from './calculateBridgeFees.js'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Validates a bridge estimate by checking the intent and transfer against the provided configuration. This method
|
|
10
|
+
* exists to allow for "at least" validation of a bridge estimates in case we want to allow for some flexibility in
|
|
11
|
+
* the bridge estimate.
|
|
12
|
+
* @param intent The BridgeIntent
|
|
13
|
+
* @param transfer The Transfer
|
|
14
|
+
* @param config The Config
|
|
15
|
+
* @returns True if the bridge estimate satisfies bridging conditions, false otherwise.
|
|
16
|
+
*/
|
|
17
|
+
export const validateBridgeEstimate = async (
|
|
18
|
+
intent: BridgeIntent,
|
|
19
|
+
transfer: Transfer,
|
|
20
|
+
config: Config,
|
|
21
|
+
): Promise<boolean> => {
|
|
22
|
+
const {
|
|
23
|
+
escrowAddress, feeFixed, feeRateBasisPoints, feesAddress, remoteChainId, remoteTokenAddress, xl1ChainId, xl1TokenAddress,
|
|
24
|
+
} = await getBridgeSettings(config)
|
|
25
|
+
|
|
26
|
+
// 1. Basic chain + token checks
|
|
27
|
+
if (intent.src !== xl1ChainId) return false
|
|
28
|
+
if (intent.dest !== remoteChainId) return false
|
|
29
|
+
if (intent.srcToken !== xl1TokenAddress) return false
|
|
30
|
+
if (intent.destToken !== remoteTokenAddress) return false
|
|
31
|
+
|
|
32
|
+
// 2. Validate transfer outputs: escrow receives destAmount,
|
|
33
|
+
// feesAddress receives feeFixed + variableFee.
|
|
34
|
+
const outputs = transfer?.transfers ?? {}
|
|
35
|
+
const escrowOut = outputs[escrowAddress]
|
|
36
|
+
const feeOut = outputs[feesAddress]
|
|
37
|
+
if (isUndefined(escrowOut) || isUndefined(feeOut)) return false
|
|
38
|
+
|
|
39
|
+
// Convert hex amounts
|
|
40
|
+
const destAmount = hexToBigInt(intent.destAmount)
|
|
41
|
+
const escrowAmount = hexToBigInt(escrowOut)
|
|
42
|
+
|
|
43
|
+
if (escrowAmount !== destAmount) return false
|
|
44
|
+
|
|
45
|
+
// 3. Recalculate fees and compare
|
|
46
|
+
const fees = calculateBridgeFees(intent.srcAmount, { feeFixed, feeRateBasisPoints })
|
|
47
|
+
|
|
48
|
+
const expectedFeeTotal
|
|
49
|
+
= hexToBigInt(fees.feeFixed) + hexToBigInt(fees.feeVariable)
|
|
50
|
+
|
|
51
|
+
const feeAmount = hexToBigInt(feeOut)
|
|
52
|
+
if (feeAmount < expectedFeeTotal) return false
|
|
53
|
+
|
|
54
|
+
// 4. Check derived dest amount
|
|
55
|
+
if (hexToBigInt(intent.destAmount) !== hexToBigInt(fees.destAmount)) {
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return true
|
|
60
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { isUndefined } from '@xylabs/sdk-js'
|
|
2
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
3
|
+
import type { BridgeIntent, Transfer } from '@xyo-network/xl1-protocol'
|
|
4
|
+
import { type Config } from '@xyo-network/xl1-protocol-sdk'
|
|
5
|
+
|
|
6
|
+
import { generateBridgeEstimate } from './generateBridgeEstimate.ts'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Validates a bridge estimate by checking the intent and transfer against the provided configuration. This method
|
|
10
|
+
* only returns true if the bridge estimate matches exactly.
|
|
11
|
+
* @param intent The BridgeIntent
|
|
12
|
+
* @param transfer The Transfer
|
|
13
|
+
* @param config The Config
|
|
14
|
+
* @returns True if the bridge estimate satisfies bridging conditions, false otherwise.
|
|
15
|
+
*/
|
|
16
|
+
export const validateBridgeEstimateExact = async (
|
|
17
|
+
intent: BridgeIntent,
|
|
18
|
+
transfer: Transfer,
|
|
19
|
+
config: Config,
|
|
20
|
+
): Promise<boolean> => {
|
|
21
|
+
const {
|
|
22
|
+
srcAddress, srcAmount, destAddress,
|
|
23
|
+
} = intent
|
|
24
|
+
const [calculatedIntent, calculatedTransfer] = await generateBridgeEstimate(srcAddress, srcAmount, destAddress, config)
|
|
25
|
+
if (isUndefined(calculatedIntent) || isUndefined(calculatedTransfer)) return false
|
|
26
|
+
const { nonce: expectedIntentNonce, ...expectedIntentStatic } = calculatedIntent
|
|
27
|
+
const { nonce: actualIntentNonce, ...actualIntentStatic } = intent
|
|
28
|
+
if (await PayloadBuilder.dataHash(expectedIntentStatic) !== await PayloadBuilder.dataHash(actualIntentStatic)) return false
|
|
29
|
+
const { epoch: expectedTransferEpoch, ...expectedTransferStatic } = calculatedTransfer
|
|
30
|
+
const { epoch: actualTransferEpoch, ...actualTransferStatic } = transfer
|
|
31
|
+
if (await PayloadBuilder.dataHash(expectedTransferStatic) !== await PayloadBuilder.dataHash(actualTransferStatic)) return false
|
|
32
|
+
|
|
33
|
+
return true
|
|
34
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { asAddress, isDefined } from '@xylabs/sdk-js'
|
|
2
|
+
import {
|
|
3
|
+
addressesContains, BoundWitnessValidator, payloadHashesContainsAll,
|
|
4
|
+
} from '@xyo-network/boundwitness-validator'
|
|
5
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
6
|
+
import type {
|
|
7
|
+
BridgeIntent, TransactionBoundWitness, Transfer,
|
|
8
|
+
} from '@xyo-network/xl1-protocol'
|
|
9
|
+
import { type Config } from '@xyo-network/xl1-protocol-sdk'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Validates a bridge estimate by checking the intent and transfer against the provided configuration. This method
|
|
13
|
+
* exists to allow for "at least" validation of a bridge estimates in case we want to allow for some flexibility in
|
|
14
|
+
* the bridge estimate.
|
|
15
|
+
* @ param signedTransaction The signed transaction bound witness
|
|
16
|
+
* @param signedTxBw The signed transaction bound witness
|
|
17
|
+
* @param intent The BridgeIntent
|
|
18
|
+
* @param transfer The Transfer
|
|
19
|
+
* @param config The Config
|
|
20
|
+
* @returns True if the bridge estimate satisfies bridging conditions, false otherwise.
|
|
21
|
+
*/
|
|
22
|
+
export const validateBridgeTransaction = async (
|
|
23
|
+
signedTxBw: TransactionBoundWitness,
|
|
24
|
+
intent: BridgeIntent,
|
|
25
|
+
transfer: Transfer,
|
|
26
|
+
config: Config,
|
|
27
|
+
): Promise<boolean> => {
|
|
28
|
+
const { srcAddress } = intent
|
|
29
|
+
|
|
30
|
+
const errors = await new BoundWitnessValidator(signedTxBw).validate()
|
|
31
|
+
if (isDefined(errors) && errors.length > 0) return false
|
|
32
|
+
|
|
33
|
+
const sender = asAddress(srcAddress, true)
|
|
34
|
+
if (!addressesContains(signedTxBw, sender)) return false
|
|
35
|
+
|
|
36
|
+
const hashes = await PayloadBuilder.hashes([intent, transfer])
|
|
37
|
+
if (!payloadHashesContainsAll(signedTxBw, hashes)) return false
|
|
38
|
+
|
|
39
|
+
return true
|
|
40
|
+
}
|