@avalabs/bridge-unified 2.1.1 → 3.0.0
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/LICENSE +9 -0
- package/README.md +115 -31
- package/dist/index.cjs +36 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +252 -84
- package/dist/index.d.ts +252 -84
- package/dist/index.js +9 -4
- package/dist/index.js.map +1 -1
- package/package.json +14 -4
- package/.turbo/turbo-build.log +0 -22
- package/.turbo/turbo-lint.log +0 -4
- package/.turbo/turbo-test.log +0 -26
- package/CHANGELOG.md +0 -37
- package/jest.config.js +0 -9
- package/src/bridges/cctp/__mocks__/asset.mock.ts +0 -15
- package/src/bridges/cctp/__mocks__/bridge-transfer.mock.ts +0 -48
- package/src/bridges/cctp/__mocks__/chain.mocks.ts +0 -33
- package/src/bridges/cctp/__mocks__/config.mock.ts +0 -45
- package/src/bridges/cctp/abis/erc20.ts +0 -117
- package/src/bridges/cctp/abis/message-transmitter.ts +0 -318
- package/src/bridges/cctp/abis/token-router.ts +0 -843
- package/src/bridges/cctp/factory.test.ts +0 -73
- package/src/bridges/cctp/factory.ts +0 -36
- package/src/bridges/cctp/handlers/estimate-gas.test.ts +0 -110
- package/src/bridges/cctp/handlers/estimate-gas.ts +0 -58
- package/src/bridges/cctp/handlers/get-assets.test.ts +0 -47
- package/src/bridges/cctp/handlers/get-assets.ts +0 -27
- package/src/bridges/cctp/handlers/get-fees.test.ts +0 -61
- package/src/bridges/cctp/handlers/get-fees.ts +0 -26
- package/src/bridges/cctp/handlers/track-transfer.test.ts +0 -779
- package/src/bridges/cctp/handlers/track-transfer.ts +0 -365
- package/src/bridges/cctp/handlers/transfer-asset.test.ts +0 -429
- package/src/bridges/cctp/handlers/transfer-asset.ts +0 -179
- package/src/bridges/cctp/index.ts +0 -1
- package/src/bridges/cctp/types/chain.ts +0 -9
- package/src/bridges/cctp/types/config.ts +0 -20
- package/src/bridges/cctp/utils/build-tx.ts +0 -30
- package/src/bridges/cctp/utils/config.test.ts +0 -49
- package/src/bridges/cctp/utils/config.ts +0 -36
- package/src/bridges/cctp/utils/transfer-data.test.ts +0 -83
- package/src/bridges/cctp/utils/transfer-data.ts +0 -48
- package/src/errors/bridge-error.ts +0 -11
- package/src/errors/bridge-initialization-error.ts +0 -9
- package/src/errors/bridge-unavailable-error.ts +0 -9
- package/src/errors/index.ts +0 -4
- package/src/errors/invalid-params-error.ts +0 -9
- package/src/index.ts +0 -3
- package/src/types/asset.ts +0 -26
- package/src/types/bridge.ts +0 -64
- package/src/types/chain.ts +0 -10
- package/src/types/config.ts +0 -10
- package/src/types/environment.ts +0 -4
- package/src/types/error.ts +0 -19
- package/src/types/index.ts +0 -9
- package/src/types/provider.ts +0 -12
- package/src/types/signer.ts +0 -18
- package/src/types/transfer.ts +0 -35
- package/src/unified-bridge-service.test.ts +0 -209
- package/src/unified-bridge-service.ts +0 -97
- package/src/utils/bridge-types.test.ts +0 -103
- package/src/utils/bridge-types.ts +0 -32
- package/src/utils/caip2.test.ts +0 -44
- package/src/utils/caip2.ts +0 -41
- package/src/utils/client.test.ts +0 -97
- package/src/utils/client.ts +0 -44
- package/src/utils/ensure-config.test.ts +0 -43
- package/src/utils/ensure-config.ts +0 -12
- package/src/utils/index.ts +0 -2
- package/src/utils/network-fee.test.ts +0 -24
- package/src/utils/network-fee.ts +0 -6
- package/src/utils/retry-promise.test.ts +0 -115
- package/src/utils/retry-promise.ts +0 -72
- package/src/utils/wait.test.ts +0 -33
- package/src/utils/wait.ts +0 -4
- package/tsconfig.jest.json +0 -7
- package/tsconfig.json +0 -9
- package/tsup.config.ts +0 -4
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
import { decodeEventLog, type Address } from 'viem';
|
|
2
|
-
import {
|
|
3
|
-
ErrorReason,
|
|
4
|
-
type BridgeConfig,
|
|
5
|
-
type BridgeService,
|
|
6
|
-
type BridgeTransfer,
|
|
7
|
-
type TrackingParams,
|
|
8
|
-
ErrorCode,
|
|
9
|
-
} from '../../../types';
|
|
10
|
-
import { getClientForChain } from '../../../utils/client';
|
|
11
|
-
import { TOKEN_ROUTER_ABI } from '../abis/token-router';
|
|
12
|
-
import { getNetworkFeeEVM } from '../../../utils/network-fee';
|
|
13
|
-
import { retryPromise, type Done } from '../../../utils/retry-promise';
|
|
14
|
-
import { getTrackingDelayByChainId } from '../utils/config';
|
|
15
|
-
import { InvalidParamsError } from '../../../errors';
|
|
16
|
-
|
|
17
|
-
// Maximum time (in ms) before the transaction is considered "timed out"
|
|
18
|
-
export const TRACKING_LIMIT_MS = 1000 * 60 * 60 * 3;
|
|
19
|
-
// The max blocks that can be queried before receiving an error response
|
|
20
|
-
export const MAX_BLOCKS = 1024n;
|
|
21
|
-
// The delay time before tracking starts
|
|
22
|
-
export const INITIAL_DELAY = 5000;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Mutates the `initial` transfer by merging it with the `updated` properties if they are not undefined
|
|
26
|
-
* Invokes the `updateListener` with a copy of the updated `initial` transfer
|
|
27
|
-
*/
|
|
28
|
-
const updateTransfer = (
|
|
29
|
-
initial: BridgeTransfer,
|
|
30
|
-
updated: Partial<BridgeTransfer>,
|
|
31
|
-
updateListener: TrackingParams['updateListener'],
|
|
32
|
-
) => {
|
|
33
|
-
Object.assign(initial, Object.fromEntries(Object.entries(updated).filter(([, value]) => value !== undefined)));
|
|
34
|
-
updateListener({ ...initial });
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Polls the source network until it's able to get the CCTP message's `nonce` from the source transaction's logs
|
|
39
|
-
* Updates the provided `BridgeTransfer` and broadcasts the changes via `updateListener`
|
|
40
|
-
*/
|
|
41
|
-
export const trackSourceTx = async (config: BridgeConfig, params: TrackingParams) => {
|
|
42
|
-
const { sourceProvider, targetProvider, updateListener, bridgeTransfer } = params;
|
|
43
|
-
const sourceClient = getClientForChain({ chain: bridgeTransfer.sourceChain, provider: sourceProvider });
|
|
44
|
-
const sourceChainData = config.find((chainData) => chainData.chainId === bridgeTransfer.sourceChain.chainId);
|
|
45
|
-
const targetClient = getClientForChain({ chain: bridgeTransfer.targetChain, provider: targetProvider });
|
|
46
|
-
const targetChainData = config.find((chainData) => chainData.chainId === bridgeTransfer.targetChain.chainId);
|
|
47
|
-
const updateableTransfer = { ...bridgeTransfer };
|
|
48
|
-
|
|
49
|
-
if (!sourceChainData || !targetChainData) {
|
|
50
|
-
throw new InvalidParamsError(ErrorReason.CHAIN_NOT_SUPPORTED);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const tracker = async (done: Done<BridgeTransfer>) => {
|
|
54
|
-
/**
|
|
55
|
-
* Return early if:
|
|
56
|
-
* - transfer has already completed successfully or due to some error
|
|
57
|
-
* - the transfer state already has the message's nonce
|
|
58
|
-
*/
|
|
59
|
-
if (updateableTransfer.completedAt || updateableTransfer.metadata?.nonce) {
|
|
60
|
-
return done(updateableTransfer);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Check if the transaction has timed out
|
|
65
|
-
*/
|
|
66
|
-
if (updateableTransfer.sourceStartedAt + TRACKING_LIMIT_MS <= Date.now()) {
|
|
67
|
-
updateTransfer(updateableTransfer, { completedAt: Date.now(), errorCode: ErrorCode.TIMEOUT }, updateListener);
|
|
68
|
-
return done(updateableTransfer);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Get the transaction's receipt.
|
|
73
|
-
* Throws if the transaction has't been processed by the network yet.
|
|
74
|
-
*/
|
|
75
|
-
const txReceipt = await sourceClient.getTransactionReceipt({
|
|
76
|
-
hash: updateableTransfer.sourceTxHash as Address,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Calculate the network fee if needed.
|
|
81
|
-
*/
|
|
82
|
-
if (!updateableTransfer.sourceNetworkFee) {
|
|
83
|
-
const tx = await sourceClient.getTransaction({ hash: updateableTransfer.sourceTxHash as Address });
|
|
84
|
-
const networkFee = getNetworkFeeEVM(tx, txReceipt);
|
|
85
|
-
|
|
86
|
-
if (networkFee) {
|
|
87
|
-
updateTransfer(updateableTransfer, { sourceNetworkFee: networkFee }, updateListener);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Update the state and terminate if the transaction was reverted
|
|
93
|
-
*/
|
|
94
|
-
if (txReceipt.status === 'reverted') {
|
|
95
|
-
updateTransfer(
|
|
96
|
-
updateableTransfer,
|
|
97
|
-
{ completedAt: Date.now(), errorCode: ErrorCode.TRANSACTION_REVERTED },
|
|
98
|
-
updateListener,
|
|
99
|
-
);
|
|
100
|
-
return done(updateableTransfer);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Check the confirmation count.
|
|
105
|
-
* - update the sourceConfirmationCount if it increased
|
|
106
|
-
* - update the startBlockNumber if confirmation count increased but is not enough
|
|
107
|
-
* - keeps polling until it's greater than requiredSourceConfirmationCount
|
|
108
|
-
*/
|
|
109
|
-
const confirmationCount = await sourceClient.getTransactionConfirmations({
|
|
110
|
-
hash: updateableTransfer.sourceTxHash as Address,
|
|
111
|
-
});
|
|
112
|
-
const hasMoreConfirmations = confirmationCount > updateableTransfer.sourceConfirmationCount;
|
|
113
|
-
const hasRequiredConfirmations = confirmationCount >= updateableTransfer.requiredSourceConfirmationCount;
|
|
114
|
-
|
|
115
|
-
if (hasMoreConfirmations) {
|
|
116
|
-
const changes = {} as Partial<BridgeTransfer>;
|
|
117
|
-
changes.sourceConfirmationCount = Number(confirmationCount);
|
|
118
|
-
|
|
119
|
-
if (!hasRequiredConfirmations) {
|
|
120
|
-
changes.startBlockNumber = await targetClient.getBlockNumber();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
updateTransfer(updateableTransfer, changes, updateListener);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (!hasRequiredConfirmations) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (!updateableTransfer.startBlockNumber) {
|
|
131
|
-
updateTransfer(updateableTransfer, { startBlockNumber: await targetClient.getBlockNumber() }, updateListener);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Get the `TransferTokens` event's log entry from the receipt
|
|
136
|
-
*/
|
|
137
|
-
const transferEventLog = txReceipt.logs.find((log) => {
|
|
138
|
-
if (log.address.toLowerCase() === sourceChainData.tokenRouterAddress.toLowerCase()) {
|
|
139
|
-
const event = decodeEventLog({
|
|
140
|
-
abi: TOKEN_ROUTER_ABI,
|
|
141
|
-
...log,
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
return event.eventName === 'TransferTokens';
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return false;
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
if (!transferEventLog) {
|
|
151
|
-
throw new InvalidParamsError(
|
|
152
|
-
ErrorReason.INVALID_PARAMS,
|
|
153
|
-
`unable to find a TransferTokens event in source transaction "${updateableTransfer.sourceTxHash}"`,
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Get the nonce used by the message transmitter from the event's log
|
|
159
|
-
* https://developers.circle.com/stablecoins/docs/evm-smart-contracts#receivemessage
|
|
160
|
-
*/
|
|
161
|
-
const transferEvent = decodeEventLog({
|
|
162
|
-
abi: TOKEN_ROUTER_ABI,
|
|
163
|
-
eventName: 'TransferTokens',
|
|
164
|
-
...transferEventLog,
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// save the nonce and broadcast
|
|
168
|
-
const nonce = transferEvent.args.nonce;
|
|
169
|
-
updateTransfer(updateableTransfer, { targetStartedAt: Date.now(), metadata: { nonce } }, updateListener);
|
|
170
|
-
return done(updateableTransfer);
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
return retryPromise<BridgeTransfer>({
|
|
174
|
-
promise: tracker,
|
|
175
|
-
delay: getTrackingDelayByChainId(sourceChainData.chainId),
|
|
176
|
-
startAfter: INITIAL_DELAY,
|
|
177
|
-
});
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Polls the target network until it finds the transaction that matches the message's nonce
|
|
182
|
-
* Updates the provided `BridgeTransfer` and broadcasts the changes via `updateListener`
|
|
183
|
-
*/
|
|
184
|
-
export const trackTargetTx = async (config: BridgeConfig, params: TrackingParams) => {
|
|
185
|
-
const { targetProvider, updateListener, bridgeTransfer } = params;
|
|
186
|
-
const updateableTransfer = { ...bridgeTransfer };
|
|
187
|
-
|
|
188
|
-
if (!bridgeTransfer.completedAt && !bridgeTransfer.metadata?.nonce) {
|
|
189
|
-
throw new InvalidParamsError(ErrorReason.INVALID_PARAMS, `nonce is missing`);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (!bridgeTransfer.startBlockNumber) {
|
|
193
|
-
throw new InvalidParamsError(ErrorReason.INVALID_PARAMS, `startBlockNumber is missing`);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const targetClient = getClientForChain({ chain: bridgeTransfer.targetChain, provider: targetProvider });
|
|
197
|
-
const targetChainData = config.find((chainData) => chainData.chainId === bridgeTransfer.targetChain.chainId);
|
|
198
|
-
|
|
199
|
-
if (!targetChainData) {
|
|
200
|
-
throw new InvalidParamsError(
|
|
201
|
-
ErrorReason.INVALID_PARAMS,
|
|
202
|
-
`unknown target chain "${bridgeTransfer.targetChain.chainId}"`,
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const tracker = async (done: Done<BridgeTransfer>) => {
|
|
207
|
-
/**
|
|
208
|
-
* Return early if:
|
|
209
|
-
* - transfer has already completed successfully or due to some error
|
|
210
|
-
*/
|
|
211
|
-
if (updateableTransfer.completedAt) {
|
|
212
|
-
return done(updateableTransfer);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Check if `startBlockNumber` became falsy for whatever reason
|
|
217
|
-
*/
|
|
218
|
-
if (!updateableTransfer.startBlockNumber) {
|
|
219
|
-
updateTransfer(
|
|
220
|
-
updateableTransfer,
|
|
221
|
-
{ completedAt: Date.now(), errorCode: ErrorCode.INVALID_PARAMS },
|
|
222
|
-
updateListener,
|
|
223
|
-
);
|
|
224
|
-
return done(updateableTransfer);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Check if the transaction has timed out
|
|
229
|
-
*/
|
|
230
|
-
if (updateableTransfer.sourceStartedAt + TRACKING_LIMIT_MS <= Date.now()) {
|
|
231
|
-
updateTransfer(updateableTransfer, { completedAt: Date.now(), errorCode: ErrorCode.TIMEOUT }, updateListener);
|
|
232
|
-
return done(updateableTransfer);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (!updateableTransfer.targetTxHash) {
|
|
236
|
-
const lastBlockNumber = await targetClient.getBlockNumber();
|
|
237
|
-
const lowestBlockNumber = updateableTransfer.startBlockNumber - MAX_BLOCKS;
|
|
238
|
-
const fromBlock = lowestBlockNumber >= 0n ? lowestBlockNumber : 'earliest';
|
|
239
|
-
const highestBlockNumber = updateableTransfer.startBlockNumber + MAX_BLOCKS;
|
|
240
|
-
const toBlock = highestBlockNumber < lastBlockNumber ? highestBlockNumber : 'latest';
|
|
241
|
-
|
|
242
|
-
const targetLogs = await targetClient.getLogs({
|
|
243
|
-
address: targetChainData.messageTransmitterAddress,
|
|
244
|
-
event: {
|
|
245
|
-
name: 'MessageReceived',
|
|
246
|
-
type: 'event',
|
|
247
|
-
inputs: [
|
|
248
|
-
{ indexed: true, internalType: 'address', name: 'caller', type: 'address' },
|
|
249
|
-
{ indexed: false, internalType: 'uint32', name: 'sourceDomain', type: 'uint32' },
|
|
250
|
-
{ indexed: true, internalType: 'uint64', name: 'nonce', type: 'uint64' },
|
|
251
|
-
{ indexed: false, internalType: 'bytes32', name: 'sender', type: 'bytes32' },
|
|
252
|
-
{ indexed: false, internalType: 'bytes', name: 'messageBody', type: 'bytes' },
|
|
253
|
-
],
|
|
254
|
-
},
|
|
255
|
-
args: { nonce: updateableTransfer.metadata!.nonce as bigint },
|
|
256
|
-
fromBlock,
|
|
257
|
-
toBlock,
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
if (targetLogs[0]?.transactionHash) {
|
|
261
|
-
updateTransfer(updateableTransfer, { targetTxHash: targetLogs[0].transactionHash }, updateListener);
|
|
262
|
-
} else {
|
|
263
|
-
updateTransfer(updateableTransfer, { startBlockNumber: lastBlockNumber }, updateListener);
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Get the transaction's receipt.
|
|
270
|
-
* Throws if the transaction has't been processed by the network yet.
|
|
271
|
-
*/
|
|
272
|
-
const txReceipt = await targetClient.getTransactionReceipt({
|
|
273
|
-
hash: updateableTransfer.targetTxHash as Address,
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Calculate the network fee if needed.
|
|
278
|
-
*/
|
|
279
|
-
if (!updateableTransfer.targetNetworkFee) {
|
|
280
|
-
const tx = await targetClient.getTransaction({ hash: updateableTransfer.targetTxHash as Address });
|
|
281
|
-
const networkFee = getNetworkFeeEVM(tx, txReceipt);
|
|
282
|
-
|
|
283
|
-
if (networkFee) {
|
|
284
|
-
updateTransfer(updateableTransfer, { targetNetworkFee: networkFee }, updateListener);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Update the state and terminate if the transaction was reverted
|
|
290
|
-
*/
|
|
291
|
-
if (txReceipt.status === 'reverted') {
|
|
292
|
-
updateTransfer(
|
|
293
|
-
updateableTransfer,
|
|
294
|
-
{ completedAt: Date.now(), errorCode: ErrorCode.TRANSACTION_REVERTED },
|
|
295
|
-
updateListener,
|
|
296
|
-
);
|
|
297
|
-
return done(updateableTransfer);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Check the confirmation count.
|
|
302
|
-
* - update the targetConfirmationCount if it increased
|
|
303
|
-
* - keeps polling until it's greater than requiredTargetConfirmationCount
|
|
304
|
-
*/
|
|
305
|
-
const confirmationCount = await targetClient.getTransactionConfirmations({
|
|
306
|
-
hash: updateableTransfer.targetTxHash as Address,
|
|
307
|
-
});
|
|
308
|
-
const hasMoreConfirmations = confirmationCount > updateableTransfer.targetConfirmationCount;
|
|
309
|
-
const hasRequiredConfirmations = confirmationCount >= updateableTransfer.requiredTargetConfirmationCount;
|
|
310
|
-
|
|
311
|
-
if (hasMoreConfirmations) {
|
|
312
|
-
updateTransfer(updateableTransfer, { targetConfirmationCount: Number(confirmationCount) }, updateListener);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if (!hasRequiredConfirmations) {
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
updateTransfer(updateableTransfer, { completedAt: Date.now() }, updateListener);
|
|
320
|
-
return done(updateableTransfer);
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
return retryPromise<BridgeTransfer>({
|
|
324
|
-
promise: tracker,
|
|
325
|
-
delay: getTrackingDelayByChainId(targetChainData.chainId),
|
|
326
|
-
startAfter: INITIAL_DELAY,
|
|
327
|
-
});
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
export function trackTransfer(bridge: BridgeService, params: TrackingParams) {
|
|
331
|
-
let abortFn: (() => void) | undefined;
|
|
332
|
-
|
|
333
|
-
const cancel = () => {
|
|
334
|
-
abortFn?.();
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
const executeTracking = async () => {
|
|
338
|
-
await bridge.ensureHasConfig();
|
|
339
|
-
|
|
340
|
-
const { sourceProvider, targetProvider, updateListener, bridgeTransfer } = params;
|
|
341
|
-
|
|
342
|
-
const { result: sourceTracker, cancel: cancelSourceTracking } = await trackSourceTx(bridge.config!, {
|
|
343
|
-
sourceProvider,
|
|
344
|
-
targetProvider,
|
|
345
|
-
updateListener,
|
|
346
|
-
bridgeTransfer,
|
|
347
|
-
});
|
|
348
|
-
abortFn = cancelSourceTracking;
|
|
349
|
-
const transferAfterSourceFinished = await sourceTracker;
|
|
350
|
-
|
|
351
|
-
const { result: targetTracker, cancel: cancelTargetTracking } = await trackTargetTx(bridge.config!, {
|
|
352
|
-
sourceProvider,
|
|
353
|
-
targetProvider,
|
|
354
|
-
updateListener,
|
|
355
|
-
bridgeTransfer: transferAfterSourceFinished,
|
|
356
|
-
});
|
|
357
|
-
abortFn = cancelTargetTracking;
|
|
358
|
-
return targetTracker;
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
return {
|
|
362
|
-
result: executeTracking(),
|
|
363
|
-
cancel,
|
|
364
|
-
};
|
|
365
|
-
}
|