@avalabs/bridge-unified 1.0.1 → 2.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.
Files changed (76) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/.turbo/turbo-test.log +25 -0
  4. package/CHANGELOG.md +12 -0
  5. package/README.md +137 -71
  6. package/dist/index.cjs +11 -3
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +207 -34
  9. package/dist/index.d.ts +207 -34
  10. package/dist/index.js +4 -3
  11. package/dist/index.js.map +1 -1
  12. package/jest.config.js +9 -0
  13. package/package.json +15 -9
  14. package/src/bridges/cctp/__mocks__/asset.mock.ts +15 -0
  15. package/src/bridges/cctp/__mocks__/bridge-transfer.mock.ts +48 -0
  16. package/src/bridges/cctp/__mocks__/chain.mocks.ts +31 -0
  17. package/src/bridges/cctp/__mocks__/config.mock.ts +42 -0
  18. package/src/bridges/cctp/abis/erc20.ts +117 -0
  19. package/src/bridges/cctp/abis/message-transmitter.ts +318 -0
  20. package/src/bridges/cctp/abis/token-router.ts +843 -0
  21. package/src/bridges/cctp/factory.test.ts +73 -0
  22. package/src/bridges/cctp/factory.ts +32 -0
  23. package/src/bridges/cctp/handlers/get-assets.test.ts +47 -0
  24. package/src/bridges/cctp/handlers/get-assets.ts +27 -0
  25. package/src/bridges/cctp/handlers/get-fees.test.ts +61 -0
  26. package/src/bridges/cctp/handlers/get-fees.ts +26 -0
  27. package/src/bridges/cctp/handlers/track-transfer.test.ts +775 -0
  28. package/src/bridges/cctp/handlers/track-transfer.ts +365 -0
  29. package/src/bridges/cctp/handlers/transfer-asset.test.ts +429 -0
  30. package/src/bridges/cctp/handlers/transfer-asset.ts +179 -0
  31. package/src/bridges/cctp/index.ts +1 -0
  32. package/src/bridges/cctp/types/chain.ts +4 -0
  33. package/src/bridges/cctp/types/config.ts +19 -0
  34. package/src/bridges/cctp/utils/config.test.ts +49 -0
  35. package/src/bridges/cctp/utils/config.ts +36 -0
  36. package/src/bridges/cctp/utils/transfer-data.test.ts +83 -0
  37. package/src/bridges/cctp/utils/transfer-data.ts +48 -0
  38. package/src/errors/bridge-error.ts +11 -0
  39. package/src/errors/bridge-initialization-error.ts +9 -0
  40. package/src/errors/bridge-unavailable-error.ts +9 -0
  41. package/src/errors/index.ts +4 -20
  42. package/src/errors/invalid-params-error.ts +9 -0
  43. package/src/index.ts +3 -1
  44. package/src/types/asset.ts +26 -0
  45. package/src/types/bridge.ts +63 -0
  46. package/src/types/chain.ts +10 -0
  47. package/src/types/config.ts +10 -0
  48. package/src/types/environment.ts +4 -0
  49. package/src/types/error.ts +19 -0
  50. package/src/types/index.ts +9 -0
  51. package/src/types/provider.ts +12 -0
  52. package/src/types/signer.ts +18 -0
  53. package/src/types/transfer.ts +35 -0
  54. package/src/unified-bridge-service.test.ts +208 -0
  55. package/src/unified-bridge-service.ts +90 -0
  56. package/src/utils/bridge-types.test.ts +103 -0
  57. package/src/utils/bridge-types.ts +32 -0
  58. package/src/utils/caip2.test.ts +44 -0
  59. package/src/utils/caip2.ts +41 -0
  60. package/src/utils/client.test.ts +97 -0
  61. package/src/utils/client.ts +44 -0
  62. package/src/utils/ensure-config.test.ts +43 -0
  63. package/src/utils/ensure-config.ts +12 -0
  64. package/src/utils/index.ts +2 -0
  65. package/src/utils/network-fee.test.ts +24 -0
  66. package/src/utils/network-fee.ts +6 -0
  67. package/src/utils/retry-promise.test.ts +115 -0
  68. package/src/utils/retry-promise.ts +72 -0
  69. package/src/utils/wait.test.ts +33 -0
  70. package/src/utils/wait.ts +4 -0
  71. package/tsconfig.jest.json +7 -0
  72. package/tsconfig.json +2 -1
  73. package/src/bridge-service.ts +0 -18
  74. package/src/handlers/get-bridge-router.ts +0 -25
  75. package/src/handlers/submit-and-watch-bridge-transaction.ts +0 -1
  76. package/src/handlers/submit-bridge-transaction-step.ts +0 -22
@@ -1,5 +1,5 @@
1
1
 
2
- > @avalabs/bridge-unified@1.0.1 build /home/runner/work/consumer-sdks/consumer-sdks/packages/bridge-unified
2
+ > @avalabs/bridge-unified@2.0.0 build /home/runner/work/consumer-sdks/consumer-sdks/packages/bridge-unified
3
3
  > tsup
4
4
 
5
5
  CLI Building entry: ./src/index.ts
@@ -10,13 +10,13 @@
10
10
  CLI Cleaning output folder
11
11
  CJS Build start
12
12
  ESM Build start
13
- CJS dist/index.cjs 473.00 B
14
- CJS dist/index.cjs.map 3.67 KB
15
- CJS ⚡️ Build success in 464ms
16
- ESM dist/index.js 459.00 B
17
- ESM dist/index.js.map 3.67 KB
18
- ESM ⚡️ Build success in 464ms
13
+ ESM dist/index.js 22.99 KB
14
+ ESM dist/index.js.map 83.05 KB
15
+ ESM ⚡️ Build success in 1654ms
16
+ CJS dist/index.cjs 23.01 KB
17
+ CJS dist/index.cjs.map 83.05 KB
18
+ CJS ⚡️ Build success in 1661ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 7247ms
21
- DTS dist/index.d.cts 1.23 KB
22
- DTS dist/index.d.ts 1.23 KB
20
+ DTS ⚡️ Build success in 10867ms
21
+ DTS dist/index.d.cts 5.90 KB
22
+ DTS dist/index.d.ts 5.90 KB
@@ -1,4 +1,4 @@
1
1
 
2
- > @avalabs/bridge-unified@1.0.1 lint /home/runner/work/consumer-sdks/consumer-sdks/packages/bridge-unified
2
+ > @avalabs/bridge-unified@2.0.0 lint /home/runner/work/consumer-sdks/consumer-sdks/packages/bridge-unified
3
3
  > eslint "src/**/*.ts"
4
4
 
@@ -0,0 +1,25 @@
1
+
2
+ > @avalabs/bridge-unified@2.0.0 test /home/runner/work/consumer-sdks/consumer-sdks/packages/bridge-unified
3
+ > jest
4
+
5
+ PASS src/bridges/cctp/handlers/track-transfer.test.ts (12.34 s)
6
+ PASS src/bridges/cctp/handlers/transfer-asset.test.ts
7
+ PASS src/unified-bridge-service.test.ts
8
+ PASS src/utils/retry-promise.test.ts
9
+ PASS src/bridges/cctp/utils/transfer-data.test.ts
10
+ PASS src/utils/bridge-types.test.ts
11
+ PASS src/utils/client.test.ts
12
+ PASS src/bridges/cctp/factory.test.ts
13
+ PASS src/bridges/cctp/handlers/get-fees.test.ts
14
+ PASS src/bridges/cctp/utils/config.test.ts
15
+ PASS src/utils/ensure-config.test.ts
16
+ PASS src/utils/caip2.test.ts
17
+ PASS src/bridges/cctp/handlers/get-assets.test.ts
18
+ PASS src/utils/network-fee.test.ts
19
+ PASS src/utils/wait.test.ts
20
+
21
+ Test Suites: 15 passed, 15 total
22
+ Tests: 82 passed, 82 total
23
+ Snapshots: 0 total
24
+ Time: 21.418 s
25
+ Ran all test suites.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @avalabs/unified-bridge
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 7df7ca0: CCTP integration
8
+
9
+ ### Minor Changes
10
+
11
+ - 7df7ca0: use caip2 chain ids
12
+ - 54757d4: Make sourceProvider optional, add bridged asset denomination info
13
+ - b8f102b: update and validate startBlockNumber while tracking
14
+
3
15
  ## 1.0.1
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -1,92 +1,158 @@
1
- <br/>
2
-
3
1
  <p align="center">
4
2
  <a href="https://subnets.avax.network/">
5
3
  <picture>
6
4
  <img alt="Avalanche Logo" src="https://images.ctfassets.net/gcj8jwzm6086/Gse8dqDEnJtT87RsbbEf4/1609daeb09e9db4a6617d44623028356/Avalanche_Horizontal_White.svg" width="auto" height="60">
7
5
  </picture>
8
- </a>
6
+ </a>
9
7
  </p>
10
8
 
11
9
  <p align="center">
12
- Parse arbitrary VM data for display in the Avalanche Subnet Explorer.
10
+ A package for routing tokens from Chain A to Chain B, and unifying multiple bridge tools into one.
13
11
  <p>
14
12
 
15
- <br>
13
+ ## What is this?
14
+
15
+ The bridging ecosystem is complex. There are often multiple tools that can be used to bridge tokens from one chain to another, and sometimes to get a token from chain A to C you need to use multiple bridging tools and route through chain B first. This package simplifies that process by creating the _Unified Bridge API_, a standard interface for bridging tokens from one chain to another without having to worry about the underlying tools or the underlying intermediary chains.
16
+
17
+ These are the bridges we currently support:
18
+
19
+ - **CCTP** - preferred for brdiging USDC between Ethereum and Avalanche C-Chain. See the `bridges/cctp` folder.
16
20
 
17
- ## Supported VMs
21
+ Future bridges we plan to support:
18
22
 
19
- - MoveVM
23
+ - **Avalanche Bridge** - is capable of transferring a fixed list of tokens between Ethereum and Avalanche C-Chain.
24
+ - **Teleporter** - for moving tokens between subnets.
25
+ - **Cross-Chain Transfer** - for moving tokens between the three Avalanche Primary Network chains (X-Chain, C-Chain, and P-Chain).
20
26
 
21
27
  ## Getting Started
22
28
 
23
29
  ```sh
24
- npm install @avalabs/vm-parser
30
+ npm install @avalabs/bridge-unified
25
31
  # or
26
- yarn add @avalabs/vm-parser
32
+ yarn add @avalabs/bridge-unified
27
33
  # or
28
- pnpm add @avalabs/vm-parser
34
+ pnpm add @avalabs/bridge-unified
29
35
  ```
30
36
 
31
- ## Overview
32
-
33
- ```tsx
34
- // 1. Import modules.
35
- import { createMoveVmConfig, DataDisplayFormat } from '@avalabs/vm-parser';
36
- import {
37
- Card,
38
- CardTitle,
39
- CardContent,
40
- Chip,
41
- TableContainer,
42
- Table,
43
- TableBody,
44
- TableRow,
45
- TableCell,
46
- } from 'some-ui-library';
47
- import useSWR from 'swr'; // Or your preferred data fetching library
48
-
49
- const MOVE_RPC_URL =
50
- 'https://seed-node1-rpc.movementlabs.xyz/ext/bc/2gLyawqthdiyrJktJmdnDAb1XVc6xwJXU6iJKu3Uwj21F2mXAK/rpc';
51
- // 2. Set up your config
52
- const moveVmConfig = createMoveVmConfig(MOVE_RPC_URL);
53
-
54
- const TransactionDetails = ({ txId }: { txId: string }) => {
55
- // 2. Get the data from the config's `getPageData` function
56
- const { data } = useSWR(txId, moveVmConfig.transactionDetails.getPageData);
57
-
58
- // 3. Display the data dynamically based on the config's displayFormat.
59
- return (
60
- <>
61
- {moveVmConfig.displayFormat.map(({ sectionTitle, fields }) => (
62
- <Card>
63
- <CardTitle>{sectionTitle}</CardTitle>
64
- <CardContent>
65
- <TableContainer>
66
- <Table>
67
- <TableBody>
68
- {fields.map(({ name, displayValue, displayFormat }) => (
69
- <TableRow>
70
- <TableCell>{field.name}</TableCell>
71
- <TableCell>
72
- /* Display the field differently depending on its display formatter */
73
- {field.displayFormat === DataDisplayFormat.CHIP ? (
74
- <Chip>{field.displayValue}</Chip>
75
- ) : field.displayFormat === DataDisplayFormat.DATETIME ? (
76
- new Date(field.displayValue).toLocaleString()
77
- ) : (
78
- fields.displayValue
79
- )}
80
- </TableCell>
81
- </TableRow>
82
- ))}
83
- </TableBody>
84
- </Table>
85
- </TableContainer>
86
- </CardContent>
87
- </Card>
88
- ))}
89
- </>
90
- );
91
- };
37
+ ## Usage
38
+
39
+ ```js
40
+ import { createUnifiedBridgeService, Environment, BridgeTransfer } from '@avalabs/bridge-unified';
41
+
42
+ // create a new service for an environment
43
+ const unifiedService = createUnifiedBridgeService({
44
+ environment: Environment.TEST,
45
+ });
46
+
47
+ // init the service, fetch and setup its configs
48
+ await unifiedService.init();
49
+
50
+ // get the list of supported assets, grouped by caip2 (https://chainagnostic.org/CAIPs/caip-2) chain IDs
51
+ const assets = await unifiedService.getAssets()
52
+
53
+ // get the bridge fee(s) of the provided transfer
54
+ const fees = await unifiedService.getFees({...})
55
+
56
+ // start a new bridge transfer and store its state
57
+ const bridgeTransfer = await unifiedService.transferAsset({...})
58
+
59
+ // create an update listener for tracking
60
+ const updateListener = (transfer: BridgeTransfer) => {
61
+ console.log(transfer)
62
+ }
63
+
64
+ // start tracking the transfer's state. whenever the state changes, it will call the provided `updateListener`
65
+ const { cancel, result } = await unifiedService.trackTransfer({bridgeTransfer, updateListener, ...})
66
+
67
+ // immediatelly stops tracking and rejects the tracker's promise
68
+ // cancel()
69
+
70
+ // wait for the transfer to finish and get its final state
71
+ const finalizedBridgeTransfer = await result
92
72
  ```
73
+
74
+ ## API
75
+
76
+ ### createUnifiedBridgeService({ environment, disabledBridgeTypes? })
77
+
78
+ Returns a new `unifiedBridgeService` for the given `environment`, using all supported bridge integrations by default. Individual bridges can be turned off via the `disabledBridgeTypes` array.
79
+
80
+ #### environment
81
+
82
+ Type: `Environment`
83
+
84
+ Defines if the bridge service should use `testnet` or `mainnet`.
85
+
86
+ #### disabledBridgeTypes
87
+
88
+ Type: `BridgeType[] | undefined`
89
+
90
+ Disables the integration of the provided `BridgeType`s.
91
+
92
+ ### unifiedBridgeService
93
+
94
+ Contains all the required properties and methods to prepare, initiate or track a bridge transfer.
95
+ Automatically picks the right (enabled) bridge integration to use based on the provided params.
96
+
97
+ ```js
98
+ {
99
+ environment, // the provided Environment during initialization
100
+ bridges, // the list of enabled bridge integrations
101
+ init,
102
+ updateConfigs,
103
+ getAssets,
104
+ getFees,
105
+ transferAsset,
106
+ trackTransfer,
107
+ }
108
+ ```
109
+
110
+ #### init
111
+
112
+ Type: `() => Promise<void>`
113
+
114
+ Initializes the unified service by attempting to fetch the configurations of the enabled bridges.
115
+
116
+ #### updateConfigs
117
+
118
+ Type: `() => Promise<void>`
119
+
120
+ Attempts to fetch the configurations of the enabled bridges.
121
+
122
+ #### getAssets
123
+
124
+ Type: `() => Promise<ChainAssetMap>`
125
+
126
+ Returns the aggregated list of assets supported by the enabled bridges grouped by [caip2](https://chainagnostic.org/CAIPs/caip-2) chain IDs.
127
+
128
+ #### getFees
129
+
130
+ Type: `(params: FeeParams) => Promise<AssetFeeMap>`
131
+
132
+ Calculates and returns the bridge fees in `tokenAddress` - `amount` pairs for a given bridge transfer.
133
+
134
+ #### transferAsset
135
+
136
+ Type: `(params: TransferParams) => Promise<BridgeTransfer>`
137
+
138
+ Starts a new bridge transfer, executing every required step in a single call.
139
+ Transactions signing is done by either the provided `sourceProvider` or a custom `sign` callback. Clients using their custom `sign` implementation may use their own solution or the default `dispatch` callback to submit the transaction to the network.
140
+ Returns a `BridgeTransfer` containing all the (known) initial values such as: environment, addresses, amount, fee, transaction hash, required and actual block confirmation counts, etc.
141
+
142
+ #### trackTransfer
143
+
144
+ Type: `(params: TrackingParams) => ({cancel, result})`
145
+
146
+ Tracks the given `BridgeTransfer`'s progress and invokes the provided listener callback whenever a change happens.
147
+
148
+ ###### cancel
149
+
150
+ Type: `() => void`
151
+
152
+ If it's still pending, rejects the tracker's promise (`result`) immediatelly and breaks its loop under the hood.
153
+
154
+ ###### result
155
+
156
+ Type: `Promise<BridgeTransfer>`
157
+
158
+ Resolves with the finalized `BridgeTransfer` (if not canceled before).
package/dist/index.cjs CHANGED
@@ -1,9 +1,17 @@
1
1
  'use strict';
2
2
 
3
- require('viem');
3
+ var viem = require('viem');
4
+ var lodash = require('lodash');
4
5
 
5
- var t=class extends Error{constructor(a,m){super(a);this.code=m;this.code=m;}},e=class extends t{constructor(o="Not implemented"){super(o,5001),this.name="NotImplementedError";}};var n=async r=>{throw new e};var i=r=>{throw new e};var s=()=>{};var v=r=>({getBridgeRouter:i,submitBridgeTransactionStep:n,submitAndWatchBridgeTransaction:s});
6
+ var H=(r=>(r.NATIVE="native",r.ERC20="erc20",r))(H||{});var E=(t=>(t.CCTP="cctp",t))(E||{}),V=(r=>(r.AllowanceApproval="allowance-approval",r.TokensTransfer="tokens-transfer",r))(V||{});var K=(r=>(r.PROD="production",r.TEST="test",r))(K||{});var R=(n=>(n[n.BRIDGE_NOT_AVAILABLE=5001]="BRIDGE_NOT_AVAILABLE",n[n.INITIALIZATION_FAILED=5002]="INITIALIZATION_FAILED",n[n.INVALID_PARAMS=5003]="INVALID_PARAMS",n[n.TIMEOUT=5004]="TIMEOUT",n[n.TRANSACTION_REVERTED=5005]="TRANSACTION_REVERTED",n))(R||{}),w=(i=>(i.UNKNOWN="UNKNOWN",i.CONFIG_NOT_AVAILABLE="CONFIG_NOT_AVAILABLE",i.INVALID_PARAMS="INVALID_PARAMS",i.IDENTICAL_CHAINS_PROVIDED="IDENTICAL_CHAINS_PROVIDED",i.INCORRECT_AMOUNT_PROVIDED="INCORRECT_AMOUNT_PROVIDED",i.INCORRECT_ADDRESS_PROVIDED="INCORRECT_ADDRESS_PROVIDED",i.CHAIN_NOT_SUPPORTED="CHAIN_NOT_SUPPORTED",i.ASSET_NOT_SUPPORTED="ASSET_NOT_SUPPORTED",i.CONFIRMATION_COUNT_UNKNOWN="CONFIRMATION_COUNT_UNKNOWN",i))(w||{});var N=class extends Error{constructor(r,a,p){super(r);this.code=a;this.details=p;}};var P=class extends N{constructor(t="UNKNOWN",r){super(t,5001,r),this.name="BridgeUnavailableError";}};var B=class extends N{constructor(t="UNKNOWN",r){super(t,5002,r),this.name="BridgeInitializationError";}};var T=class extends N{constructor(t="INVALID_PARAMS",r){super(t,5003,r),this.name="InvalidParamsError";}};var ae={test:"https://raw.githubusercontent.com/ava-labs/avalanche-bridge-resources/main/cctp/cctp_config.test.json",production:"https://raw.githubusercontent.com/ava-labs/avalanche-bridge-resources/main/cctp/cctp_config.json"},q=async e=>{try{return (await(await fetch(ae[e])).json()).map(a=>({...a,chainId:`eip155:${a.chainId}`}))}catch(t){throw new B("CONFIG_NOT_AVAILABLE",`Error while fetching CCTP config: ${t.message}`)}},M=e=>{switch(e){case"eip155:43114":case"eip155:43113":return 1e3;default:return 2e4}};async function $(e){await e.ensureHasConfig();let t=e.config.map(r=>r.chainId);return e.config.reduce((r,a)=>(r[a.chainId]=a.tokens.map(p=>({...p,type:"erc20",destinations:t.reduce((n,o)=>(a.chainId!==o&&(n[o]||(n[o]=[]),n[o]?.push("cctp")),n),{})})),r),{})}var se="^[-a-z0-9]{3,8}$",ie="^[-_a-zA-Z0-9]{1,50}$",G=":",oe=e=>{let[t,r]=e.split(G);if(!t||!r)throw new Error("Invalid identifier provided.");if(!new RegExp(se).test(t))throw new Error("Invalid namespace provided.");if(!new RegExp(ie).test(r))throw new Error("Invalid reference provided.");return {namespace:t,reference:r}},pe=({namespace:e,reference:t})=>`${e}${G}${t}`,S={toJSON:oe,toString:pe};var le=e=>{let{reference:t}=S.toJSON(e.chainId);return {id:Number(t),name:e.chainName,nativeCurrency:{decimals:e.networkToken.decimals,symbol:e.networkToken.symbol,name:e.networkToken.name},network:e.chainName,rpcUrls:{default:{http:[e.rpcUrl]},public:{http:[e.rpcUrl]}},...e.utilityAddresses?.multicall&&{contracts:{multicall3:{address:e.utilityAddresses.multicall}}}}},I=({chain:e,provider:t})=>{let r=le(e),a=t?viem.custom(t):viem.http(e.rpcUrl,{batch:!0,retryCount:0});return viem.createWalletClient({chain:r,transport:a}).extend(viem.publicActions)};var x=[{inputs:[{internalType:"address",name:"circleTokenMessenger_",type:"address"},{internalType:"address",name:"burnToken_",type:"address"}],stateMutability:"nonpayable",type:"constructor"},{inputs:[],name:"AlreadyAdmin",type:"error"},{inputs:[],name:"AlreadyFeeCollector",type:"error"},{inputs:[],name:"AlreadySupportedBurnToken",type:"error"},{inputs:[],name:"AmountLessThanFee",type:"error"},{inputs:[],name:"BalanceNotIncreased",type:"error"},{inputs:[],name:"CannotRemoveLastAdmin",type:"error"},{inputs:[],name:"FeePercentageGreaterThanMax",type:"error"},{inputs:[],name:"InvalidAdminAddress",type:"error"},{inputs:[],name:"InvalidFeeCollector",type:"error"},{inputs:[],name:"InvalidMintRecipientAddress",type:"error"},{inputs:[],name:"InvalidTokenAddress",type:"error"},{inputs:[],name:"InvalidTokenMessengerAddress",type:"error"},{inputs:[],name:"MaxFeeLessThanMinFee",type:"error"},{inputs:[],name:"NotAdmin",type:"error"},{inputs:[],name:"NotFeeCollector",type:"error"},{inputs:[],name:"UnSupportedBurnToken",type:"error"},{inputs:[],name:"UnsupportedDomain",type:"error"},{anonymous:!1,inputs:[{indexed:!1,internalType:"address",name:"admin",type:"address"}],name:"AdminAdded",type:"event"},{anonymous:!1,inputs:[{indexed:!1,internalType:"address",name:"admin",type:"address"}],name:"AdminRemoved",type:"event"},{anonymous:!1,inputs:[{indexed:!1,internalType:"address",name:"token",type:"address"}],name:"BurnTokenAdded",type:"event"},{anonymous:!1,inputs:[{indexed:!1,internalType:"address",name:"token",type:"address"}],name:"BurnTokenRemoved",type:"event"},{anonymous:!1,inputs:[{indexed:!1,internalType:"address",name:"feeCollector",type:"address"}],name:"FeeCollectorAdded",type:"event"},{anonymous:!1,inputs:[{indexed:!1,internalType:"address",name:"feeCollector",type:"address"}],name:"FeeCollectorRemoved",type:"event"},{anonymous:!1,inputs:[{indexed:!1,internalType:"uint32",name:"domain",type:"uint32"},{components:[{internalType:"uint256",name:"maxFee",type:"uint256"},{internalType:"uint256",name:"minFee",type:"uint256"},{internalType:"uint32",name:"feePercentage",type:"uint32"},{internalType:"uint256",name:"txnFee",type:"uint256"},{internalType:"bool",name:"supported",type:"bool"}],indexed:!1,internalType:"struct FeeCalculator.FeeConfiguration",name:"feeConfiguration",type:"tuple"}],name:"FeeConfigurationUpdated",type:"event"},{anonymous:!1,inputs:[{indexed:!0,internalType:"address",name:"previousOwner",type:"address"},{indexed:!0,internalType:"address",name:"newOwner",type:"address"}],name:"OwnershipTransferred",type:"event"},{anonymous:!1,inputs:[{indexed:!1,internalType:"address",name:"account",type:"address"}],name:"Paused",type:"event"},{anonymous:!1,inputs:[{indexed:!1,internalType:"uint64",name:"nonce",type:"uint64"},{indexed:!1,internalType:"address",name:"burnToken",type:"address"},{indexed:!1,internalType:"uint256",name:"amount",type:"uint256"},{indexed:!1,internalType:"address",name:"depositor",type:"address"},{indexed:!1,internalType:"address",name:"mintRecipient",type:"address"},{indexed:!1,internalType:"uint32",name:"destinationDomain",type:"uint32"},{indexed:!1,internalType:"uint256",name:"totalFee",type:"uint256"}],name:"TransferTokens",type:"event"},{anonymous:!1,inputs:[{indexed:!1,internalType:"address",name:"account",type:"address"}],name:"Unpaused",type:"event"},{inputs:[{internalType:"address",name:"account",type:"address"}],name:"addAdmin",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[{internalType:"address",name:"feeCollector",type:"address"}],name:"addFeeCollector",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"}],name:"addSupportedBurnToken",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[{internalType:"uint256",name:"amount",type:"uint256"},{internalType:"uint32",name:"destinationDomain",type:"uint32"}],name:"calculateFee",outputs:[{internalType:"uint256",name:"",type:"uint256"}],stateMutability:"view",type:"function"},{inputs:[],name:"circleTokenMessenger",outputs:[{internalType:"contract ICircleTokenMessenger",name:"",type:"address"}],stateMutability:"view",type:"function"},{inputs:[],name:"circleTokenMessengerAddress",outputs:[{internalType:"address",name:"",type:"address"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"}],name:"collectFees",outputs:[{internalType:"bool",name:"",type:"bool"}],stateMutability:"nonpayable",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"}],name:"getFeeAmounts",outputs:[{internalType:"uint256",name:"",type:"uint256"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"uint32",name:"domain",type:"uint32"}],name:"getFeeConfiguration",outputs:[{components:[{internalType:"uint256",name:"maxFee",type:"uint256"},{internalType:"uint256",name:"minFee",type:"uint256"},{internalType:"uint32",name:"feePercentage",type:"uint32"},{internalType:"uint256",name:"txnFee",type:"uint256"},{internalType:"bool",name:"supported",type:"bool"}],internalType:"struct FeeCalculator.FeeConfiguration",name:"",type:"tuple"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"uint32",name:"domain",type:"uint32"}],name:"getFeePercentage",outputs:[{internalType:"uint32",name:"",type:"uint32"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"uint32",name:"domain",type:"uint32"}],name:"getMaxFee",outputs:[{internalType:"uint256",name:"",type:"uint256"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"uint32",name:"domain",type:"uint32"}],name:"getMinFee",outputs:[{internalType:"uint256",name:"",type:"uint256"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"uint32",name:"domain",type:"uint32"}],name:"getTxnFee",outputs:[{internalType:"uint256",name:"",type:"uint256"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"address",name:"account",type:"address"}],name:"isAdmin",outputs:[{internalType:"bool",name:"",type:"bool"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"address",name:"account",type:"address"}],name:"isFeeCollector",outputs:[{internalType:"bool",name:"",type:"bool"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"}],name:"isSupportedBurnToken",outputs:[{internalType:"bool",name:"",type:"bool"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"uint32",name:"domain",type:"uint32"}],name:"isSupportedDomain",outputs:[{internalType:"bool",name:"",type:"bool"}],stateMutability:"view",type:"function"},{inputs:[],name:"owner",outputs:[{internalType:"address",name:"",type:"address"}],stateMutability:"view",type:"function"},{inputs:[],name:"pause",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[],name:"paused",outputs:[{internalType:"bool",name:"",type:"bool"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"address",name:"account",type:"address"}],name:"removeAdmin",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[{internalType:"address",name:"feeCollector",type:"address"}],name:"removeFeeCollector",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"}],name:"removeSupportedBurnToken",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[],name:"renounceOwnership",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[{internalType:"uint32",name:"domain",type:"uint32"},{components:[{internalType:"uint256",name:"maxFee",type:"uint256"},{internalType:"uint256",name:"minFee",type:"uint256"},{internalType:"uint32",name:"feePercentage",type:"uint32"},{internalType:"uint256",name:"txnFee",type:"uint256"},{internalType:"bool",name:"supported",type:"bool"}],internalType:"struct FeeCalculator.FeeConfiguration",name:"feeConfiguration",type:"tuple"}],name:"setFeeConfiguration",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[{internalType:"address",name:"",type:"address"}],name:"supportedBurnTokens",outputs:[{internalType:"bool",name:"",type:"bool"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"address",name:"newOwner",type:"address"}],name:"transferOwnership",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[{internalType:"uint256",name:"amount",type:"uint256"},{internalType:"uint32",name:"destinationDomain",type:"uint32"},{internalType:"address",name:"mintRecipient",type:"address"},{internalType:"address",name:"burnToken",type:"address"}],name:"transferTokens",outputs:[{internalType:"uint64",name:"nonce",type:"uint64"}],stateMutability:"nonpayable",type:"function"},{inputs:[],name:"unpause",outputs:[],stateMutability:"nonpayable",type:"function"}];var _=({sourceChain:e,targetChain:t,amount:r,asset:a},p)=>{if(e.chainId===t.chainId)throw new T("IDENTICAL_CHAINS_PROVIDED");if(r<=0n)throw new T("INCORRECT_AMOUNT_PROVIDED","Amount must be greater than zero");let n=p.find(i=>i.chainId===e.chainId);if(!n)throw new T("CHAIN_NOT_SUPPORTED",`Not supported on source chain "${e.chainId}"`);let o=p.find(i=>i.chainId===t.chainId);if(!o)throw new T("CHAIN_NOT_SUPPORTED",`Not supported on target chain "${t.chainId}"`);let d=n.tokens.find(i=>i.symbol===a.symbol),y=o.tokens.find(i=>i.symbol===a.symbol);if(!d||!y)throw new T("ASSET_NOT_SUPPORTED");return {sourceChainData:n,targetChainData:o,burnToken:d,mintToken:y}};async function W(e,t){await e.ensureHasConfig();let{sourceChain:r,targetChain:a,asset:p,amount:n,provider:o}=t,{sourceChainData:d,targetChainData:y,burnToken:i}=_({sourceChain:r,targetChain:a,asset:p,amount:n},e.config),u=await I({chain:r,provider:o}).readContract({address:d.tokenRouterAddress,abi:x,functionName:"calculateFee",args:[n,y.domain]});return {[i.address]:u}}var D=[{constant:!0,inputs:[],name:"name",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_spender",type:"address"},{name:"_value",type:"uint256"}],name:"approve",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"totalSupply",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_from",type:"address"},{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transferFrom",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"decimals",outputs:[{name:"",type:"uint8"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"balanceOf",outputs:[{name:"balance",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[],name:"symbol",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transfer",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"},{name:"_spender",type:"address"}],name:"allowance",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{payable:!0,stateMutability:"payable",type:"fallback"},{anonymous:!1,inputs:[{indexed:!0,name:"owner",type:"address"},{indexed:!0,name:"spender",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Approval",type:"event"},{anonymous:!1,inputs:[{indexed:!0,name:"from",type:"address"},{indexed:!0,name:"to",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Transfer",type:"event"}];var ye=async(e,t)=>{let{sourceChain:r,targetChain:a,asset:p,amount:n,fromAddress:o,toAddress:d,sourceProvider:y,onStepChange:i,sign:s}=t,u=d??o;if(!viem.isAddress(o)||!viem.isAddress(u))throw new T("INCORRECT_ADDRESS_PROVIDED");let{sourceChainData:c,targetChainData:f,burnToken:l}=_({sourceChain:r,targetChain:a,asset:p,amount:n},e.config),m=I({chain:r,provider:y}),b=await m.readContract({address:l.address,abi:D,functionName:"allowance",args:[o,c.tokenRouterAddress]})<n,h=b?2:1;if(b)if(i?.({currentSignature:1,currentSignatureReason:"allowance-approval",requiredSignatures:h}),s){let g=viem.encodeFunctionData({abi:D,functionName:"approve",args:[c.tokenRouterAddress,n]}),A=await s({from:o,to:l.address,data:g},k=>m.sendRawTransaction({serializedTransaction:k}));await m.waitForTransactionReceipt({hash:A,pollingInterval:1e3});}else {let{request:g}=await m.simulateContract({account:o,address:l.address,abi:D,functionName:"approve",args:[c.tokenRouterAddress,n]}),A=await m.writeContract(g);await m.waitForTransactionReceipt({hash:A,pollingInterval:1e3});}if(i?.({currentSignature:b?2:1,currentSignatureReason:"tokens-transfer",requiredSignatures:h}),s){let g=viem.encodeFunctionData({abi:x,functionName:"transferTokens",args:[n,f.domain,u,l.address]});return s({from:o,to:c.tokenRouterAddress,data:g},A=>m.sendRawTransaction({serializedTransaction:A}))}else {let{request:g}=await m.simulateContract({account:o,address:c.tokenRouterAddress,abi:x,functionName:"transferTokens",args:[n,f.domain,u,l.address]});return m.writeContract(g)}},fe=async e=>{try{return await e.getBlockNumber()}catch{return}};async function J(e,t,r){await e.ensureHasConfig();let{minimumConfirmations:a}=e.config.find(u=>u.chainId===t.sourceChain.chainId)??{},{minimumConfirmations:p}=e.config.find(u=>u.chainId===t.targetChain.chainId)??{};if(!a||!p)throw new T("CONFIRMATION_COUNT_UNKNOWN");let n=await e.getFees({...t,provider:t.sourceProvider}),o=(t.asset.address&&n[t.asset.address])??0n,d=await ye(e,t),y=Date.now(),i=I({chain:t.targetChain,provider:t.targetProvider}),s=await fe(i);return {type:e.type,environment:r,fromAddress:t.fromAddress,toAddress:t.toAddress??t.fromAddress,amount:t.amount,amountDecimals:t.asset.decimals,symbol:t.asset.symbol,bridgeFee:o,sourceChain:t.sourceChain,sourceStartedAt:y,sourceTxHash:d,sourceConfirmationCount:0,requiredSourceConfirmationCount:a,targetChain:t.targetChain,targetConfirmationCount:0,requiredTargetConfirmationCount:p,startBlockNumber:s}}async function Z(e){if(!e.config&&(await e.updateConfig(),!e.config))throw new B("CONFIG_NOT_AVAILABLE")}var O=(e,t)=>e.gasPrice&&BigInt(e.gasPrice*t.gasUsed);var L=async e=>new Promise(t=>{setTimeout(t,e);});var U=({promise:e,delay:t,startAfter:r})=>{let a=!1,p=!1,n=0,o,d,y=u=>{o&&a&&(a=!1,o(u));},i=()=>{p=!0,d&&a&&(a=!1,d("cancelled"));};return {result:new Promise((u,c)=>{a=!0,o=u,d=c;let f=async()=>{if(!(!a||p)){try{if(await e(y),!a||p)return;await L(t);}catch(l){console.error(l.message),n+=1,await L(2**n*t);}await f();}};r?setTimeout(f,r):f();}),cancel:i}};var Q=1e3*60*60*3,Y=1024n,ee=5e3,C=(e,t,r)=>{Object.assign(e,Object.fromEntries(Object.entries(t).filter(([,a])=>a!==void 0))),r({...e});},Te=async(e,t)=>{let{sourceProvider:r,targetProvider:a,updateListener:p,bridgeTransfer:n}=t,o=I({chain:n.sourceChain,provider:r}),d=e.find(c=>c.chainId===n.sourceChain.chainId),y=I({chain:n.targetChain,provider:a}),i=e.find(c=>c.chainId===n.targetChain.chainId),s={...n};if(!d||!i)throw new T("CHAIN_NOT_SUPPORTED");return U({promise:async c=>{if(s.completedAt||s.metadata?.nonce)return c(s);if(s.sourceStartedAt+Q<=Date.now())return C(s,{completedAt:Date.now(),errorCode:5004},p),c(s);let f=await o.getTransactionReceipt({hash:s.sourceTxHash});if(!s.sourceNetworkFee){let A=await o.getTransaction({hash:s.sourceTxHash}),k=O(A,f);k&&C(s,{sourceNetworkFee:k},p);}if(f.status==="reverted")return C(s,{completedAt:Date.now(),errorCode:5005},p),c(s);let l=await o.getTransactionConfirmations({hash:s.sourceTxHash}),m=l>s.sourceConfirmationCount,v=l>=s.requiredSourceConfirmationCount;if(m){let A={};A.sourceConfirmationCount=Number(l),v||(A.startBlockNumber=await y.getBlockNumber()),C(s,A,p);}if(!v)return;s.startBlockNumber||C(s,{startBlockNumber:await y.getBlockNumber()},p);let b=f.logs.find(A=>A.address===d.tokenRouterAddress?viem.decodeEventLog({abi:x,...A}).eventName==="TransferTokens":!1);if(!b)throw new T("INVALID_PARAMS",`unable to find a TransferTokens event in source transaction "${s.sourceTxHash}"`);let g=viem.decodeEventLog({abi:x,eventName:"TransferTokens",...b}).args.nonce;return C(s,{targetStartedAt:Date.now(),metadata:{nonce:g}},p),c(s)},delay:M(d.chainId),startAfter:ee})},ge=async(e,t)=>{let{targetProvider:r,updateListener:a,bridgeTransfer:p}=t,n={...p};if(!p.completedAt&&!p.metadata?.nonce)throw new T("INVALID_PARAMS","nonce is missing");if(!p.startBlockNumber)throw new T("INVALID_PARAMS","startBlockNumber is missing");let o=I({chain:p.targetChain,provider:r}),d=e.find(i=>i.chainId===p.targetChain.chainId);if(!d)throw new T("INVALID_PARAMS",`unknown target chain "${p.targetChain.chainId}"`);return U({promise:async i=>{if(n.completedAt)return i(n);if(!n.startBlockNumber)return C(n,{completedAt:Date.now(),errorCode:5003},a),i(n);if(n.sourceStartedAt+Q<=Date.now())return C(n,{completedAt:Date.now(),errorCode:5004},a),i(n);if(!n.targetTxHash){let l=await o.getBlockNumber(),m=n.startBlockNumber-Y,v=m>=0n?m:"earliest",b=n.startBlockNumber+Y,h=b<l?b:"latest",g=await o.getLogs({address:d.messageTransmitterAddress,event:{name:"MessageReceived",type:"event",inputs:[{indexed:!0,internalType:"address",name:"caller",type:"address"},{indexed:!1,internalType:"uint32",name:"sourceDomain",type:"uint32"},{indexed:!0,internalType:"uint64",name:"nonce",type:"uint64"},{indexed:!1,internalType:"bytes32",name:"sender",type:"bytes32"},{indexed:!1,internalType:"bytes",name:"messageBody",type:"bytes"}]},args:{nonce:n.metadata.nonce},fromBlock:v,toBlock:h});if(g[0]?.transactionHash)C(n,{targetTxHash:g[0].transactionHash},a);else {C(n,{startBlockNumber:l},a);return}}let s=await o.getTransactionReceipt({hash:n.targetTxHash});if(!n.targetNetworkFee){let l=await o.getTransaction({hash:n.targetTxHash}),m=O(l,s);m&&C(n,{targetNetworkFee:m},a);}if(s.status==="reverted")return C(n,{completedAt:Date.now(),errorCode:5005},a),i(n);let u=await o.getTransactionConfirmations({hash:n.targetTxHash}),c=u>n.targetConfirmationCount,f=u>=n.requiredTargetConfirmationCount;if(c&&C(n,{targetConfirmationCount:Number(u)},a),!!f)return C(n,{completedAt:Date.now()},a),i(n)},delay:M(d.chainId),startAfter:ee})};function te(e,t){let r,a=()=>{r?.();};return {result:(async()=>{await e.ensureHasConfig();let{sourceProvider:n,targetProvider:o,updateListener:d,bridgeTransfer:y}=t,{result:i,cancel:s}=await Te(e.config,{sourceProvider:n,targetProvider:o,updateListener:d,bridgeTransfer:y});r=s;let u=await i,{result:c,cancel:f}=await ge(e.config,{sourceProvider:n,targetProvider:o,updateListener:d,bridgeTransfer:u});return r=f,c})(),cancel:a}}var ne=e=>({type:"cctp",config:null,updateConfig:async function(){this.config=await q(e);},ensureHasConfig:async function(){return Z(this)},getAssets:async function(){return $(this)},getFees:async function(t){return W(this,t)},transferAsset:async function(t){return J(this,t,e)},trackTransfer:function(t){return te(this,t)}});var Ae=new Map([["cctp",ne]]),re=(e,t)=>new Map([...Ae].filter(([r])=>!t?.includes(r)).map(([r,a])=>[r,a(e)])),F=(e,t,r)=>{let a=t.destinations[r]?.find(p=>e.has(p));if(!a)throw new P;return {type:a,bridge:e.get(a)}};var dn=({environment:e,disabledBridgeTypes:t})=>{let r=re(e,t),a=async()=>{await Promise.allSettled(Array.from(r).map(([,s])=>s.updateConfig()));};return {environment:e,bridges:r,init:async()=>{await a();},updateConfigs:a,getAssets:async()=>(await Promise.all(Array.from(r).map(([,u])=>u.getAssets()))).reduce((u,c)=>{for(let[f,l]of Object.entries(c)){let m=u[f];if(m)for(let v of l){let b=m.findIndex(({symbol:h})=>h===v.symbol);b===-1?m.push(v):lodash.mergeWith(m[b],v,(h,g)=>{if(lodash.isArray(h))return [...new Set(h.concat(g))]});}else u[f]=l;}return u},{}),getFees:async s=>{let{bridge:u}=F(r,s.asset,s.targetChain.chainId);return u.getFees(s)},canTransferAsset:(s,u)=>{try{return F(r,s,u),!0}catch{return !1}},transferAsset:async s=>{let{bridge:u}=F(r,s.asset,s.targetChain.chainId);return u.transferAsset(s)},trackTransfer:s=>{let u=r.get(s.bridgeTransfer.type);if(!u)throw new P;return u.trackTransfer(s)}}};
6
7
 
7
- exports.createBridgeService = v;
8
+ exports.BridgeSignatureReason = V;
9
+ exports.BridgeType = E;
10
+ exports.Environment = K;
11
+ exports.ErrorCode = R;
12
+ exports.ErrorReason = w;
13
+ exports.TokenType = H;
14
+ exports.caip2 = S;
15
+ exports.createUnifiedBridgeService = dn;
8
16
  //# sourceMappingURL=out.js.map
9
17
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/handlers/submit-bridge-transaction-step.ts","../src/errors/index.ts","../src/handlers/get-bridge-router.ts","../src/handlers/submit-and-watch-bridge-transaction.ts","../src/bridge-service.ts"],"names":["BridgeError","message","code","NotImplementedError","submitBridgeTransactionStep","_params","getBridgeRouter","submitAndWatchBridgeTransaction","createBridgeService","_options"],"mappings":"AAAA,MAA6B,OCI7B,IAAMA,EAAN,cAA0B,KAAM,CAC9B,YACEC,EACOC,EACP,CACA,MAAMD,CAAO,EAFN,UAAAC,EAGP,KAAK,KAAOA,CACd,CACF,EAEaC,EAAN,cAAkCH,CAAY,CACnD,YAAYC,EAAU,kBAAmB,CACvC,MAAMA,EAAS,IAAyB,EACxC,KAAK,KAAO,qBACd,CACF,EDPO,IAAMG,EAA8B,MAAOC,GAA2C,CAQ3F,MAAM,IAAIF,CACZ,EEAO,IAAMG,EAAmBD,GAA4D,CAE1F,MAAM,IAAIF,CACZ,ECxBO,IAAMI,EAAkC,IAAM,CAAC,ECW/C,IAAMC,EAAuBC,IAC3B,CACL,gBAAAH,EACA,4BAAAF,EACA,gCAAAG,CACF","sourcesContent":["import { type Address } from 'viem';\nimport type { Token } from '@internal/bridge-shared';\nimport { NotImplementedError } from '../errors';\n\ntype SubmitBridgeTransactionParams = {\n fromChainId: string;\n toChainId: string;\n fromAddress: Address;\n token: Token;\n amount: string;\n};\n\nexport const submitBridgeTransactionStep = async (_params: SubmitBridgeTransactionParams) => {\n /**\n * 1. Validate the token is supported on the fromChainId\n * 2. Validate the token is supported on the toChainId\n * 3. Figure out which bridge platform to use based on the from/to chains and the token being transferred\n * - Ex: Ethereum -> Avalanche USDC = use CCTP, but Ethereum -> Avalanche WAVAX use Avalanche bridge\n * 4. Return the transaction id\n */\n throw new NotImplementedError();\n};\n","export enum ErrorCode {\n NOT_IMPLEMENTED = 5001,\n}\n\nclass BridgeError extends Error {\n constructor(\n message: string,\n public code: ErrorCode,\n ) {\n super(message);\n this.code = code;\n }\n}\n\nexport class NotImplementedError extends BridgeError {\n constructor(message = 'Not implemented') {\n super(message, ErrorCode.NOT_IMPLEMENTED);\n this.name = 'NotImplementedError';\n }\n}\n","import { NotImplementedError } from '../errors';\nimport type { BridgePlatform, Token } from '@internal/bridge-shared';\n\ntype GetBridgeRouterParams = {\n fromChainId: string;\n toChainId: string;\n fromToken: Token;\n};\n\ntype BridgeTransactionStep = {\n fromChainId: string;\n toChainId: string;\n bridgePlatform: BridgePlatform;\n fromToken: Token;\n toToken: Token;\n};\n\n/**\n * Returns the steps required to complete a bridge transaction.\n * It could sometimes take multiple transactions to complete a bridge from chain A to B.\n */\nexport const getBridgeRouter = (_params: GetBridgeRouterParams): BridgeTransactionStep[] => {\n // Implement smart logic for determining how to get the token from chain A to B\n throw new NotImplementedError();\n};\n","export const submitAndWatchBridgeTransaction = () => {};\n","import { submitBridgeTransactionStep } from './handlers/submit-bridge-transaction-step';\nimport { getBridgeRouter } from './handlers/get-bridge-router';\nimport { submitAndWatchBridgeTransaction } from './handlers/submit-and-watch-bridge-transaction';\nimport type { Environment, MaybePromise, NativeToken } from '@internal/bridge-shared';\n\nexport type BridgeServiceConfig = {\n environment: `${Environment}`;\n getChainNativeAsset: ({ evmChainId }: { evmChainId: string }) => MaybePromise<NativeToken>;\n getChainErc20Asset: ({ evmChainId, address }: { evmChainId: string; address: string }) => MaybePromise<NativeToken>;\n};\n\nexport const createBridgeService = (_options: BridgeServiceConfig) => {\n return {\n getBridgeRouter,\n submitBridgeTransactionStep,\n submitAndWatchBridgeTransaction,\n };\n};\n"]}
1
+ {"version":3,"sources":["../src/types/asset.ts","../src/types/bridge.ts","../src/types/environment.ts","../src/types/error.ts","../src/errors/bridge-error.ts","../src/errors/bridge-unavailable-error.ts","../src/errors/bridge-initialization-error.ts","../src/errors/invalid-params-error.ts","../src/bridges/cctp/utils/config.ts","../src/bridges/cctp/handlers/get-assets.ts","../src/utils/client.ts","../src/utils/caip2.ts","../src/bridges/cctp/abis/token-router.ts","../src/bridges/cctp/utils/transfer-data.ts","../src/bridges/cctp/handlers/get-fees.ts","../src/bridges/cctp/handlers/transfer-asset.ts","../src/bridges/cctp/abis/erc20.ts","../src/utils/ensure-config.ts","../src/bridges/cctp/handlers/track-transfer.ts","../src/utils/network-fee.ts","../src/utils/wait.ts","../src/utils/retry-promise.ts","../src/bridges/cctp/factory.ts","../src/utils/bridge-types.ts","../src/unified-bridge-service.ts"],"names":["TokenType","BridgeType","BridgeSignatureReason","Environment","ErrorCode","ErrorReason","BridgeError","message","code","details","BridgeUnavailableError","BridgeInitializationError","InvalidParamsError","CONFIG_URLS","getConfig","environment","chainData","err","getTrackingDelayByChainId","chainId","getAssets","bridge","chainIds","assets","asset","destinations","createWalletClient","publicActions","custom","http","namespacePattern","referencePattern","delimeter","toJSON","identifier","namespace","reference","toString","caip2_default","_getChain","chain","getClientForChain","provider","chainInfo","transport","TOKEN_ROUTER_ABI","getTransferData","sourceChain","targetChain","amount","config","sourceChainData","targetChainData","burnToken","token","mintToken","getFees","params","feeAmount","encodeFunctionData","isAddress","ERC20_ABI","approveAndTransfer","fromAddress","maybeToAddress","sourceProvider","onStepChange","sign","toAddress","client","isAllowanceApprovalRequired","requiredSignatures","data","txHash","signedTxHash","request","getStartBlockNumber","targetClient","transferAsset","requiredSourceConfirmationCount","requiredTargetConfirmationCount","fees","bridgeFee","sourceStartedAt","targetBlockNumber","ensureHasConfig","decodeEventLog","getNetworkFeeEVM","transaction","receipt","wait","time","res","retryPromise","promise","delay","startAfter","isRunning","isCancelled","errorCount","resolve","reject","done","cancel","rej","execute","TRACKING_LIMIT_MS","MAX_BLOCKS","INITIAL_DELAY","updateTransfer","initial","updated","updateListener","value","trackSourceTx","targetProvider","bridgeTransfer","sourceClient","updateableTransfer","txReceipt","tx","networkFee","confirmationCount","hasMoreConfirmations","hasRequiredConfirmations","changes","transferEventLog","log","nonce","trackTargetTx","lastBlockNumber","lowestBlockNumber","fromBlock","highestBlockNumber","toBlock","targetLogs","trackTransfer","abortFn","sourceTracker","cancelSourceTracking","transferAfterSourceFinished","targetTracker","cancelTargetTracking","cctpBridgeFactory","supportedBridges","getEnabledBridgeServices","disabledBridgeTypes","bridgeType","factory","getBridgeForTransfer","enabledBridgeServices","targetChainId","isArray","mergeWith","createUnifiedBridgeService","updateConfigs","bridgeService","aggregatedAssets","chainAssetMap","bridgeAssets","existingAssets","bridgeAsset","index","symbol","objValue","srcValue"],"mappings":"AAGO,IAAKA,OACVA,EAAA,OAAS,SACTA,EAAA,MAAQ,QAFEA,OAAA,ICKL,IAAKC,OACVA,EAAA,KAAO,OADGA,OAAA,IAYAC,OACVA,EAAA,kBAAoB,qBACpBA,EAAA,eAAiB,kBAFPA,OAAA,ICpBL,IAAKC,OACVA,EAAA,KAAO,aACPA,EAAA,KAAO,OAFGA,OAAA,ICAL,IAAKC,OACVA,IAAA,qBAAuB,MAAvB,uBACAA,IAAA,sBAAwB,MAAxB,wBACAA,IAAA,eAAiB,MAAjB,iBACAA,IAAA,QAAU,MAAV,UACAA,IAAA,qBAAuB,MAAvB,uBALUA,OAAA,IAQAC,OACVA,EAAA,QAAU,UACVA,EAAA,qBAAuB,uBACvBA,EAAA,eAAiB,iBACjBA,EAAA,0BAA4B,4BAC5BA,EAAA,0BAA4B,4BAC5BA,EAAA,2BAA6B,6BAC7BA,EAAA,oBAAsB,sBACtBA,EAAA,oBAAsB,sBACtBA,EAAA,2BAA6B,6BATnBA,OAAA,ICNL,IAAMC,EAAN,cAA0B,KAAM,CACrC,YACEC,EACOC,EACAC,EACP,CACA,MAAMF,CAAO,EAHN,UAAAC,EACA,aAAAC,CAGT,CACF,ECPO,IAAMC,EAAN,cAAqCJ,CAAY,CACtD,YAAYC,YAA+BE,EAAkB,CAC3D,MAAMF,OAAyCE,CAAO,EACtD,KAAK,KAAO,wBACd,CACF,ECLO,IAAME,EAAN,cAAwCL,CAAY,CACzD,YAAYC,YAA+BE,EAAkB,CAC3D,MAAMF,OAA0CE,CAAO,EACvD,KAAK,KAAO,2BACd,CACF,ECLO,IAAMG,EAAN,cAAiCN,CAAY,CAClD,YAAYC,mBAAsCE,EAAkB,CAClE,MAAMF,OAAmCE,CAAO,EAChD,KAAK,KAAO,oBACd,CACF,ECFA,IAAMI,GAA2C,CAC9C,KACC,wGACD,WACC,kGACJ,EAEaC,EAAY,MAAOC,GAA8C,CAC5E,GAAI,CAIF,OAFuB,MADN,MAAM,MAAMF,GAAYE,CAAW,CAAE,GAChB,KAAK,GAE7B,IAAKC,IAAe,CAAE,GAAGA,EAAW,QAAS,UAAUA,EAAU,OAAO,EAAG,EAAE,CAC7F,OAASC,EAAK,CACZ,MAAM,IAAIN,yBAER,qCAAsCM,EAAyB,OAAO,EACxE,CACF,CACF,EAEaC,EAA6BC,GAAoB,CAC5D,OAAQA,EAAS,CACf,mBACA,mBACE,MAAO,KACT,QACE,MAAO,IACX,CACF,ECjCA,eAAsBC,EAAUC,EAAuB,CACrD,MAAMA,EAAO,gBAAgB,EAE7B,IAAMC,EAAWD,EAAO,OAAQ,IAAKL,GAAcA,EAAU,OAAO,EAEpE,OAAOK,EAAO,OAAQ,OAAsB,CAACE,EAAQP,KACnDO,EAAOP,EAAU,OAAO,EAAIA,EAAU,OAAO,IAAKQ,IAAW,CAC3D,GAAGA,EACH,aACA,aAAcF,EAAS,OAAwB,CAACG,EAAcN,KACxDH,EAAU,UAAYG,IACnBM,EAAaN,CAAO,IACvBM,EAAaN,CAAO,EAAI,CAAC,GAG3BM,EAAaN,CAAO,GAAG,WAAoB,GAGtCM,GACN,CAAC,CAAC,CACP,EAAE,EAEKF,GACN,CAAC,CAAC,CACP,CC1BA,OAAS,sBAAAG,GAAoB,iBAAAC,GAAe,UAAAC,GAAQ,QAAAC,OAAY,OCOhE,IAAMC,GAAmB,mBAEnBC,GAAmB,wBACnBC,EAAY,IAEZC,GAAUC,GAAqC,CACnD,GAAM,CAACC,EAAWC,CAAS,EAAIF,EAAW,MAAMF,CAAS,EAEzD,GAAI,CAACG,GAAa,CAACC,EACjB,MAAM,IAAI,MAAM,8BAA8B,EAGhD,GAAI,CAAC,IAAI,OAAON,EAAgB,EAAE,KAAKK,CAAS,EAC9C,MAAM,IAAI,MAAM,6BAA6B,EAG/C,GAAI,CAAC,IAAI,OAAOJ,EAAgB,EAAE,KAAKK,CAAS,EAC9C,MAAM,IAAI,MAAM,6BAA6B,EAG/C,MAAO,CACL,UAAAD,EACA,UAAAC,CACF,CACF,EAEMC,GAAW,CAAC,CAAE,UAAAF,EAAW,UAAAC,CAAU,IAChC,GAAGD,CAAS,GAAGH,CAAS,GAAGI,CAAS,GAGtCE,EAAQ,CACb,OAAAL,GACA,SAAAI,EACF,EDnCA,IAAME,GAAaC,GAAiB,CAClC,GAAM,CAAE,UAAWrB,CAAQ,EAAImB,EAAM,OAAOE,EAAM,OAAO,EAEzD,MAAO,CACL,GAAI,OAAOrB,CAAO,EAClB,KAAMqB,EAAM,UACZ,eAAgB,CACd,SAAUA,EAAM,aAAa,SAC7B,OAAQA,EAAM,aAAa,OAC3B,KAAMA,EAAM,aAAa,IAC3B,EACA,QAASA,EAAM,UACf,QAAS,CACP,QAAS,CACP,KAAM,CAACA,EAAM,MAAM,CACrB,EACA,OAAQ,CACN,KAAM,CAACA,EAAM,MAAM,CACrB,CACF,EACA,GAAIA,EAAM,kBAAkB,WAAa,CACvC,UAAW,CACT,WAAY,CACV,QAASA,EAAM,iBAAiB,SAClC,CACF,CACF,CACF,CACF,EAEaC,EAAoB,CAAC,CAAE,MAAAD,EAAO,SAAAE,CAAS,IAA6C,CAC/F,IAAMC,EAAYJ,GAAUC,CAAK,EAC3BI,EAAYF,EAAWd,GAAOc,CAAQ,EAAIb,GAAKW,EAAM,OAAQ,CAAE,MAAO,GAAM,WAAY,CAAE,CAAC,EAEjG,OAAOd,GAAmB,CACxB,MAAOiB,EACP,UAAAC,CACF,CAAC,EAAE,OAAOjB,EAAa,CACzB,EE3CO,IAAMkB,EAAmB,CAC9B,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,wBACN,KAAM,SACR,EACA,CACE,aAAc,UACd,KAAM,aACN,KAAM,SACR,CACF,EACA,gBAAiB,aACjB,KAAM,aACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,eACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,sBACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,4BACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,oBACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,sBACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,wBACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,8BACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,sBACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,sBACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,8BACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,sBACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,+BACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,uBACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,WACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,kBACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,uBACN,KAAM,OACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,oBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,aACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,eACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,iBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,mBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,eACN,KAAM,SACR,CACF,EACA,KAAM,oBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,eACN,KAAM,SACR,CACF,EACA,KAAM,sBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,SACd,KAAM,SACN,KAAM,QACR,EACA,CACE,WAAY,CACV,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,SACd,KAAM,gBACN,KAAM,QACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,OACd,KAAM,YACN,KAAM,MACR,CACF,EACA,QAAS,GACT,aAAc,wCACd,KAAM,mBACN,KAAM,OACR,CACF,EACA,KAAM,0BACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,gBACN,KAAM,SACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,WACN,KAAM,SACR,CACF,EACA,KAAM,uBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,SACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,SACd,KAAM,QACN,KAAM,QACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,YACN,KAAM,SACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,YACN,KAAM,SACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,gBACN,KAAM,SACR,EACA,CACE,QAAS,GACT,aAAc,SACd,KAAM,oBACN,KAAM,QACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,WACN,KAAM,SACR,CACF,EACA,KAAM,iBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,WACN,KAAM,OACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,WACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,eACN,KAAM,SACR,CACF,EACA,KAAM,kBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,wBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,SACd,KAAM,oBACN,KAAM,QACR,CACF,EACA,KAAM,eACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,uBACN,QAAS,CACP,CACE,aAAc,iCACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,8BACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,cACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,gBACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,sBACN,QAAS,CACP,CACE,WAAY,CACV,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,SACd,KAAM,gBACN,KAAM,QACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,OACd,KAAM,YACN,KAAM,MACR,CACF,EACA,aAAc,wCACd,KAAM,GACN,KAAM,OACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,mBACN,QAAS,CACP,CACE,aAAc,SACd,KAAM,GACN,KAAM,QACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,YACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,YACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,YACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,UACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,iBACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,uBACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,oBACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,QACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,QACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,SACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,cACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,eACN,KAAM,SACR,CACF,EACA,KAAM,qBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,2BACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,oBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,EACA,CACE,WAAY,CACV,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,SACd,KAAM,gBACN,KAAM,QACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,OACd,KAAM,YACN,KAAM,MACR,CACF,EACA,aAAc,wCACd,KAAM,mBACN,KAAM,OACR,CACF,EACA,KAAM,sBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,KAAM,sBACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,WACN,KAAM,SACR,CACF,EACA,KAAM,oBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,SACd,KAAM,oBACN,KAAM,QACR,EACA,CACE,aAAc,UACd,KAAM,gBACN,KAAM,SACR,EACA,CACE,aAAc,UACd,KAAM,YACN,KAAM,SACR,CACF,EACA,KAAM,iBACN,QAAS,CACP,CACE,aAAc,SACd,KAAM,QACN,KAAM,QACR,CACF,EACA,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,UACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,CACF,ECn0BO,IAAMC,EAAkB,CAAC,CAAE,YAAAC,EAAa,YAAAC,EAAa,OAAAC,EAAQ,MAAAzB,CAAM,EAA0B0B,IAAmB,CACrH,GAAIH,EAAY,UAAYC,EAAY,QACtC,MAAM,IAAIpC,6BAAwD,EAGpE,GAAIqC,GAAU,GACZ,MAAM,IAAIrC,8BAA0D,kCAAkC,EAGxG,IAAMuC,EAAkBD,EAAO,KAAMlC,GAAcA,EAAU,UAAY+B,EAAY,OAAO,EAE5F,GAAI,CAACI,EACH,MAAM,IAAIvC,wBAER,kCAAkCmC,EAAY,OAAO,GACvD,EAGF,IAAMK,EAAkBF,EAAO,KAAMlC,GAAcA,EAAU,UAAYgC,EAAY,OAAO,EAE5F,GAAI,CAACI,EACH,MAAM,IAAIxC,wBAER,kCAAkCoC,EAAY,OAAO,GACvD,EAGF,IAAMK,EAAYF,EAAgB,OAAO,KAAMG,GAAUA,EAAM,SAAW9B,EAAM,MAAM,EAChF+B,EAAYH,EAAgB,OAAO,KAAME,GAAUA,EAAM,SAAW9B,EAAM,MAAM,EAEtF,GAAI,CAAC6B,GAAa,CAACE,EACjB,MAAM,IAAI3C,uBAAkD,EAG9D,MAAO,CACL,gBAAAuC,EACA,gBAAAC,EACA,UAAAC,EACA,UAAAE,CACF,CACF,EC1CA,eAAsBC,EAAQnC,EAAuBoC,EAAmB,CACtE,MAAMpC,EAAO,gBAAgB,EAE7B,GAAM,CAAE,YAAA0B,EAAa,YAAAC,EAAa,MAAAxB,EAAO,OAAAyB,EAAQ,SAAAP,CAAS,EAAIe,EACxD,CAAE,gBAAAN,EAAiB,gBAAAC,EAAiB,UAAAC,CAAU,EAAIP,EACtD,CAAE,YAAAC,EAAa,YAAAC,EAAa,MAAAxB,EAAO,OAAAyB,CAAO,EAC1C5B,EAAO,MACT,EAGMqC,EAAY,MADHjB,EAAkB,CAAE,MAAOM,EAAa,SAAAL,CAAS,CAAC,EAClC,aAAa,CAC1C,QAASS,EAAgB,mBACzB,IAAKN,EACL,aAAc,eACd,KAAM,CAACI,EAAQG,EAAgB,MAAM,CACvC,CAAC,EAED,MAAO,CACL,CAACC,EAAU,OAAO,EAAGK,CACvB,CACF,CCzBA,OAAS,sBAAAC,EAAoB,aAAAC,MAAoC,OCA1D,IAAMC,EAAY,CACvB,CACE,SAAU,GACV,OAAQ,CAAC,EACT,KAAM,OACN,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,QAAS,CAAC,EACtC,QAAS,GACT,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,SAAU,GACV,OAAQ,CACN,CAAE,KAAM,WAAY,KAAM,SAAU,EACpC,CAAE,KAAM,SAAU,KAAM,SAAU,CACpC,EACA,KAAM,UACN,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,MAAO,CAAC,EACpC,QAAS,GACT,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,SAAU,GACV,OAAQ,CAAC,EACT,KAAM,cACN,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,SAAU,CAAC,EACvC,QAAS,GACT,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,SAAU,GACV,OAAQ,CACN,CAAE,KAAM,QAAS,KAAM,SAAU,EACjC,CAAE,KAAM,MAAO,KAAM,SAAU,EAC/B,CAAE,KAAM,SAAU,KAAM,SAAU,CACpC,EACA,KAAM,eACN,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,MAAO,CAAC,EACpC,QAAS,GACT,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,SAAU,GACV,OAAQ,CAAC,EACT,KAAM,WACN,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,CAAC,EACrC,QAAS,GACT,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,SAAU,GACV,OAAQ,CAAC,CAAE,KAAM,SAAU,KAAM,SAAU,CAAC,EAC5C,KAAM,YACN,QAAS,CAAC,CAAE,KAAM,UAAW,KAAM,SAAU,CAAC,EAC9C,QAAS,GACT,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,SAAU,GACV,OAAQ,CAAC,EACT,KAAM,SACN,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,QAAS,CAAC,EACtC,QAAS,GACT,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,SAAU,GACV,OAAQ,CACN,CAAE,KAAM,MAAO,KAAM,SAAU,EAC/B,CAAE,KAAM,SAAU,KAAM,SAAU,CACpC,EACA,KAAM,WACN,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,MAAO,CAAC,EACpC,QAAS,GACT,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,SAAU,GACV,OAAQ,CACN,CAAE,KAAM,SAAU,KAAM,SAAU,EAClC,CAAE,KAAM,WAAY,KAAM,SAAU,CACtC,EACA,KAAM,YACN,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,SAAU,CAAC,EACvC,QAAS,GACT,gBAAiB,OACjB,KAAM,UACR,EACA,CAAE,QAAS,GAAM,gBAAiB,UAAW,KAAM,UAAW,EAC9D,CACE,UAAW,GACX,OAAQ,CACN,CAAE,QAAS,GAAM,KAAM,QAAS,KAAM,SAAU,EAChD,CAAE,QAAS,GAAM,KAAM,UAAW,KAAM,SAAU,EAClD,CAAE,QAAS,GAAO,KAAM,QAAS,KAAM,SAAU,CACnD,EACA,KAAM,WACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CAAE,QAAS,GAAM,KAAM,OAAQ,KAAM,SAAU,EAC/C,CAAE,QAAS,GAAM,KAAM,KAAM,KAAM,SAAU,EAC7C,CAAE,QAAS,GAAO,KAAM,QAAS,KAAM,SAAU,CACnD,EACA,KAAM,WACN,KAAM,OACR,CACF,EDpGA,IAAMC,GAAqB,MAAOzC,EAAuBoC,IAA2B,CAClF,GAAM,CACJ,YAAAV,EACA,YAAAC,EACA,MAAAxB,EACA,OAAAyB,EACA,YAAAc,EACA,UAAWC,EACX,eAAAC,EACA,aAAAC,EACA,KAAAC,CACF,EAAIV,EACEW,EAAYJ,GAAkBD,EAEpC,GAAI,CAACH,EAAUG,CAAW,GAAK,CAACH,EAAUQ,CAAS,EACjD,MAAM,IAAIxD,8BAAyD,EAGrE,GAAM,CAAE,gBAAAuC,EAAiB,gBAAAC,EAAiB,UAAAC,CAAU,EAAIP,EACtD,CAAE,YAAAC,EAAa,YAAAC,EAAa,MAAAxB,EAAO,OAAAyB,CAAO,EAC1C5B,EAAO,MACT,EACMgD,EAAS5B,EAAkB,CAAE,MAAOM,EAAa,SAAUkB,CAAe,CAAC,EAS3EK,EAPY,MAAMD,EAAO,aAAa,CAC1C,QAAShB,EAAU,QACnB,IAAKQ,EACL,aAAc,YACd,KAAM,CAACE,EAAaZ,EAAgB,kBAAkB,CACxD,CAAC,EAE+CF,EAC1CsB,EAAqBD,EAA8B,EAAI,EAE7D,GAAIA,EAOF,GANAJ,IAAe,CACb,iBAAkB,EAClB,4CACA,mBAAAK,CACF,CAAC,EAEGJ,EAAM,CACR,IAAMK,EAAOb,EAAmB,CAC9B,IAAKE,EACL,aAAc,UACd,KAAM,CAACV,EAAgB,mBAAoBF,CAAM,CACnD,CAAC,EAEKwB,EAAS,MAAMN,EACnB,CACE,KAAMJ,EACN,GAAIV,EAAU,QACd,KAAAmB,CACF,EACCE,GAAsBL,EAAO,mBAAmB,CAAE,sBAAuBK,CAAa,CAAC,CAC1F,EAEA,MAAML,EAAO,0BAA0B,CAAE,KAAMI,EAAQ,gBAAiB,GAAM,CAAC,CACjF,KAAO,CACL,GAAM,CAAE,QAAAE,CAAQ,EAAI,MAAMN,EAAO,iBAAiB,CAChD,QAASN,EACT,QAASV,EAAU,QACnB,IAAKQ,EACL,aAAc,UACd,KAAM,CAACV,EAAgB,mBAAoBF,CAAM,CACnD,CAAC,EAEKwB,EAAS,MAAMJ,EAAO,cAAcM,CAAO,EACjD,MAAMN,EAAO,0BAA0B,CAAE,KAAMI,EAAQ,gBAAiB,GAAM,CAAC,CACjF,CASF,GANAP,IAAe,CACb,iBAAkBI,EAA8B,EAAI,EACpD,yCACA,mBAAAC,CACF,CAAC,EAEGJ,EAAM,CACR,IAAMK,EAAOb,EAAmB,CAC9B,IAAKd,EACL,aAAc,iBACd,KAAM,CAACI,EAAQG,EAAgB,OAAQgB,EAAWf,EAAU,OAAO,CACrE,CAAC,EAED,OAAOc,EACL,CACE,KAAMJ,EACN,GAAIZ,EAAgB,mBACpB,KAAAqB,CACF,EACCE,GAAsBL,EAAO,mBAAmB,CAAE,sBAAuBK,CAAa,CAAC,CAC1F,CACF,KAAO,CACL,GAAM,CAAE,QAAAC,CAAQ,EAAI,MAAMN,EAAO,iBAAiB,CAChD,QAASN,EACT,QAASZ,EAAgB,mBACzB,IAAKN,EACL,aAAc,iBACd,KAAM,CAACI,EAAQG,EAAgB,OAAQgB,EAAWf,EAAU,OAAO,CACrE,CAAC,EAED,OAAOgB,EAAO,cAAcM,CAAO,CACrC,CACF,EAEMC,GAAsB,MAAOC,GAA+B,CAChE,GAAI,CAEF,OADyB,MAAMA,EAAa,eAAe,CAE7D,MAAQ,CACN,MACF,CACF,EAEA,eAAsBC,EACpBzD,EACAoC,EACA1C,EACyB,CACzB,MAAMM,EAAO,gBAAgB,EAE7B,GAAM,CAAE,qBAAsB0D,CAAgC,EAC5D1D,EAAO,OAAQ,KAAML,GAAcA,EAAU,UAAYyC,EAAO,YAAY,OAAO,GAAK,CAAC,EACrF,CAAE,qBAAsBuB,CAAgC,EAC5D3D,EAAO,OAAQ,KAAML,GAAcA,EAAU,UAAYyC,EAAO,YAAY,OAAO,GAAK,CAAC,EAE3F,GAAI,CAACsB,GAAmC,CAACC,EACvC,MAAM,IAAIpE,8BAAyD,EAGrE,IAAMqE,EAAO,MAAM5D,EAAO,QAAQ,CAAE,GAAGoC,EAAQ,SAAUA,EAAO,cAAe,CAAC,EAE1EyB,GAAazB,EAAO,MAAM,SAAWwB,EAAKxB,EAAO,MAAM,OAAO,IAAM,GACpEgB,EAAS,MAAMX,GAAmBzC,EAAQoC,CAAM,EAChD0B,EAAkB,KAAK,IAAI,EAC3BN,EAAepC,EAAkB,CAAE,MAAOgB,EAAO,YAAa,SAAUA,EAAO,cAAe,CAAC,EAC/F2B,EAAoB,MAAMR,GAAoBC,CAAY,EAEhE,MAAO,CACL,KAAMxD,EAAO,KACb,YAAAN,EACA,YAAa0C,EAAO,YACpB,UAAWA,EAAO,WAAaA,EAAO,YACtC,OAAQA,EAAO,OACf,eAAgBA,EAAO,MAAM,SAC7B,OAAQA,EAAO,MAAM,OAErB,UAAAyB,EAEA,YAAazB,EAAO,YACpB,gBAAA0B,EACA,aAAcV,EACd,wBAAyB,EACzB,gCAAAM,EAEA,YAAatB,EAAO,YACpB,wBAAyB,EACzB,gCAAAuB,EAEA,iBAAkBI,CACpB,CACF,CE/KA,eAAsBC,EAAgBhE,EAAuB,CAC3D,GAAI,CAACA,EAAO,SACV,MAAMA,EAAO,aAAa,EAEtB,CAACA,EAAO,QACV,MAAM,IAAIV,wBAA0D,CAG1E,CCXA,OAAS,kBAAA2E,MAAoC,OCA7C,MAA0D,OAGnD,IAAMC,EAAmB,CAACC,EAA0BC,IAClDD,EAAY,UAAY,OAAOA,EAAY,SAAWC,EAAQ,OAAO,ECJvE,IAAMC,EAAO,MAAOC,GACzB,IAAI,QAASC,GAAQ,CACnB,WAAWA,EAAKD,CAAI,CACtB,CAAC,ECOI,IAAME,EAAe,CAAI,CAAE,QAAAC,EAAS,MAAAC,EAAO,WAAAC,CAAW,IAAiB,CAC5E,IAAIC,EAAY,GACZC,EAAc,GACdC,EAAqB,EACrBC,EACAC,EAEEC,EAAQ9B,GAAY,CACpB4B,GAAWH,IACbA,EAAY,GACZG,EAAQ5B,CAAI,EAEhB,EAEM+B,EAAS,IAAM,CACnBL,EAAc,GAEVG,GAAUJ,IACZA,EAAY,GACZI,EAAO,WAAW,EAEtB,EAoCA,MAAO,CACL,OAnCa,IAAI,QAAW,CAACT,EAAKY,IAAQ,CAC1CP,EAAY,GACZG,EAAUR,EACVS,EAASG,EAET,IAAMC,EAAU,SAA2B,CACzC,GAAI,GAACR,GAAaC,GAIlB,IAAI,CAGF,GAFA,MAAMJ,EAAQQ,CAAI,EAEd,CAACL,GAAaC,EAChB,OAGF,MAAMR,EAAKK,CAAK,CAClB,OAAS9E,EAAK,CACZ,QAAQ,MAAOA,EAAc,OAAO,EACpCkF,GAAc,EACd,MAAMT,EAAK,GAAKS,EAAaJ,CAAK,CACpC,CAEA,MAAMU,EAAQ,EAChB,EAEIT,EACF,WAAWS,EAAST,CAAU,EAE9BS,EAAQ,CAEZ,CAAC,EAIC,OAAAF,CACF,CACF,EHtDO,IAAMG,EAAoB,IAAO,GAAK,GAAK,EAErCC,EAAa,MAEbC,GAAgB,IAMvBC,EAAiB,CACrBC,EACAC,EACAC,IACG,CACH,OAAO,OAAOF,EAAS,OAAO,YAAY,OAAO,QAAQC,CAAO,EAAE,OAAO,CAAC,CAAC,CAAEE,CAAK,IAAMA,IAAU,MAAS,CAAC,CAAC,EAC7GD,EAAe,CAAE,GAAGF,CAAQ,CAAC,CAC/B,EAMaI,GAAgB,MAAOhE,EAAsBO,IAA2B,CACnF,GAAM,CAAE,eAAAQ,EAAgB,eAAAkD,EAAgB,eAAAH,EAAgB,eAAAI,CAAe,EAAI3D,EACrE4D,EAAe5E,EAAkB,CAAE,MAAO2E,EAAe,YAAa,SAAUnD,CAAe,CAAC,EAChGd,EAAkBD,EAAO,KAAMlC,GAAcA,EAAU,UAAYoG,EAAe,YAAY,OAAO,EACrGvC,EAAepC,EAAkB,CAAE,MAAO2E,EAAe,YAAa,SAAUD,CAAe,CAAC,EAChG/D,EAAkBF,EAAO,KAAMlC,GAAcA,EAAU,UAAYoG,EAAe,YAAY,OAAO,EACrGE,EAAqB,CAAE,GAAGF,CAAe,EAE/C,GAAI,CAACjE,GAAmB,CAACC,EACvB,MAAM,IAAIxC,uBAAkD,EA2H9D,OAAOiF,EAA6B,CAClC,QAzHc,MAAOS,GAA+B,CAMpD,GAAIgB,EAAmB,aAAeA,EAAmB,UAAU,MACjE,OAAOhB,EAAKgB,CAAkB,EAMhC,GAAIA,EAAmB,gBAAkBZ,GAAqB,KAAK,IAAI,EACrE,OAAAG,EAAeS,EAAoB,CAAE,YAAa,KAAK,IAAI,EAAG,cAA6B,EAAGN,CAAc,EACrGV,EAAKgB,CAAkB,EAOhC,IAAMC,EAAY,MAAMF,EAAa,sBAAsB,CACzD,KAAMC,EAAmB,YAC3B,CAAC,EAKD,GAAI,CAACA,EAAmB,iBAAkB,CACxC,IAAME,EAAK,MAAMH,EAAa,eAAe,CAAE,KAAMC,EAAmB,YAAwB,CAAC,EAC3FG,EAAalC,EAAiBiC,EAAID,CAAS,EAE7CE,GACFZ,EAAeS,EAAoB,CAAE,iBAAkBG,CAAW,EAAGT,CAAc,CAEvF,CAKA,GAAIO,EAAU,SAAW,WACvB,OAAAV,EACES,EACA,CAAE,YAAa,KAAK,IAAI,EAAG,cAA0C,EACrEN,CACF,EACOV,EAAKgB,CAAkB,EAShC,IAAMI,EAAoB,MAAML,EAAa,4BAA4B,CACvE,KAAMC,EAAmB,YAC3B,CAAC,EACKK,EAAuBD,EAAoBJ,EAAmB,wBAC9DM,EAA2BF,GAAqBJ,EAAmB,gCAEzE,GAAIK,EAAsB,CACxB,IAAME,EAAU,CAAC,EACjBA,EAAQ,wBAA0B,OAAOH,CAAiB,EAErDE,IACHC,EAAQ,iBAAmB,MAAMhD,EAAa,eAAe,GAG/DgC,EAAeS,EAAoBO,EAASb,CAAc,CAC5D,CAEA,GAAI,CAACY,EACH,OAGGN,EAAmB,kBACtBT,EAAeS,EAAoB,CAAE,iBAAkB,MAAMzC,EAAa,eAAe,CAAE,EAAGmC,CAAc,EAM9G,IAAMc,EAAmBP,EAAU,KAAK,KAAMQ,GACxCA,EAAI,UAAY5E,EAAgB,mBACpBmC,EAAe,CAC3B,IAAKzC,EACL,GAAGkF,CACL,CAAC,EAEY,YAAc,iBAGtB,EACR,EAED,GAAI,CAACD,EACH,MAAM,IAAIlH,mBAER,gEAAgE0G,EAAmB,YAAY,GACjG,EAcF,IAAMU,EAPgB1C,EAAe,CACnC,IAAKzC,EACL,UAAW,iBACX,GAAGiF,CACL,CAAC,EAG2B,KAAK,MACjC,OAAAjB,EAAeS,EAAoB,CAAE,gBAAiB,KAAK,IAAI,EAAG,SAAU,CAAE,MAAAU,CAAM,CAAE,EAAGhB,CAAc,EAChGV,EAAKgB,CAAkB,CAChC,EAIE,MAAOpG,EAA0BiC,EAAgB,OAAO,EACxD,WAAYyD,EACd,CAAC,CACH,EAMaqB,GAAgB,MAAO/E,EAAsBO,IAA2B,CACnF,GAAM,CAAE,eAAA0D,EAAgB,eAAAH,EAAgB,eAAAI,CAAe,EAAI3D,EACrD6D,EAAqB,CAAE,GAAGF,CAAe,EAE/C,GAAI,CAACA,EAAe,aAAe,CAACA,EAAe,UAAU,MAC3D,MAAM,IAAIxG,mBAA+C,kBAAkB,EAG7E,GAAI,CAACwG,EAAe,iBAClB,MAAM,IAAIxG,mBAA+C,6BAA6B,EAGxF,IAAMiE,EAAepC,EAAkB,CAAE,MAAO2E,EAAe,YAAa,SAAUD,CAAe,CAAC,EAChG/D,EAAkBF,EAAO,KAAMlC,GAAcA,EAAU,UAAYoG,EAAe,YAAY,OAAO,EAE3G,GAAI,CAAChE,EACH,MAAM,IAAIxC,mBAER,yBAAyBwG,EAAe,YAAY,OAAO,GAC7D,EAwHF,OAAOvB,EAA6B,CAClC,QAtHc,MAAOS,GAA+B,CAKpD,GAAIgB,EAAmB,YACrB,OAAOhB,EAAKgB,CAAkB,EAMhC,GAAI,CAACA,EAAmB,iBACtB,OAAAT,EACES,EACA,CAAE,YAAa,KAAK,IAAI,EAAG,cAAoC,EAC/DN,CACF,EACOV,EAAKgB,CAAkB,EAMhC,GAAIA,EAAmB,gBAAkBZ,GAAqB,KAAK,IAAI,EACrE,OAAAG,EAAeS,EAAoB,CAAE,YAAa,KAAK,IAAI,EAAG,cAA6B,EAAGN,CAAc,EACrGV,EAAKgB,CAAkB,EAGhC,GAAI,CAACA,EAAmB,aAAc,CACpC,IAAMY,EAAkB,MAAMrD,EAAa,eAAe,EACpDsD,EAAoBb,EAAmB,iBAAmBX,EAC1DyB,EAAYD,GAAqB,GAAKA,EAAoB,WAC1DE,EAAqBf,EAAmB,iBAAmBX,EAC3D2B,EAAUD,EAAqBH,EAAkBG,EAAqB,SAEtEE,EAAa,MAAM1D,EAAa,QAAQ,CAC5C,QAASzB,EAAgB,0BACzB,MAAO,CACL,KAAM,kBACN,KAAM,QACN,OAAQ,CACN,CAAE,QAAS,GAAM,aAAc,UAAW,KAAM,SAAU,KAAM,SAAU,EAC1E,CAAE,QAAS,GAAO,aAAc,SAAU,KAAM,eAAgB,KAAM,QAAS,EAC/E,CAAE,QAAS,GAAM,aAAc,SAAU,KAAM,QAAS,KAAM,QAAS,EACvE,CAAE,QAAS,GAAO,aAAc,UAAW,KAAM,SAAU,KAAM,SAAU,EAC3E,CAAE,QAAS,GAAO,aAAc,QAAS,KAAM,cAAe,KAAM,OAAQ,CAC9E,CACF,EACA,KAAM,CAAE,MAAOkE,EAAmB,SAAU,KAAgB,EAC5D,UAAAc,EACA,QAAAE,CACF,CAAC,EAED,GAAIC,EAAW,CAAC,GAAG,gBACjB1B,EAAeS,EAAoB,CAAE,aAAciB,EAAW,CAAC,EAAE,eAAgB,EAAGvB,CAAc,MAC7F,CACLH,EAAeS,EAAoB,CAAE,iBAAkBY,CAAgB,EAAGlB,CAAc,EACxF,MACF,CACF,CAMA,IAAMO,EAAY,MAAM1C,EAAa,sBAAsB,CACzD,KAAMyC,EAAmB,YAC3B,CAAC,EAKD,GAAI,CAACA,EAAmB,iBAAkB,CACxC,IAAME,EAAK,MAAM3C,EAAa,eAAe,CAAE,KAAMyC,EAAmB,YAAwB,CAAC,EAC3FG,EAAalC,EAAiBiC,EAAID,CAAS,EAE7CE,GACFZ,EAAeS,EAAoB,CAAE,iBAAkBG,CAAW,EAAGT,CAAc,CAEvF,CAKA,GAAIO,EAAU,SAAW,WACvB,OAAAV,EACES,EACA,CAAE,YAAa,KAAK,IAAI,EAAG,cAA0C,EACrEN,CACF,EACOV,EAAKgB,CAAkB,EAQhC,IAAMI,EAAoB,MAAM7C,EAAa,4BAA4B,CACvE,KAAMyC,EAAmB,YAC3B,CAAC,EACKK,EAAuBD,EAAoBJ,EAAmB,wBAC9DM,EAA2BF,GAAqBJ,EAAmB,gCAMzE,GAJIK,GACFd,EAAeS,EAAoB,CAAE,wBAAyB,OAAOI,CAAiB,CAAE,EAAGV,CAAc,EAGvG,EAACY,EAIL,OAAAf,EAAeS,EAAoB,CAAE,YAAa,KAAK,IAAI,CAAE,EAAGN,CAAc,EACvEV,EAAKgB,CAAkB,CAChC,EAIE,MAAOpG,EAA0BkC,EAAgB,OAAO,EACxD,WAAYwD,EACd,CAAC,CACH,EAEO,SAAS4B,GAAcnH,EAAuBoC,EAAwB,CAC3E,IAAIgF,EAEElC,EAAS,IAAM,CACnBkC,IAAU,CACZ,EA0BA,MAAO,CACL,QAzBsB,SAAY,CAClC,MAAMpH,EAAO,gBAAgB,EAE7B,GAAM,CAAE,eAAA4C,EAAgB,eAAAkD,EAAgB,eAAAH,EAAgB,eAAAI,CAAe,EAAI3D,EAErE,CAAE,OAAQiF,EAAe,OAAQC,CAAqB,EAAI,MAAMzB,GAAc7F,EAAO,OAAS,CAClG,eAAA4C,EACA,eAAAkD,EACA,eAAAH,EACA,eAAAI,CACF,CAAC,EACDqB,EAAUE,EACV,IAAMC,EAA8B,MAAMF,EAEpC,CAAE,OAAQG,EAAe,OAAQC,CAAqB,EAAI,MAAMb,GAAc5G,EAAO,OAAS,CAClG,eAAA4C,EACA,eAAAkD,EACA,eAAAH,EACA,eAAgB4B,CAClB,CAAC,EACD,OAAAH,EAAUK,EACHD,CACT,GAG0B,EACxB,OAAAtC,CACF,CACF,CIpWO,IAAMwC,GAA2ChI,IAC/C,CACL,YACA,OAAQ,KACR,aAAc,gBAAkB,CAC9B,KAAK,OAAS,MAAMD,EAAUC,CAAW,CAC3C,EACA,gBAAiB,gBAAkB,CACjC,OAAOsE,EAAgB,IAAI,CAC7B,EACA,UAAW,gBAAkB,CAC3B,OAAOjE,EAAU,IAAI,CACvB,EACA,QAAS,eAAgBqC,EAAQ,CAC/B,OAAOD,EAAQ,KAAMC,CAAM,CAC7B,EACA,cAAe,eAAgBA,EAAQ,CACrC,OAAOqB,EAAc,KAAMrB,EAAQ1C,CAAW,CAChD,EACA,cAAe,SAAU0C,EAAQ,CAC/B,OAAO+E,GAAc,KAAM/E,CAAM,CACnC,CACF,GCxBK,IAAMuF,GAAmB,IAAI,IAAI,CAAC,QAAkBD,EAAiB,CAAC,CAAC,EAEjEE,GAA2B,CAAClI,EAA0BmI,IAC1D,IAAI,IACT,CAAC,GAAGF,EAAgB,EACjB,OAAO,CAAC,CAACG,CAAU,IAAM,CAACD,GAAqB,SAASC,CAAU,CAAC,EACnE,IAAI,CAAC,CAACA,EAAYC,CAAO,IAAM,CAACD,EAAYC,EAAQrI,CAAW,CAAC,CAAC,CACtE,EAGWsI,EAAuB,CAClCC,EACA9H,EACA+H,IACG,CACH,IAAMJ,EAAa3H,EAAM,aAAa+H,CAAa,GAAG,KAAMJ,GAAeG,EAAsB,IAAIH,CAAU,CAAC,EAEhH,GAAI,CAACA,EACH,MAAM,IAAIzI,EAGZ,MAAO,CACL,KAAMyI,EACN,OAAQG,EAAsB,IAAIH,CAAU,CAC9C,CACF,EC3BA,OAAS,WAAAK,GAAS,aAAAC,OAAiB,SAG5B,IAAMC,GAA6B,CAAC,CAAE,YAAA3I,EAAa,oBAAAmI,CAAoB,IAA2B,CACvG,IAAMI,EAAwBL,GAAyBlI,EAAamI,CAAmB,EAEjFS,EAAgB,SAAY,CAChC,MAAM,QAAQ,WACZ,MAAM,KAAKL,CAAqB,EAAE,IAAI,CAAC,CAAC,CAAEM,CAAa,IAAMA,EAAc,aAAa,CAAC,CAC3F,CACF,EAgEA,MAAO,CACL,YAAA7I,EACA,QAASuI,EACT,KAjEW,SAAY,CACvB,MAAMK,EAAc,CACtB,EAgEE,cAAAA,EACA,UA/DgB,UACD,MAAM,QAAQ,IAAI,MAAM,KAAKL,CAAqB,EAAE,IAAI,CAAC,CAAC,CAAEjI,CAAM,IAAMA,EAAO,UAAU,CAAC,CAAC,GAC5F,OAAsB,CAACwI,EAAkBC,IAAkB,CACvE,OAAW,CAAC3I,EAAS4I,CAAY,IAAK,OAAO,QAAQD,CAAa,EAAG,CACnE,IAAME,EAAiBH,EAAiB1I,CAAO,EAE/C,GAAI6I,EACF,QAAWC,KAAeF,EAAc,CACtC,IAAMG,EAAQF,EAAe,UAAU,CAAC,CAAE,OAAAG,CAAO,IAAMA,IAAWF,EAAY,MAAM,EAEhFC,IAAU,GACZF,EAAe,KAAKC,CAAW,EAE/BR,GAAUO,EAAeE,CAAK,EAAGD,EAAa,CAACG,EAAUC,IAAa,CACpE,GAAIb,GAAQY,CAAQ,EAClB,MAAO,CAAC,GAAG,IAAI,IAAIA,EAAS,OAAOC,CAAQ,CAAC,CAAC,CAEjD,CAAC,CAEL,MAEAR,EAAiB1I,CAAO,EAAI4I,CAEhC,CAEA,OAAOF,CACT,EAAG,CAAC,CAAC,EAsCL,QAnCc,MAAOpG,GAAsB,CAC3C,GAAM,CAAE,OAAApC,CAAO,EAAIgI,EAAqBC,EAAuB7F,EAAO,MAAOA,EAAO,YAAY,OAAO,EACvG,OAAOpC,EAAO,QAAQoC,CAAM,CAC9B,EAiCE,iBA1BuB,CAACjC,EAAoB+H,IAA0B,CACtE,GAAI,CACF,OAAAF,EAAqBC,EAAuB9H,EAAO+H,CAAa,EACzD,EACT,MAAQ,CACN,MAAO,EACT,CACF,EAoBE,cAhCoB,MAAO9F,GAA2B,CACtD,GAAM,CAAE,OAAApC,CAAO,EAAIgI,EAAqBC,EAAuB7F,EAAO,MAAOA,EAAO,YAAY,OAAO,EACvG,OAAOpC,EAAO,cAAcoC,CAAM,CACpC,EA8BE,cAnBqBA,GAA2B,CAChD,IAAMpC,EAASiI,EAAsB,IAAI7F,EAAO,eAAe,IAAI,EAEnE,GAAI,CAACpC,EACH,MAAM,IAAIX,EAGZ,OAAOW,EAAO,cAAcoC,CAAM,CACpC,CAYA,CACF","sourcesContent":["import type { Address } from 'viem';\nimport type { BridgeType } from './bridge';\n\nexport enum TokenType {\n NATIVE = 'native',\n ERC20 = 'erc20',\n}\n\nexport type Asset = {\n type: TokenType;\n address?: Address;\n name: string;\n symbol: string;\n decimals: number;\n};\n\n// chainId - bridge type pairs\nexport type DestinationInfo = Record<string, BridgeType[]>;\n\nexport type BridgeAsset = Asset & {\n destinations: DestinationInfo;\n};\n\nexport type ChainAssetMap = Record<string, BridgeAsset[]>;\n\nexport type AssetFeeMap = Record<Address, bigint>;\n","import type { AssetFeeMap, BridgeAsset, ChainAssetMap } from './asset';\nimport type { Chain } from './chain';\nimport type { BridgeConfig } from './config';\nimport type { Environment } from './environment';\nimport type { Provider } from './provider';\nimport type { Signer } from './signer';\nimport type { BridgeTransfer } from './transfer';\n\nexport enum BridgeType {\n CCTP = 'cctp',\n}\n\nexport type FeeParams = {\n asset: BridgeAsset;\n amount: bigint;\n sourceChain: Chain;\n targetChain: Chain;\n provider?: Provider;\n};\n\nexport enum BridgeSignatureReason {\n AllowanceApproval = 'allowance-approval',\n TokensTransfer = 'tokens-transfer',\n}\n\nexport type BridgeStepDetails = {\n currentSignature: number;\n requiredSignatures: number;\n currentSignatureReason: BridgeSignatureReason;\n};\n\nexport type TransferParams = {\n asset: BridgeAsset;\n amount: bigint;\n fromAddress: string;\n toAddress?: string;\n sourceChain: Chain;\n targetChain: Chain;\n sourceProvider?: Provider;\n targetProvider?: Provider;\n onStepChange?: (stepDetails: BridgeStepDetails) => void;\n sign?: Signer;\n};\n\nexport type TrackingParams = {\n bridgeTransfer: BridgeTransfer;\n sourceProvider?: Provider;\n targetProvider?: Provider;\n updateListener: (transfer: BridgeTransfer) => void;\n};\n\nexport type BridgeService = {\n type: BridgeType;\n config: BridgeConfig | null;\n ensureHasConfig: () => Promise<void>;\n updateConfig: () => Promise<void>;\n getAssets: () => Promise<ChainAssetMap>;\n getFees: (params: FeeParams) => Promise<AssetFeeMap>;\n transferAsset: (params: TransferParams) => Promise<BridgeTransfer>;\n trackTransfer: (transfer: TrackingParams) => { cancel: () => void; result: Promise<BridgeTransfer> };\n};\n\nexport type BridgeServiceFactory = (environment: Environment) => BridgeService;\n","export enum Environment {\n PROD = 'production',\n TEST = 'test',\n}\n","export enum ErrorCode {\n BRIDGE_NOT_AVAILABLE = 5001,\n INITIALIZATION_FAILED = 5002,\n INVALID_PARAMS = 5003,\n TIMEOUT = 5004,\n TRANSACTION_REVERTED = 5005,\n}\n\nexport enum ErrorReason {\n UNKNOWN = 'UNKNOWN', // generic, not specified error\n CONFIG_NOT_AVAILABLE = 'CONFIG_NOT_AVAILABLE', // error while fetching or parsing the config\n INVALID_PARAMS = 'INVALID_PARAMS', // generic error with the params\n IDENTICAL_CHAINS_PROVIDED = 'IDENTICAL_CHAINS_PROVIDED', // provided source and target chains are the same\n INCORRECT_AMOUNT_PROVIDED = 'INCORRECT_AMOUNT_PROVIDED', // the transfer amount is incorrect (e.g.: lesser than or equal to zero)\n INCORRECT_ADDRESS_PROVIDED = 'INCORRECT_ADDRESS_PROVIDED', // the sender or recipient address is incorrect\n CHAIN_NOT_SUPPORTED = 'CHAIN_NOT_SUPPORTED', // the provided source or target chain is not supported by the bridge\n ASSET_NOT_SUPPORTED = 'ASSET_NOT_SUPPORTED', // the provided asset is not supported by the bridge\n CONFIRMATION_COUNT_UNKNOWN = 'CONFIRMATION_COUNT_UNKNOWN', // required confirmation count of the source or target chain is unknown\n}\n","import type { ErrorCode } from '../types';\n\nexport class BridgeError extends Error {\n constructor(\n message: string,\n public code: ErrorCode,\n public details?: string,\n ) {\n super(message);\n }\n}\n","import { ErrorCode, ErrorReason } from '../types';\nimport { BridgeError } from './bridge-error';\n\nexport class BridgeUnavailableError extends BridgeError {\n constructor(message = ErrorReason.UNKNOWN, details?: string) {\n super(message, ErrorCode.BRIDGE_NOT_AVAILABLE, details);\n this.name = 'BridgeUnavailableError';\n }\n}\n","import { ErrorCode, ErrorReason } from '../types';\nimport { BridgeError } from './bridge-error';\n\nexport class BridgeInitializationError extends BridgeError {\n constructor(message = ErrorReason.UNKNOWN, details?: string) {\n super(message, ErrorCode.INITIALIZATION_FAILED, details);\n this.name = 'BridgeInitializationError';\n }\n}\n","import { ErrorCode, ErrorReason } from '../types';\nimport { BridgeError } from './bridge-error';\n\nexport class InvalidParamsError extends BridgeError {\n constructor(message = ErrorReason.INVALID_PARAMS, details?: string) {\n super(message, ErrorCode.INVALID_PARAMS, details);\n this.name = 'InvalidParamsError';\n }\n}\n","import { BridgeInitializationError } from '../../../errors';\nimport { ErrorReason } from '../../../types';\nimport { Environment } from '../../../types/environment';\nimport { AvalancheChainIds } from '../types/chain';\nimport type { Config } from '../types/config';\n\nconst CONFIG_URLS: Record<Environment, string> = {\n [Environment.TEST]:\n 'https://raw.githubusercontent.com/ava-labs/avalanche-bridge-resources/main/cctp/cctp_config.test.json',\n [Environment.PROD]:\n 'https://raw.githubusercontent.com/ava-labs/avalanche-bridge-resources/main/cctp/cctp_config.json',\n};\n\nexport const getConfig = async (environment: Environment): Promise<Config> => {\n try {\n const response = await fetch(CONFIG_URLS[environment]!);\n const config: Config = await response.json();\n\n return config.map((chainData) => ({ ...chainData, chainId: `eip155:${chainData.chainId}` }));\n } catch (err) {\n throw new BridgeInitializationError(\n ErrorReason.CONFIG_NOT_AVAILABLE,\n `Error while fetching CCTP config: ${(err as unknown as Error).message}`,\n );\n }\n};\n\nexport const getTrackingDelayByChainId = (chainId: string) => {\n switch (chainId) {\n case AvalancheChainIds.MAINNET:\n case AvalancheChainIds.FUJI:\n return 1000;\n default:\n return 20000;\n }\n};\n","import { TokenType, type BridgeService, type ChainAssetMap, type DestinationInfo, BridgeType } from '../../../types';\n\nexport async function getAssets(bridge: BridgeService) {\n await bridge.ensureHasConfig();\n\n const chainIds = bridge.config!.map((chainData) => chainData.chainId);\n\n return bridge.config!.reduce<ChainAssetMap>((assets, chainData) => {\n assets[chainData.chainId] = chainData.tokens.map((asset) => ({\n ...asset,\n type: TokenType.ERC20,\n destinations: chainIds.reduce<DestinationInfo>((destinations, chainId) => {\n if (chainData.chainId !== chainId) {\n if (!destinations[chainId]) {\n destinations[chainId] = [];\n }\n\n destinations[chainId]?.push(BridgeType.CCTP);\n }\n\n return destinations;\n }, {}),\n }));\n\n return assets;\n }, {});\n}\n","import { createWalletClient, publicActions, custom, http } from 'viem';\nimport type { Chain } from '../types/chain';\nimport type { Provider } from '../types';\nimport caip2 from './caip2';\n\nconst _getChain = (chain: Chain) => {\n const { reference: chainId } = caip2.toJSON(chain.chainId);\n\n return {\n id: Number(chainId),\n name: chain.chainName,\n nativeCurrency: {\n decimals: chain.networkToken.decimals,\n symbol: chain.networkToken.symbol,\n name: chain.networkToken.name,\n },\n network: chain.chainName,\n rpcUrls: {\n default: {\n http: [chain.rpcUrl],\n },\n public: {\n http: [chain.rpcUrl],\n },\n },\n ...(chain.utilityAddresses?.multicall && {\n contracts: {\n multicall3: {\n address: chain.utilityAddresses.multicall,\n },\n },\n }),\n };\n};\n\nexport const getClientForChain = ({ chain, provider }: { chain: Chain; provider?: Provider }) => {\n const chainInfo = _getChain(chain);\n const transport = provider ? custom(provider) : http(chain.rpcUrl, { batch: true, retryCount: 0 });\n\n return createWalletClient({\n chain: chainInfo,\n transport,\n }).extend(publicActions);\n};\n","// ref: https://chainagnostic.org/CAIPs/caip-2\n\nexport type Caip2ChainId = {\n namespace: string;\n reference: string;\n};\n\nconst namespacePattern = '^[-a-z0-9]{3,8}$';\n// the standard allows up to 32 characters for the reference part, but we have to set it to 50 so it accepts our cb58 encoded chain IDs\nconst referencePattern = '^[-_a-zA-Z0-9]{1,50}$';\nconst delimeter = ':';\n\nconst toJSON = (identifier: string): Caip2ChainId => {\n const [namespace, reference] = identifier.split(delimeter);\n\n if (!namespace || !reference) {\n throw new Error('Invalid identifier provided.');\n }\n\n if (!new RegExp(namespacePattern).test(namespace)) {\n throw new Error('Invalid namespace provided.');\n }\n\n if (!new RegExp(referencePattern).test(reference)) {\n throw new Error('Invalid reference provided.');\n }\n\n return {\n namespace,\n reference,\n };\n};\n\nconst toString = ({ namespace, reference }: Caip2ChainId) => {\n return `${namespace}${delimeter}${reference}`;\n};\n\nexport default {\n toJSON,\n toString,\n};\n","export const TOKEN_ROUTER_ABI = [\n {\n inputs: [\n {\n internalType: 'address',\n name: 'circleTokenMessenger_',\n type: 'address',\n },\n {\n internalType: 'address',\n name: 'burnToken_',\n type: 'address',\n },\n ],\n stateMutability: 'nonpayable',\n type: 'constructor',\n },\n {\n inputs: [],\n name: 'AlreadyAdmin',\n type: 'error',\n },\n {\n inputs: [],\n name: 'AlreadyFeeCollector',\n type: 'error',\n },\n {\n inputs: [],\n name: 'AlreadySupportedBurnToken',\n type: 'error',\n },\n {\n inputs: [],\n name: 'AmountLessThanFee',\n type: 'error',\n },\n {\n inputs: [],\n name: 'BalanceNotIncreased',\n type: 'error',\n },\n {\n inputs: [],\n name: 'CannotRemoveLastAdmin',\n type: 'error',\n },\n {\n inputs: [],\n name: 'FeePercentageGreaterThanMax',\n type: 'error',\n },\n {\n inputs: [],\n name: 'InvalidAdminAddress',\n type: 'error',\n },\n {\n inputs: [],\n name: 'InvalidFeeCollector',\n type: 'error',\n },\n {\n inputs: [],\n name: 'InvalidMintRecipientAddress',\n type: 'error',\n },\n {\n inputs: [],\n name: 'InvalidTokenAddress',\n type: 'error',\n },\n {\n inputs: [],\n name: 'InvalidTokenMessengerAddress',\n type: 'error',\n },\n {\n inputs: [],\n name: 'MaxFeeLessThanMinFee',\n type: 'error',\n },\n {\n inputs: [],\n name: 'NotAdmin',\n type: 'error',\n },\n {\n inputs: [],\n name: 'NotFeeCollector',\n type: 'error',\n },\n {\n inputs: [],\n name: 'UnSupportedBurnToken',\n type: 'error',\n },\n {\n inputs: [],\n name: 'UnsupportedDomain',\n type: 'error',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: false,\n internalType: 'address',\n name: 'admin',\n type: 'address',\n },\n ],\n name: 'AdminAdded',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: false,\n internalType: 'address',\n name: 'admin',\n type: 'address',\n },\n ],\n name: 'AdminRemoved',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: false,\n internalType: 'address',\n name: 'token',\n type: 'address',\n },\n ],\n name: 'BurnTokenAdded',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: false,\n internalType: 'address',\n name: 'token',\n type: 'address',\n },\n ],\n name: 'BurnTokenRemoved',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: false,\n internalType: 'address',\n name: 'feeCollector',\n type: 'address',\n },\n ],\n name: 'FeeCollectorAdded',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: false,\n internalType: 'address',\n name: 'feeCollector',\n type: 'address',\n },\n ],\n name: 'FeeCollectorRemoved',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: false,\n internalType: 'uint32',\n name: 'domain',\n type: 'uint32',\n },\n {\n components: [\n {\n internalType: 'uint256',\n name: 'maxFee',\n type: 'uint256',\n },\n {\n internalType: 'uint256',\n name: 'minFee',\n type: 'uint256',\n },\n {\n internalType: 'uint32',\n name: 'feePercentage',\n type: 'uint32',\n },\n {\n internalType: 'uint256',\n name: 'txnFee',\n type: 'uint256',\n },\n {\n internalType: 'bool',\n name: 'supported',\n type: 'bool',\n },\n ],\n indexed: false,\n internalType: 'struct FeeCalculator.FeeConfiguration',\n name: 'feeConfiguration',\n type: 'tuple',\n },\n ],\n name: 'FeeConfigurationUpdated',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: true,\n internalType: 'address',\n name: 'previousOwner',\n type: 'address',\n },\n {\n indexed: true,\n internalType: 'address',\n name: 'newOwner',\n type: 'address',\n },\n ],\n name: 'OwnershipTransferred',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: false,\n internalType: 'address',\n name: 'account',\n type: 'address',\n },\n ],\n name: 'Paused',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: false,\n internalType: 'uint64',\n name: 'nonce',\n type: 'uint64',\n },\n {\n indexed: false,\n internalType: 'address',\n name: 'burnToken',\n type: 'address',\n },\n {\n indexed: false,\n internalType: 'uint256',\n name: 'amount',\n type: 'uint256',\n },\n {\n indexed: false,\n internalType: 'address',\n name: 'depositor',\n type: 'address',\n },\n {\n indexed: false,\n internalType: 'address',\n name: 'mintRecipient',\n type: 'address',\n },\n {\n indexed: false,\n internalType: 'uint32',\n name: 'destinationDomain',\n type: 'uint32',\n },\n {\n indexed: false,\n internalType: 'uint256',\n name: 'totalFee',\n type: 'uint256',\n },\n ],\n name: 'TransferTokens',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: false,\n internalType: 'address',\n name: 'account',\n type: 'address',\n },\n ],\n name: 'Unpaused',\n type: 'event',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'account',\n type: 'address',\n },\n ],\n name: 'addAdmin',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'feeCollector',\n type: 'address',\n },\n ],\n name: 'addFeeCollector',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'token',\n type: 'address',\n },\n ],\n name: 'addSupportedBurnToken',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'uint256',\n name: 'amount',\n type: 'uint256',\n },\n {\n internalType: 'uint32',\n name: 'destinationDomain',\n type: 'uint32',\n },\n ],\n name: 'calculateFee',\n outputs: [\n {\n internalType: 'uint256',\n name: '',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'circleTokenMessenger',\n outputs: [\n {\n internalType: 'contract ICircleTokenMessenger',\n name: '',\n type: 'address',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'circleTokenMessengerAddress',\n outputs: [\n {\n internalType: 'address',\n name: '',\n type: 'address',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'token',\n type: 'address',\n },\n ],\n name: 'collectFees',\n outputs: [\n {\n internalType: 'bool',\n name: '',\n type: 'bool',\n },\n ],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'token',\n type: 'address',\n },\n ],\n name: 'getFeeAmounts',\n outputs: [\n {\n internalType: 'uint256',\n name: '',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'uint32',\n name: 'domain',\n type: 'uint32',\n },\n ],\n name: 'getFeeConfiguration',\n outputs: [\n {\n components: [\n {\n internalType: 'uint256',\n name: 'maxFee',\n type: 'uint256',\n },\n {\n internalType: 'uint256',\n name: 'minFee',\n type: 'uint256',\n },\n {\n internalType: 'uint32',\n name: 'feePercentage',\n type: 'uint32',\n },\n {\n internalType: 'uint256',\n name: 'txnFee',\n type: 'uint256',\n },\n {\n internalType: 'bool',\n name: 'supported',\n type: 'bool',\n },\n ],\n internalType: 'struct FeeCalculator.FeeConfiguration',\n name: '',\n type: 'tuple',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'uint32',\n name: 'domain',\n type: 'uint32',\n },\n ],\n name: 'getFeePercentage',\n outputs: [\n {\n internalType: 'uint32',\n name: '',\n type: 'uint32',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'uint32',\n name: 'domain',\n type: 'uint32',\n },\n ],\n name: 'getMaxFee',\n outputs: [\n {\n internalType: 'uint256',\n name: '',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'uint32',\n name: 'domain',\n type: 'uint32',\n },\n ],\n name: 'getMinFee',\n outputs: [\n {\n internalType: 'uint256',\n name: '',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'uint32',\n name: 'domain',\n type: 'uint32',\n },\n ],\n name: 'getTxnFee',\n outputs: [\n {\n internalType: 'uint256',\n name: '',\n type: 'uint256',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'account',\n type: 'address',\n },\n ],\n name: 'isAdmin',\n outputs: [\n {\n internalType: 'bool',\n name: '',\n type: 'bool',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'account',\n type: 'address',\n },\n ],\n name: 'isFeeCollector',\n outputs: [\n {\n internalType: 'bool',\n name: '',\n type: 'bool',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'token',\n type: 'address',\n },\n ],\n name: 'isSupportedBurnToken',\n outputs: [\n {\n internalType: 'bool',\n name: '',\n type: 'bool',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'uint32',\n name: 'domain',\n type: 'uint32',\n },\n ],\n name: 'isSupportedDomain',\n outputs: [\n {\n internalType: 'bool',\n name: '',\n type: 'bool',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'owner',\n outputs: [\n {\n internalType: 'address',\n name: '',\n type: 'address',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'pause',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [],\n name: 'paused',\n outputs: [\n {\n internalType: 'bool',\n name: '',\n type: 'bool',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'account',\n type: 'address',\n },\n ],\n name: 'removeAdmin',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'feeCollector',\n type: 'address',\n },\n ],\n name: 'removeFeeCollector',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'token',\n type: 'address',\n },\n ],\n name: 'removeSupportedBurnToken',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [],\n name: 'renounceOwnership',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'uint32',\n name: 'domain',\n type: 'uint32',\n },\n {\n components: [\n {\n internalType: 'uint256',\n name: 'maxFee',\n type: 'uint256',\n },\n {\n internalType: 'uint256',\n name: 'minFee',\n type: 'uint256',\n },\n {\n internalType: 'uint32',\n name: 'feePercentage',\n type: 'uint32',\n },\n {\n internalType: 'uint256',\n name: 'txnFee',\n type: 'uint256',\n },\n {\n internalType: 'bool',\n name: 'supported',\n type: 'bool',\n },\n ],\n internalType: 'struct FeeCalculator.FeeConfiguration',\n name: 'feeConfiguration',\n type: 'tuple',\n },\n ],\n name: 'setFeeConfiguration',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: '',\n type: 'address',\n },\n ],\n name: 'supportedBurnTokens',\n outputs: [\n {\n internalType: 'bool',\n name: '',\n type: 'bool',\n },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'address',\n name: 'newOwner',\n type: 'address',\n },\n ],\n name: 'transferOwnership',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n {\n internalType: 'uint256',\n name: 'amount',\n type: 'uint256',\n },\n {\n internalType: 'uint32',\n name: 'destinationDomain',\n type: 'uint32',\n },\n {\n internalType: 'address',\n name: 'mintRecipient',\n type: 'address',\n },\n {\n internalType: 'address',\n name: 'burnToken',\n type: 'address',\n },\n ],\n name: 'transferTokens',\n outputs: [\n {\n internalType: 'uint64',\n name: 'nonce',\n type: 'uint64',\n },\n ],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [],\n name: 'unpause',\n outputs: [],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n] as const;\n","import { InvalidParamsError } from '../../../errors';\nimport { ErrorReason } from '../../../types';\nimport type { TransferParams } from '../../../types/bridge';\nimport type { Config } from '../types/config';\n\ntype PartialTransferParams = Pick<TransferParams, 'sourceChain' | 'targetChain' | 'amount' | 'asset'>;\n\nexport const getTransferData = ({ sourceChain, targetChain, amount, asset }: PartialTransferParams, config: Config) => {\n if (sourceChain.chainId === targetChain.chainId) {\n throw new InvalidParamsError(ErrorReason.IDENTICAL_CHAINS_PROVIDED);\n }\n\n if (amount <= 0n) {\n throw new InvalidParamsError(ErrorReason.INCORRECT_AMOUNT_PROVIDED, 'Amount must be greater than zero');\n }\n\n const sourceChainData = config.find((chainData) => chainData.chainId === sourceChain.chainId);\n\n if (!sourceChainData) {\n throw new InvalidParamsError(\n ErrorReason.CHAIN_NOT_SUPPORTED,\n `Not supported on source chain \"${sourceChain.chainId}\"`,\n );\n }\n\n const targetChainData = config.find((chainData) => chainData.chainId === targetChain.chainId);\n\n if (!targetChainData) {\n throw new InvalidParamsError(\n ErrorReason.CHAIN_NOT_SUPPORTED,\n `Not supported on target chain \"${targetChain.chainId}\"`,\n );\n }\n\n const burnToken = sourceChainData.tokens.find((token) => token.symbol === asset.symbol);\n const mintToken = targetChainData.tokens.find((token) => token.symbol === asset.symbol);\n\n if (!burnToken || !mintToken) {\n throw new InvalidParamsError(ErrorReason.ASSET_NOT_SUPPORTED);\n }\n\n return {\n sourceChainData,\n targetChainData,\n burnToken,\n mintToken,\n };\n};\n","import type { AssetFeeMap, BridgeService, FeeParams } from '../../../types';\nimport { getClientForChain } from '../../../utils/client';\nimport { TOKEN_ROUTER_ABI } from '../abis/token-router';\nimport { getTransferData } from '../utils/transfer-data';\n\nexport async function getFees(bridge: BridgeService, params: FeeParams) {\n await bridge.ensureHasConfig();\n\n const { sourceChain, targetChain, asset, amount, provider } = params;\n const { sourceChainData, targetChainData, burnToken } = getTransferData(\n { sourceChain, targetChain, asset, amount },\n bridge.config!,\n );\n\n const client = getClientForChain({ chain: sourceChain, provider });\n const feeAmount = await client.readContract({\n address: sourceChainData.tokenRouterAddress,\n abi: TOKEN_ROUTER_ABI,\n functionName: 'calculateFee',\n args: [amount, targetChainData.domain],\n });\n\n return {\n [burnToken.address]: feeAmount,\n } as AssetFeeMap;\n}\n","import { encodeFunctionData, isAddress, type PublicClient } from 'viem';\nimport {\n ErrorReason,\n type BridgeService,\n type Environment,\n type TransferParams,\n type Hex,\n type BridgeTransfer,\n BridgeSignatureReason,\n} from '../../../types';\nimport { getClientForChain } from '../../../utils/client';\nimport { ERC20_ABI } from '../abis/erc20';\nimport { getTransferData } from '../utils/transfer-data';\nimport { TOKEN_ROUTER_ABI } from '../abis/token-router';\nimport { InvalidParamsError } from '../../../errors';\n\nconst approveAndTransfer = async (bridge: BridgeService, params: TransferParams) => {\n const {\n sourceChain,\n targetChain,\n asset,\n amount,\n fromAddress,\n toAddress: maybeToAddress,\n sourceProvider,\n onStepChange,\n sign,\n } = params;\n const toAddress = maybeToAddress ?? fromAddress;\n\n if (!isAddress(fromAddress) || !isAddress(toAddress)) {\n throw new InvalidParamsError(ErrorReason.INCORRECT_ADDRESS_PROVIDED);\n }\n\n const { sourceChainData, targetChainData, burnToken } = getTransferData(\n { sourceChain, targetChain, asset, amount },\n bridge.config!,\n );\n const client = getClientForChain({ chain: sourceChain, provider: sourceProvider });\n\n const allowance = await client.readContract({\n address: burnToken.address,\n abi: ERC20_ABI,\n functionName: 'allowance',\n args: [fromAddress, sourceChainData.tokenRouterAddress],\n });\n\n const isAllowanceApprovalRequired = allowance < amount;\n const requiredSignatures = isAllowanceApprovalRequired ? 2 : 1; // if approval is required, we'll need 2 signatures\n\n if (isAllowanceApprovalRequired) {\n onStepChange?.({\n currentSignature: 1,\n currentSignatureReason: BridgeSignatureReason.AllowanceApproval,\n requiredSignatures,\n });\n\n if (sign) {\n const data = encodeFunctionData({\n abi: ERC20_ABI,\n functionName: 'approve',\n args: [sourceChainData.tokenRouterAddress, amount],\n });\n\n const txHash = await sign(\n {\n from: fromAddress,\n to: burnToken.address,\n data,\n },\n (signedTxHash: Hex) => client.sendRawTransaction({ serializedTransaction: signedTxHash }),\n );\n\n await client.waitForTransactionReceipt({ hash: txHash, pollingInterval: 1_000 });\n } else {\n const { request } = await client.simulateContract({\n account: fromAddress,\n address: burnToken.address,\n abi: ERC20_ABI,\n functionName: 'approve',\n args: [sourceChainData.tokenRouterAddress, amount],\n });\n\n const txHash = await client.writeContract(request);\n await client.waitForTransactionReceipt({ hash: txHash, pollingInterval: 1_000 });\n }\n }\n\n onStepChange?.({\n currentSignature: isAllowanceApprovalRequired ? 2 : 1,\n currentSignatureReason: BridgeSignatureReason.TokensTransfer,\n requiredSignatures,\n });\n\n if (sign) {\n const data = encodeFunctionData({\n abi: TOKEN_ROUTER_ABI,\n functionName: 'transferTokens',\n args: [amount, targetChainData.domain, toAddress, burnToken.address],\n });\n\n return sign(\n {\n from: fromAddress,\n to: sourceChainData.tokenRouterAddress,\n data,\n },\n (signedTxHash: Hex) => client.sendRawTransaction({ serializedTransaction: signedTxHash }),\n );\n } else {\n const { request } = await client.simulateContract({\n account: fromAddress,\n address: sourceChainData.tokenRouterAddress,\n abi: TOKEN_ROUTER_ABI,\n functionName: 'transferTokens',\n args: [amount, targetChainData.domain, toAddress, burnToken.address],\n });\n\n return client.writeContract(request);\n }\n};\n\nconst getStartBlockNumber = async (targetClient: PublicClient) => {\n try {\n const startBlockNumber = await targetClient.getBlockNumber();\n return startBlockNumber;\n } catch {\n return undefined;\n }\n};\n\nexport async function transferAsset(\n bridge: BridgeService,\n params: TransferParams,\n environment: Environment,\n): Promise<BridgeTransfer> {\n await bridge.ensureHasConfig();\n\n const { minimumConfirmations: requiredSourceConfirmationCount } =\n bridge.config!.find((chainData) => chainData.chainId === params.sourceChain.chainId) ?? {};\n const { minimumConfirmations: requiredTargetConfirmationCount } =\n bridge.config!.find((chainData) => chainData.chainId === params.targetChain.chainId) ?? {};\n\n if (!requiredSourceConfirmationCount || !requiredTargetConfirmationCount) {\n throw new InvalidParamsError(ErrorReason.CONFIRMATION_COUNT_UNKNOWN);\n }\n\n const fees = await bridge.getFees({ ...params, provider: params.sourceProvider });\n\n const bridgeFee = (params.asset.address && fees[params.asset.address]) ?? 0n;\n const txHash = await approveAndTransfer(bridge, params);\n const sourceStartedAt = Date.now();\n const targetClient = getClientForChain({ chain: params.targetChain, provider: params.targetProvider });\n const targetBlockNumber = await getStartBlockNumber(targetClient);\n\n return {\n type: bridge.type,\n environment,\n fromAddress: params.fromAddress,\n toAddress: params.toAddress ?? params.fromAddress,\n amount: params.amount,\n amountDecimals: params.asset.decimals,\n symbol: params.asset.symbol,\n\n bridgeFee,\n\n sourceChain: params.sourceChain,\n sourceStartedAt,\n sourceTxHash: txHash,\n sourceConfirmationCount: 0,\n requiredSourceConfirmationCount,\n\n targetChain: params.targetChain,\n targetConfirmationCount: 0,\n requiredTargetConfirmationCount,\n\n startBlockNumber: targetBlockNumber,\n };\n}\n","export const ERC20_ABI = [\n {\n constant: true,\n inputs: [],\n name: 'name',\n outputs: [{ name: '', type: 'string' }],\n payable: false,\n stateMutability: 'view',\n type: 'function',\n },\n {\n constant: false,\n inputs: [\n { name: '_spender', type: 'address' },\n { name: '_value', type: 'uint256' },\n ],\n name: 'approve',\n outputs: [{ name: '', type: 'bool' }],\n payable: false,\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n constant: true,\n inputs: [],\n name: 'totalSupply',\n outputs: [{ name: '', type: 'uint256' }],\n payable: false,\n stateMutability: 'view',\n type: 'function',\n },\n {\n constant: false,\n inputs: [\n { name: '_from', type: 'address' },\n { name: '_to', type: 'address' },\n { name: '_value', type: 'uint256' },\n ],\n name: 'transferFrom',\n outputs: [{ name: '', type: 'bool' }],\n payable: false,\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n constant: true,\n inputs: [],\n name: 'decimals',\n outputs: [{ name: '', type: 'uint8' }],\n payable: false,\n stateMutability: 'view',\n type: 'function',\n },\n {\n constant: true,\n inputs: [{ name: '_owner', type: 'address' }],\n name: 'balanceOf',\n outputs: [{ name: 'balance', type: 'uint256' }],\n payable: false,\n stateMutability: 'view',\n type: 'function',\n },\n {\n constant: true,\n inputs: [],\n name: 'symbol',\n outputs: [{ name: '', type: 'string' }],\n payable: false,\n stateMutability: 'view',\n type: 'function',\n },\n {\n constant: false,\n inputs: [\n { name: '_to', type: 'address' },\n { name: '_value', type: 'uint256' },\n ],\n name: 'transfer',\n outputs: [{ name: '', type: 'bool' }],\n payable: false,\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n constant: true,\n inputs: [\n { name: '_owner', type: 'address' },\n { name: '_spender', type: 'address' },\n ],\n name: 'allowance',\n outputs: [{ name: '', type: 'uint256' }],\n payable: false,\n stateMutability: 'view',\n type: 'function',\n },\n { payable: true, stateMutability: 'payable', type: 'fallback' },\n {\n anonymous: false,\n inputs: [\n { indexed: true, name: 'owner', type: 'address' },\n { indexed: true, name: 'spender', type: 'address' },\n { indexed: false, name: 'value', type: 'uint256' },\n ],\n name: 'Approval',\n type: 'event',\n },\n {\n anonymous: false,\n inputs: [\n { indexed: true, name: 'from', type: 'address' },\n { indexed: true, name: 'to', type: 'address' },\n { indexed: false, name: 'value', type: 'uint256' },\n ],\n name: 'Transfer',\n type: 'event',\n },\n] as const;\n","import { BridgeInitializationError } from '../errors';\nimport { ErrorReason, type BridgeService } from '../types';\n\nexport async function ensureHasConfig(bridge: BridgeService) {\n if (!bridge.config) {\n await bridge.updateConfig();\n\n if (!bridge.config) {\n throw new BridgeInitializationError(ErrorReason.CONFIG_NOT_AVAILABLE);\n }\n }\n}\n","import { decodeEventLog, type Address } from 'viem';\nimport {\n ErrorReason,\n type BridgeConfig,\n type BridgeService,\n type BridgeTransfer,\n type TrackingParams,\n ErrorCode,\n} from '../../../types';\nimport { getClientForChain } from '../../../utils/client';\nimport { TOKEN_ROUTER_ABI } from '../abis/token-router';\nimport { getNetworkFeeEVM } from '../../../utils/network-fee';\nimport { retryPromise, type Done } from '../../../utils/retry-promise';\nimport { getTrackingDelayByChainId } from '../utils/config';\nimport { InvalidParamsError } from '../../../errors';\n\n// Maximum time (in ms) before the transaction is considered \"timed out\"\nexport const TRACKING_LIMIT_MS = 1000 * 60 * 60 * 3;\n// The max blocks that can be queried before receiving an error response\nexport const MAX_BLOCKS = 1024n;\n// The delay time before tracking starts\nexport const INITIAL_DELAY = 5000;\n\n/**\n * Mutates the `initial` transfer by merging it with the `updated` properties if they are not undefined\n * Invokes the `updateListener` with a copy of the updated `initial` transfer\n */\nconst updateTransfer = (\n initial: BridgeTransfer,\n updated: Partial<BridgeTransfer>,\n updateListener: TrackingParams['updateListener'],\n) => {\n Object.assign(initial, Object.fromEntries(Object.entries(updated).filter(([, value]) => value !== undefined)));\n updateListener({ ...initial });\n};\n\n/**\n * Polls the source network until it's able to get the CCTP message's `nonce` from the source transaction's logs\n * Updates the provided `BridgeTransfer` and broadcasts the changes via `updateListener`\n */\nexport const trackSourceTx = async (config: BridgeConfig, params: TrackingParams) => {\n const { sourceProvider, targetProvider, updateListener, bridgeTransfer } = params;\n const sourceClient = getClientForChain({ chain: bridgeTransfer.sourceChain, provider: sourceProvider });\n const sourceChainData = config.find((chainData) => chainData.chainId === bridgeTransfer.sourceChain.chainId);\n const targetClient = getClientForChain({ chain: bridgeTransfer.targetChain, provider: targetProvider });\n const targetChainData = config.find((chainData) => chainData.chainId === bridgeTransfer.targetChain.chainId);\n const updateableTransfer = { ...bridgeTransfer };\n\n if (!sourceChainData || !targetChainData) {\n throw new InvalidParamsError(ErrorReason.CHAIN_NOT_SUPPORTED);\n }\n\n const tracker = async (done: Done<BridgeTransfer>) => {\n /**\n * Return early if:\n * - transfer has already completed successfully or due to some error\n * - the transfer state already has the message's nonce\n */\n if (updateableTransfer.completedAt || updateableTransfer.metadata?.nonce) {\n return done(updateableTransfer);\n }\n\n /**\n * Check if the transaction has timed out\n */\n if (updateableTransfer.sourceStartedAt + TRACKING_LIMIT_MS <= Date.now()) {\n updateTransfer(updateableTransfer, { completedAt: Date.now(), errorCode: ErrorCode.TIMEOUT }, updateListener);\n return done(updateableTransfer);\n }\n\n /**\n * Get the transaction's receipt.\n * Throws if the transaction has't been processed by the network yet.\n */\n const txReceipt = await sourceClient.getTransactionReceipt({\n hash: updateableTransfer.sourceTxHash as Address,\n });\n\n /**\n * Calculate the network fee if needed.\n */\n if (!updateableTransfer.sourceNetworkFee) {\n const tx = await sourceClient.getTransaction({ hash: updateableTransfer.sourceTxHash as Address });\n const networkFee = getNetworkFeeEVM(tx, txReceipt);\n\n if (networkFee) {\n updateTransfer(updateableTransfer, { sourceNetworkFee: networkFee }, updateListener);\n }\n }\n\n /**\n * Update the state and terminate if the transaction was reverted\n */\n if (txReceipt.status === 'reverted') {\n updateTransfer(\n updateableTransfer,\n { completedAt: Date.now(), errorCode: ErrorCode.TRANSACTION_REVERTED },\n updateListener,\n );\n return done(updateableTransfer);\n }\n\n /**\n * Check the confirmation count.\n * - update the sourceConfirmationCount if it increased\n * - update the startBlockNumber if confirmation count increased but is not enough\n * - keeps polling until it's greater than requiredSourceConfirmationCount\n */\n const confirmationCount = await sourceClient.getTransactionConfirmations({\n hash: updateableTransfer.sourceTxHash as Address,\n });\n const hasMoreConfirmations = confirmationCount > updateableTransfer.sourceConfirmationCount;\n const hasRequiredConfirmations = confirmationCount >= updateableTransfer.requiredSourceConfirmationCount;\n\n if (hasMoreConfirmations) {\n const changes = {} as Partial<BridgeTransfer>;\n changes.sourceConfirmationCount = Number(confirmationCount);\n\n if (!hasRequiredConfirmations) {\n changes.startBlockNumber = await targetClient.getBlockNumber();\n }\n\n updateTransfer(updateableTransfer, changes, updateListener);\n }\n\n if (!hasRequiredConfirmations) {\n return;\n }\n\n if (!updateableTransfer.startBlockNumber) {\n updateTransfer(updateableTransfer, { startBlockNumber: await targetClient.getBlockNumber() }, updateListener);\n }\n\n /**\n * Get the `TransferTokens` event's log entry from the receipt\n */\n const transferEventLog = txReceipt.logs.find((log) => {\n if (log.address === sourceChainData.tokenRouterAddress) {\n const event = decodeEventLog({\n abi: TOKEN_ROUTER_ABI,\n ...log,\n });\n\n return event.eventName === 'TransferTokens';\n }\n\n return false;\n });\n\n if (!transferEventLog) {\n throw new InvalidParamsError(\n ErrorReason.INVALID_PARAMS,\n `unable to find a TransferTokens event in source transaction \"${updateableTransfer.sourceTxHash}\"`,\n );\n }\n\n /**\n * Get the nonce used by the message transmitter from the event's log\n * https://developers.circle.com/stablecoins/docs/evm-smart-contracts#receivemessage\n */\n const transferEvent = decodeEventLog({\n abi: TOKEN_ROUTER_ABI,\n eventName: 'TransferTokens',\n ...transferEventLog,\n });\n\n // save the nonce and broadcast\n const nonce = transferEvent.args.nonce;\n updateTransfer(updateableTransfer, { targetStartedAt: Date.now(), metadata: { nonce } }, updateListener);\n return done(updateableTransfer);\n };\n\n return retryPromise<BridgeTransfer>({\n promise: tracker,\n delay: getTrackingDelayByChainId(sourceChainData.chainId),\n startAfter: INITIAL_DELAY,\n });\n};\n\n/**\n * Polls the target network until it finds the transaction that matches the message's nonce\n * Updates the provided `BridgeTransfer` and broadcasts the changes via `updateListener`\n */\nexport const trackTargetTx = async (config: BridgeConfig, params: TrackingParams) => {\n const { targetProvider, updateListener, bridgeTransfer } = params;\n const updateableTransfer = { ...bridgeTransfer };\n\n if (!bridgeTransfer.completedAt && !bridgeTransfer.metadata?.nonce) {\n throw new InvalidParamsError(ErrorReason.INVALID_PARAMS, `nonce is missing`);\n }\n\n if (!bridgeTransfer.startBlockNumber) {\n throw new InvalidParamsError(ErrorReason.INVALID_PARAMS, `startBlockNumber is missing`);\n }\n\n const targetClient = getClientForChain({ chain: bridgeTransfer.targetChain, provider: targetProvider });\n const targetChainData = config.find((chainData) => chainData.chainId === bridgeTransfer.targetChain.chainId);\n\n if (!targetChainData) {\n throw new InvalidParamsError(\n ErrorReason.INVALID_PARAMS,\n `unknown target chain \"${bridgeTransfer.targetChain.chainId}\"`,\n );\n }\n\n const tracker = async (done: Done<BridgeTransfer>) => {\n /**\n * Return early if:\n * - transfer has already completed successfully or due to some error\n */\n if (updateableTransfer.completedAt) {\n return done(updateableTransfer);\n }\n\n /**\n * Check if `startBlockNumber` became falsy for whatever reason\n */\n if (!updateableTransfer.startBlockNumber) {\n updateTransfer(\n updateableTransfer,\n { completedAt: Date.now(), errorCode: ErrorCode.INVALID_PARAMS },\n updateListener,\n );\n return done(updateableTransfer);\n }\n\n /**\n * Check if the transaction has timed out\n */\n if (updateableTransfer.sourceStartedAt + TRACKING_LIMIT_MS <= Date.now()) {\n updateTransfer(updateableTransfer, { completedAt: Date.now(), errorCode: ErrorCode.TIMEOUT }, updateListener);\n return done(updateableTransfer);\n }\n\n if (!updateableTransfer.targetTxHash) {\n const lastBlockNumber = await targetClient.getBlockNumber();\n const lowestBlockNumber = updateableTransfer.startBlockNumber - MAX_BLOCKS;\n const fromBlock = lowestBlockNumber >= 0n ? lowestBlockNumber : 'earliest';\n const highestBlockNumber = updateableTransfer.startBlockNumber + MAX_BLOCKS;\n const toBlock = highestBlockNumber < lastBlockNumber ? highestBlockNumber : 'latest';\n\n const targetLogs = await targetClient.getLogs({\n address: targetChainData.messageTransmitterAddress,\n event: {\n name: 'MessageReceived',\n type: 'event',\n inputs: [\n { indexed: true, internalType: 'address', name: 'caller', type: 'address' },\n { indexed: false, internalType: 'uint32', name: 'sourceDomain', type: 'uint32' },\n { indexed: true, internalType: 'uint64', name: 'nonce', type: 'uint64' },\n { indexed: false, internalType: 'bytes32', name: 'sender', type: 'bytes32' },\n { indexed: false, internalType: 'bytes', name: 'messageBody', type: 'bytes' },\n ],\n },\n args: { nonce: updateableTransfer.metadata!.nonce as bigint },\n fromBlock,\n toBlock,\n });\n\n if (targetLogs[0]?.transactionHash) {\n updateTransfer(updateableTransfer, { targetTxHash: targetLogs[0].transactionHash }, updateListener);\n } else {\n updateTransfer(updateableTransfer, { startBlockNumber: lastBlockNumber }, updateListener);\n return;\n }\n }\n\n /**\n * Get the transaction's receipt.\n * Throws if the transaction has't been processed by the network yet.\n */\n const txReceipt = await targetClient.getTransactionReceipt({\n hash: updateableTransfer.targetTxHash as Address,\n });\n\n /**\n * Calculate the network fee if needed.\n */\n if (!updateableTransfer.targetNetworkFee) {\n const tx = await targetClient.getTransaction({ hash: updateableTransfer.targetTxHash as Address });\n const networkFee = getNetworkFeeEVM(tx, txReceipt);\n\n if (networkFee) {\n updateTransfer(updateableTransfer, { targetNetworkFee: networkFee }, updateListener);\n }\n }\n\n /**\n * Update the state and terminate if the transaction was reverted\n */\n if (txReceipt.status === 'reverted') {\n updateTransfer(\n updateableTransfer,\n { completedAt: Date.now(), errorCode: ErrorCode.TRANSACTION_REVERTED },\n updateListener,\n );\n return done(updateableTransfer);\n }\n\n /**\n * Check the confirmation count.\n * - update the targetConfirmationCount if it increased\n * - keeps polling until it's greater than requiredTargetConfirmationCount\n */\n const confirmationCount = await targetClient.getTransactionConfirmations({\n hash: updateableTransfer.targetTxHash as Address,\n });\n const hasMoreConfirmations = confirmationCount > updateableTransfer.targetConfirmationCount;\n const hasRequiredConfirmations = confirmationCount >= updateableTransfer.requiredTargetConfirmationCount;\n\n if (hasMoreConfirmations) {\n updateTransfer(updateableTransfer, { targetConfirmationCount: Number(confirmationCount) }, updateListener);\n }\n\n if (!hasRequiredConfirmations) {\n return;\n }\n\n updateTransfer(updateableTransfer, { completedAt: Date.now() }, updateListener);\n return done(updateableTransfer);\n };\n\n return retryPromise<BridgeTransfer>({\n promise: tracker,\n delay: getTrackingDelayByChainId(targetChainData.chainId),\n startAfter: INITIAL_DELAY,\n });\n};\n\nexport function trackTransfer(bridge: BridgeService, params: TrackingParams) {\n let abortFn: (() => void) | undefined;\n\n const cancel = () => {\n abortFn?.();\n };\n\n const executeTracking = async () => {\n await bridge.ensureHasConfig();\n\n const { sourceProvider, targetProvider, updateListener, bridgeTransfer } = params;\n\n const { result: sourceTracker, cancel: cancelSourceTracking } = await trackSourceTx(bridge.config!, {\n sourceProvider,\n targetProvider,\n updateListener,\n bridgeTransfer,\n });\n abortFn = cancelSourceTracking;\n const transferAfterSourceFinished = await sourceTracker;\n\n const { result: targetTracker, cancel: cancelTargetTracking } = await trackTargetTx(bridge.config!, {\n sourceProvider,\n targetProvider,\n updateListener,\n bridgeTransfer: transferAfterSourceFinished,\n });\n abortFn = cancelTargetTracking;\n return targetTracker;\n };\n\n return {\n result: executeTracking(),\n cancel,\n };\n}\n","import { type Transaction, type TransactionReceipt } from 'viem';\n\n// returns the network fee for EVM transaction in wei (10**-18)\nexport const getNetworkFeeEVM = (transaction: Transaction, receipt: TransactionReceipt) => {\n return transaction.gasPrice && BigInt(transaction.gasPrice * receipt.gasUsed);\n};\n","export const wait = async (time: number) =>\n new Promise((res) => {\n setTimeout(res, time);\n });\n","import { wait } from './wait';\n\nexport type Done<T> = (data: T) => void;\n\ntype Params<T> = {\n promise: (done: Done<T>) => Promise<unknown>;\n delay: number;\n startAfter?: number;\n};\n\nexport const retryPromise = <T>({ promise, delay, startAfter }: Params<T>) => {\n let isRunning = false;\n let isCancelled = false;\n let errorCount: number = 0;\n let resolve: ((data: T) => void) | undefined = undefined;\n let reject: ((reason?: string) => void) | undefined = undefined;\n\n const done = (data: T) => {\n if (resolve && isRunning) {\n isRunning = false;\n resolve(data);\n }\n };\n\n const cancel = () => {\n isCancelled = true;\n\n if (reject && isRunning) {\n isRunning = false;\n reject('cancelled');\n }\n };\n\n const result = new Promise<T>((res, rej) => {\n isRunning = true;\n resolve = res;\n reject = rej;\n\n const execute = async (): Promise<void> => {\n if (!isRunning || isCancelled) {\n return;\n }\n\n try {\n await promise(done);\n\n if (!isRunning || isCancelled) {\n return;\n }\n\n await wait(delay);\n } catch (err) {\n console.error((err as Error).message);\n errorCount += 1;\n await wait(2 ** errorCount * delay);\n }\n\n await execute();\n };\n\n if (startAfter) {\n setTimeout(execute, startAfter);\n } else {\n execute();\n }\n });\n\n return {\n result,\n cancel,\n };\n};\n","import { type BridgeServiceFactory, BridgeType } from '../../types/bridge';\nimport { getConfig } from './utils/config';\nimport { getAssets } from './handlers/get-assets';\nimport { getFees } from './handlers/get-fees';\nimport { transferAsset } from './handlers/transfer-asset';\nimport { ensureHasConfig } from '../../utils/ensure-config';\nimport { trackTransfer } from './handlers/track-transfer';\n\nexport const cctpBridgeFactory: BridgeServiceFactory = (environment) => {\n return {\n type: BridgeType.CCTP,\n config: null,\n updateConfig: async function () {\n this.config = await getConfig(environment);\n },\n ensureHasConfig: async function () {\n return ensureHasConfig(this);\n },\n getAssets: async function () {\n return getAssets(this);\n },\n getFees: async function (params) {\n return getFees(this, params);\n },\n transferAsset: async function (params) {\n return transferAsset(this, params, environment);\n },\n trackTransfer: function (params) {\n return trackTransfer(this, params);\n },\n };\n};\n","import { cctpBridgeFactory } from '../bridges/cctp/factory';\nimport { BridgeUnavailableError } from '../errors';\nimport type { BridgeAsset } from '../types/asset';\nimport { type BridgeService, BridgeType } from '../types/bridge';\nimport { Environment } from '../types/environment';\n\nexport const supportedBridges = new Map([[BridgeType.CCTP, cctpBridgeFactory]]);\n\nexport const getEnabledBridgeServices = (environment: Environment, disabledBridgeTypes?: BridgeType[]) => {\n return new Map(\n [...supportedBridges]\n .filter(([bridgeType]) => !disabledBridgeTypes?.includes(bridgeType))\n .map(([bridgeType, factory]) => [bridgeType, factory(environment)]),\n );\n};\n\nexport const getBridgeForTransfer = (\n enabledBridgeServices: Map<BridgeType, BridgeService>,\n asset: BridgeAsset,\n targetChainId: string,\n) => {\n const bridgeType = asset.destinations[targetChainId]?.find((bridgeType) => enabledBridgeServices.has(bridgeType));\n\n if (!bridgeType) {\n throw new BridgeUnavailableError();\n }\n\n return {\n type: bridgeType,\n bridge: enabledBridgeServices.get(bridgeType)!,\n };\n};\n","import type { FeeParams, TrackingParams, TransferParams } from './types/bridge';\nimport type { BridgeServiceConfig } from './types/config';\nimport { getBridgeForTransfer, getEnabledBridgeServices } from './utils';\nimport type { BridgeAsset, ChainAssetMap } from './types';\nimport { isArray, mergeWith } from 'lodash';\nimport { BridgeUnavailableError } from './errors';\n\nexport const createUnifiedBridgeService = ({ environment, disabledBridgeTypes }: BridgeServiceConfig) => {\n const enabledBridgeServices = getEnabledBridgeServices(environment, disabledBridgeTypes);\n\n const updateConfigs = async () => {\n await Promise.allSettled(\n Array.from(enabledBridgeServices).map(([, bridgeService]) => bridgeService.updateConfig()),\n );\n };\n\n const init = async () => {\n await updateConfigs();\n };\n\n const getAssets = async () => {\n const assets = await Promise.all(Array.from(enabledBridgeServices).map(([, bridge]) => bridge.getAssets()));\n return assets.reduce<ChainAssetMap>((aggregatedAssets, chainAssetMap) => {\n for (const [chainId, bridgeAssets] of Object.entries(chainAssetMap)) {\n const existingAssets = aggregatedAssets[chainId];\n\n if (existingAssets) {\n for (const bridgeAsset of bridgeAssets) {\n const index = existingAssets.findIndex(({ symbol }) => symbol === bridgeAsset.symbol);\n\n if (index === -1) {\n existingAssets.push(bridgeAsset);\n } else {\n mergeWith(existingAssets[index], bridgeAsset, (objValue, srcValue) => {\n if (isArray(objValue)) {\n return [...new Set(objValue.concat(srcValue))];\n }\n });\n }\n }\n } else {\n aggregatedAssets[chainId] = bridgeAssets;\n }\n }\n\n return aggregatedAssets;\n }, {});\n };\n\n const getFees = async (params: FeeParams) => {\n const { bridge } = getBridgeForTransfer(enabledBridgeServices, params.asset, params.targetChain.chainId);\n return bridge.getFees(params);\n };\n\n const transferAsset = async (params: TransferParams) => {\n const { bridge } = getBridgeForTransfer(enabledBridgeServices, params.asset, params.targetChain.chainId);\n return bridge.transferAsset(params);\n };\n\n const canTransferAsset = (asset: BridgeAsset, targetChainId: string) => {\n try {\n getBridgeForTransfer(enabledBridgeServices, asset, targetChainId);\n return true;\n } catch {\n return false;\n }\n };\n\n const trackTransfer = (params: TrackingParams) => {\n const bridge = enabledBridgeServices.get(params.bridgeTransfer.type);\n\n if (!bridge) {\n throw new BridgeUnavailableError();\n }\n\n return bridge.trackTransfer(params);\n };\n\n return {\n environment,\n bridges: enabledBridgeServices,\n init,\n updateConfigs,\n getAssets,\n getFees,\n canTransferAsset,\n transferAsset,\n trackTransfer,\n };\n};\n"]}