@avalabs/bridge-unified 0.0.0-hello-world-20230824162438 → 0.0.0-license-20240801163452

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ Copyright (C) 2021, Ava Labs, Inc. All rights reserved.
2
+
3
+ Subject to the limited license below (**”License””), you may not, and you may not permit anyone else to, copy, reproduce, aggregate, republish, download, post, distribute, license, sublicense, reverse engineer, modify, or create derivative works based on this software (collectively, **“Software”**).
4
+
5
+ You are hereby granted a limited, non-exclusive, non-sublicensable and non-transferable license to download and use the Software as-is solely (i) for use in connection with the Avalanche Public Blockchain platform, having a NetworkID of 1 (Mainnet) or 5 (Fuji), and associated blockchains, comprised exclusively of the Avalanche X-Chain, C-Chain, P-Chain and any subnets linked to the P-Chain (**“Avalanche Authorized Platform”**) or (ii) for non-production, testing or research purposes without any commercial application within the Avalanche ecosystem (**“Non-Commercial Use”**); provided that, in each case, you may not use or allow use of the Software (a) in connection with any forks of the Avalanche Authorized Platform, (b) in any manner not operationally connected to the Avalanche Authorized Platform other than for Non-Commercial Use, or (c) to the extent the number of monthly active users or the number of total installs of any software that uses the Software across all versions thereof exceeds 10,000 at any time. You may not modify or alter the Software in any way.
6
+
7
+ You hereby acknowledge and agree to the terms set forth at www.avalabs.org/important-notice.
8
+
9
+ **TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED ON AN “AS IS” BASIS, AND AVA LABS EXPRESSLY DISCLAIMS AND EXCLUDES ALL REPRESENTATIONS, WARRANTIES AND OTHER TERMS AND CONDITIONS, WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION BY OPERATION OF LAW OR BY CUSTOM, STATUTE OR OTHERWISE, AND INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTY, TERM, OR CONDITION OF NON-INFRINGEMENT, MERCHANTABILITY, TITLE, OR FITNESS FOR PARTICULAR PURPOSE. YOU USE THE SOFTWARE AT YOUR OWN RISK. AVA LABS EXPRESSLY DISCLAIMS ALL LIABILITY (INCLUDING FOR ALL DIRECT, CONSEQUENTIAL OR OTHER DAMAGES OR LOSSES) RELATED TO ANY USE OF THE SOFTWARE.**
package/README.md CHANGED
@@ -16,11 +16,11 @@ The bridging ecosystem is complex. There are often multiple tools that can be us
16
16
 
17
17
  These are the bridges we currently support:
18
18
 
19
- - **Avalanche Bridge** - is capable of transferring a fixed list of tokens between Ethereum and Avalanche C-Chain. See the `@avalabs/bridge-avalanche` package.
20
- - **CCTP** - preferred for brdiging USDC between Ethereum and Avalanche C-Chain. See the `@avalabs/bridge-cctp` package.
19
+ - **CCTP** - preferred for brdiging USDC between Ethereum and Avalanche C-Chain. See the `bridges/cctp` folder.
21
20
 
22
21
  Future bridges we plan to support:
23
22
 
23
+ - **Avalanche Bridge** - is capable of transferring a fixed list of tokens between Ethereum and Avalanche C-Chain.
24
24
  - **Teleporter** - for moving tokens between subnets.
25
25
  - **Cross-Chain Transfer** - for moving tokens between the three Avalanche Primary Network chains (X-Chain, C-Chain, and P-Chain).
26
26
 
@@ -34,6 +34,141 @@ Future bridges we plan to support:
34
34
  pnpm add @avalabs/bridge-unified
35
35
  ```
36
36
 
37
- ## How it works
37
+ ## Usage
38
38
 
39
- TODO: Explain details of this api.
39
+ ```js
40
+ import { createUnifiedBridgeService, getEnabledBridgeServices, Environment, BridgeTransfer } from '@avalabs/bridge-unified';
41
+
42
+ const environment = Environment.TEST;
43
+ // use all available bridges
44
+ const disabledBridgeTypes = []
45
+
46
+ // fetch all available bridge services
47
+ const enabledBridgeServices = await getEnabledBridgeServices(environment, disabledBridgeTypes);
48
+
49
+ // create a new service for a given environment and list of bridge services
50
+ const unifiedService = createUnifiedBridgeService({
51
+ environment,
52
+ enabledBridgeServices
53
+ });
54
+
55
+ // get the list of supported assets, grouped by caip2 (https://chainagnostic.org/CAIPs/caip-2) chain IDs
56
+ const assets = await unifiedService.getAssets()
57
+
58
+ // get the bridge fee(s) of the provided transfer
59
+ const fees = await unifiedService.getFees({...})
60
+
61
+ // start a new bridge transfer and store its state
62
+ const bridgeTransfer = await unifiedService.transferAsset({...})
63
+
64
+ // create an update listener for tracking
65
+ const updateListener = (transfer: BridgeTransfer) => {
66
+ console.log(transfer)
67
+ }
68
+
69
+ // start tracking the transfer's state. whenever the state changes, it will call the provided `updateListener`
70
+ const { cancel, result } = await unifiedService.trackTransfer({bridgeTransfer, updateListener, ...})
71
+
72
+ // immediatelly stops tracking and rejects the tracker's promise
73
+ // cancel()
74
+
75
+ // wait for the transfer to finish and get its final state
76
+ const finalizedBridgeTransfer = await result
77
+ ```
78
+
79
+ ## API
80
+
81
+ ### getEnabledBridgeServices(environment, disabledBridgeTypes);
82
+
83
+ Type: `(environment: Environment, disabledBridgeTypes: BridgeType[]) => Promise<BridgeServicesMap>`
84
+
85
+ Returns all available bridge services for a given environment (excluding disabledBridgeTypes). Any bridge service which fails to initialize will be absent from this returned value.
86
+
87
+ #### environment
88
+
89
+ Type: `Environment`
90
+
91
+ Defines if the bridge service should use `testnet` or `mainnet`.
92
+
93
+ #### disabledBridgeTypes
94
+
95
+ Type: `BridgeType[]`
96
+
97
+ Disables the integration of the provided `BridgeType`s.
98
+
99
+ #### enabledBridgeServices
100
+
101
+ Type: `BridgeServicesMap` => `Map<BridgeType, BridgeService>`
102
+
103
+ This includes all the bridge services which were initialized successfully, to pass to `createUnifiedBridgeService`.
104
+
105
+ ### createUnifiedBridgeService({ environment, enabledBridgeServices })
106
+
107
+ Returns a new `unifiedBridgeService` for the given `environment` and `enabledBridgeServices` map.
108
+
109
+ ### unifiedBridgeService
110
+
111
+ Contains all the required properties and methods to prepare, initiate or track a bridge transfer.
112
+ Automatically picks the right (enabled) bridge integration to use based on the provided params.
113
+
114
+ ```js
115
+ {
116
+ environment, // the provided Environment during initialization
117
+ getAssets,
118
+ getFees,
119
+ estimateGas,
120
+ canTransferAsset,
121
+ transferAsset,
122
+ trackTransfer,
123
+ }
124
+ ```
125
+
126
+ #### getAssets
127
+
128
+ Type: `() => Promise<ChainAssetMap>`
129
+
130
+ Returns the aggregated list of assets supported by the enabled bridges grouped by [caip2](https://chainagnostic.org/CAIPs/caip-2) chain IDs.
131
+
132
+ #### getFees
133
+
134
+ Type: `(params: FeeParams) => Promise<AssetFeeMap>`
135
+
136
+ Calculates and returns the bridge fees in `tokenAddress` - `amount` pairs for a given bridge transfer.
137
+
138
+ #### estimateGas
139
+
140
+ Type: `(params: TransferParams) => Promise<bigint>`
141
+
142
+ Estimates the gas cost of a specific transfer.
143
+
144
+ #### canTransferAsset
145
+
146
+ Type: `(asset: BridgeAsset, targetChainId: string) => boolean`
147
+
148
+ Indicates whether the unified bridge supports transferring a specific asset to a specific target chain.
149
+
150
+ #### transferAsset
151
+
152
+ Type: `(params: TransferParams) => Promise<BridgeTransfer>`
153
+
154
+ Starts a new bridge transfer, executing every required step in a single call.
155
+ 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.
156
+ Returns a `BridgeTransfer` containing all the (known) initial values such as: environment, addresses, amount, fee, transaction hash, required and actual block confirmation counts, etc.
157
+
158
+ #### trackTransfer
159
+
160
+ Type: `(params: TrackingParams) => ({cancel, result})`
161
+
162
+ Tracks the given `BridgeTransfer`'s progress and invokes the provided listener callback whenever a change happens.
163
+
164
+ ###### cancel
165
+
166
+ Type: `() => void`
167
+
168
+ If it's still pending, rejects the tracker's promise (`result`) immediatelly and breaks its loop under the hood.
169
+
170
+ ###### result
171
+
172
+ Type: `Promise<BridgeTransfer>`
173
+
174
+ Resolves with the finalized `BridgeTransfer` (if not canceled before).
package/dist/index.cjs CHANGED
@@ -1,7 +1,18 @@
1
1
  'use strict';
2
2
 
3
- var o=class extends Error{constructor(s,a){super(s);this.code=a;this.code=a;}},e=class extends o{constructor(t="Not implemented"){super(t,5001),this.name="NotImplementedError";}};var n=async r=>{throw new e};var i=r=>{throw new e};var m=async({address:r,chainIds:t})=>{throw new e};var O=r=>({planBridgeJourney:i,executeBridgeJourneyStep:n,checkForPendingBridgeJourney:m});
3
+ var viem = require('viem');
4
+ var lodash = require('lodash');
4
5
 
5
- exports.createUnifiedBridgeService = O;
6
+ var H=(r=>(r.NATIVE="native",r.ERC20="erc20",r))(H||{});var E=(e=>(e.CCTP="cctp",e))(E||{}),G=(r=>(r.AllowanceApproval="allowance-approval",r.TokensTransfer="tokens-transfer",r))(G||{});var K=(r=>(r.PROD="production",r.TEST="test",r))(K||{});var B=(t=>(t[t.BRIDGE_NOT_AVAILABLE=5001]="BRIDGE_NOT_AVAILABLE",t[t.INITIALIZATION_FAILED=5002]="INITIALIZATION_FAILED",t[t.INVALID_PARAMS=5003]="INVALID_PARAMS",t[t.TIMEOUT=5004]="TIMEOUT",t[t.TRANSACTION_REVERTED=5005]="TRANSACTION_REVERTED",t))(B||{}),w=(a=>(a.UNKNOWN="UNKNOWN",a.CONFIG_NOT_AVAILABLE="CONFIG_NOT_AVAILABLE",a.INVALID_PARAMS="INVALID_PARAMS",a.IDENTICAL_CHAINS_PROVIDED="IDENTICAL_CHAINS_PROVIDED",a.INCORRECT_AMOUNT_PROVIDED="INCORRECT_AMOUNT_PROVIDED",a.INCORRECT_ADDRESS_PROVIDED="INCORRECT_ADDRESS_PROVIDED",a.CHAIN_NOT_SUPPORTED="CHAIN_NOT_SUPPORTED",a.ASSET_NOT_SUPPORTED="ASSET_NOT_SUPPORTED",a.CONFIRMATION_COUNT_UNKNOWN="CONFIRMATION_COUNT_UNKNOWN",a))(w||{});async function $(n){let e=n.map(r=>r.chainId);return n.reduce((r,s)=>(r[s.chainId]=s.tokens.map(i=>({...i,type:"erc20",destinations:e.reduce((t,o)=>(s.chainId!==o&&(t[o]||(t[o]=[]),t[o]?.push("cctp")),t),{})})),r),{})}var ue="^[-a-z0-9]{3,8}$",de="^[-_a-zA-Z0-9]{1,50}$",q=":",me=n=>{let[e,r]=n.split(q);if(!e||!r)throw new Error("Invalid identifier provided.");if(!new RegExp(ue).test(e))throw new Error("Invalid namespace provided.");if(!new RegExp(de).test(r))throw new Error("Invalid reference provided.");return {namespace:e,reference:r}},ce=({namespace:n,reference:e})=>`${n}${q}${e}`,M={toJSON:me,toString:ce};var ge=n=>{let{reference:e}=M.toJSON(n.chainId);return {id:Number(e),name:n.chainName,nativeCurrency:{decimals:n.networkToken.decimals,symbol:n.networkToken.symbol,name:n.networkToken.name},network:n.chainName,rpcUrls:{default:{http:[n.rpcUrl]},public:{http:[n.rpcUrl]}},...n.utilityAddresses?.multicall&&{contracts:{multicall3:{address:n.utilityAddresses.multicall}}}}},b=({chain:n,provider:e})=>{let r=ge(n),s=e?viem.custom(e):viem.http(n.rpcUrl,{batch:!0,retryCount:0});return viem.createWalletClient({chain:r,transport:s}).extend(viem.publicActions)};var v=[{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 x=class extends Error{constructor(r,s,i){super(r);this.code=s;this.details=i;}};var k=class extends x{constructor(e="UNKNOWN",r){super(e,5001,r),this.name="BridgeUnavailableError";}};var S=class extends x{constructor(e="UNKNOWN",r){super(e,5002,r),this.name="BridgeInitializationError";}};var T=class extends x{constructor(e="INVALID_PARAMS",r){super(e,5003,r),this.name="InvalidParamsError";}};var R=({sourceChain:n,targetChain:e,amount:r,asset:s},i)=>{if(n.chainId===e.chainId)throw new T("IDENTICAL_CHAINS_PROVIDED");if(r<=0n)throw new T("INCORRECT_AMOUNT_PROVIDED","Amount must be greater than zero");let t=i.find(a=>a.chainId===n.chainId);if(!t)throw new T("CHAIN_NOT_SUPPORTED",`Not supported on source chain "${n.chainId}"`);let o=i.find(a=>a.chainId===e.chainId);if(!o)throw new T("CHAIN_NOT_SUPPORTED",`Not supported on target chain "${e.chainId}"`);let d=t.tokens.find(a=>a.symbol===s.symbol),u=o.tokens.find(a=>a.symbol===s.symbol);if(!d||!u)throw new T("ASSET_NOT_SUPPORTED");return {sourceChainData:t,targetChainData:o,burnToken:d,mintToken:u}};async function F(n,e){let{sourceChain:r,targetChain:s,asset:i,amount:t,provider:o}=e,{sourceChainData:d,targetChainData:u,burnToken:a}=R({sourceChain:r,targetChain:s,asset:i,amount:t},n),m=await b({chain:r,provider:o}).readContract({address:d.tokenRouterAddress,abi:v,functionName:"calculateFee",args:[t,u.domain]});return {[a.address]:m}}var N=[{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"}];function j({amount:n,burnToken:e,targetChainData:r,toAddress:s}){return viem.encodeFunctionData({abi:v,functionName:"transferTokens",args:[n,r.domain,s,e.address]})}function X({amount:n,sourceChainData:e}){return viem.encodeFunctionData({abi:N,functionName:"approve",args:[e.tokenRouterAddress,n]})}var Ae=async(n,e)=>{let{sourceChain:r,targetChain:s,asset:i,amount:t,fromAddress:o,toAddress:d,sourceProvider:u,onStepChange:a,sign:p}=e,m=d??o;if(!viem.isAddress(o)||!viem.isAddress(m))throw new T("INCORRECT_ADDRESS_PROVIDED");let{sourceChainData:c,targetChainData:y,burnToken:l}=R({sourceChain:r,targetChain:s,asset:i,amount:t},n),f=b({chain:r,provider:u}),C=await f.readContract({address:l.address,abi:N,functionName:"allowance",args:[o,c.tokenRouterAddress]})<t,_=C?2:1;if(C)if(a?.({currentSignature:1,currentSignatureReason:"allowance-approval",requiredSignatures:_}),p){let g=X({amount:t,sourceChainData:c}),I=await p({from:o,to:l.address,data:g},pe=>f.sendRawTransaction({serializedTransaction:pe}));await f.waitForTransactionReceipt({hash:I,pollingInterval:1e3});}else {let{request:g}=await f.simulateContract({account:o,address:l.address,abi:N,functionName:"approve",args:[c.tokenRouterAddress,t]}),I=await f.writeContract(g);await f.waitForTransactionReceipt({hash:I,pollingInterval:1e3});}if(a?.({currentSignature:C?2:1,currentSignatureReason:"tokens-transfer",requiredSignatures:_}),p){let g=j({amount:t,burnToken:l,targetChainData:y,toAddress:m});return p({from:o,to:c.tokenRouterAddress,data:g},I=>f.sendRawTransaction({serializedTransaction:I}))}let{request:P}=await f.simulateContract({account:o,address:c.tokenRouterAddress,abi:v,functionName:"transferTokens",args:[t,y.domain,m,l.address]});return f.writeContract(P)},Ce=async n=>{try{return await n.getBlockNumber()}catch{return}};async function J(n,e,r){let{minimumConfirmations:s}=n.find(m=>m.chainId===e.sourceChain.chainId)??{},{minimumConfirmations:i}=n.find(m=>m.chainId===e.targetChain.chainId)??{};if(!s||!i)throw new T("CONFIRMATION_COUNT_UNKNOWN");let t=await F(n,{...e,provider:e.sourceProvider}),o=(e.asset.address&&t[e.asset.address])??0n,d=await Ae(n,e),u=Date.now(),a=b({chain:e.targetChain,provider:e.targetProvider}),p=await Ce(a);return {type:"cctp",environment:r,fromAddress:e.fromAddress,toAddress:e.toAddress??e.fromAddress,amount:e.amount,amountDecimals:e.asset.decimals,symbol:e.asset.symbol,bridgeFee:o,sourceChain:e.sourceChain,sourceStartedAt:u,sourceTxHash:d,sourceConfirmationCount:0,requiredSourceConfirmationCount:s,targetChain:e.targetChain,targetConfirmationCount:0,requiredTargetConfirmationCount:i,startBlockNumber:p}}var O=(n,e)=>n.gasPrice&&BigInt(n.gasPrice*e.gasUsed);var L=async n=>new Promise(e=>{setTimeout(e,n);});var U=({promise:n,delay:e,startAfter:r})=>{let s=!1,i=!1,t=0,o,d,u=m=>{o&&s&&(s=!1,o(m));},a=()=>{i=!0,d&&s&&(s=!1,d("cancelled"));};return {result:new Promise((m,c)=>{s=!0,o=m,d=c;let y=async()=>{if(!(!s||i)){try{if(await n(u),!s||i)return;await L(e);}catch(l){console.error(l.message),t+=1,await L(2**t*e);}await y();}};r?setTimeout(y,r):y();}),cancel:a}};var be={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"},Z=async n=>{try{return (await(await fetch(be[n])).json()).map(s=>({...s,chainId:`eip155:${s.chainId}`}))}catch(e){throw new S("CONFIG_NOT_AVAILABLE",`Error while fetching CCTP config: ${e.message}`)}},V=n=>{switch(n){case"eip155:43114":case"eip155:43113":return 1e3;default:return 2e4}};var ee=1e3*60*60*3,Q=1024n,te=5e3,A=(n,e,r)=>{Object.assign(n,Object.fromEntries(Object.entries(e).filter(([,s])=>s!==void 0))),r({...n});},he=async(n,e)=>{let{sourceProvider:r,targetProvider:s,updateListener:i,bridgeTransfer:t}=e,o=b({chain:t.sourceChain,provider:r}),d=n.find(c=>c.chainId===t.sourceChain.chainId),u=b({chain:t.targetChain,provider:s}),a=n.find(c=>c.chainId===t.targetChain.chainId),p={...t};if(!d||!a)throw new T("CHAIN_NOT_SUPPORTED");return U({promise:async c=>{if(p.completedAt||p.metadata?.nonce)return c(p);if(p.sourceStartedAt+ee<=Date.now())return A(p,{completedAt:Date.now(),errorCode:5004},i),c(p);let y=await o.getTransactionReceipt({hash:p.sourceTxHash});if(!p.sourceNetworkFee){let g=await o.getTransaction({hash:p.sourceTxHash}),I=O(g,y);I&&A(p,{sourceNetworkFee:I},i);}if(y.status==="reverted")return A(p,{completedAt:Date.now(),errorCode:5005},i),c(p);let l=await o.getTransactionConfirmations({hash:p.sourceTxHash}),f=l>p.sourceConfirmationCount,h=l>=p.requiredSourceConfirmationCount;if(f){let g={};g.sourceConfirmationCount=Number(l),h||(g.startBlockNumber=await u.getBlockNumber()),A(p,g,i);}if(!h)return;p.startBlockNumber||A(p,{startBlockNumber:await u.getBlockNumber()},i);let C=y.logs.find(g=>g.address.toLowerCase()===d.tokenRouterAddress.toLowerCase()?viem.decodeEventLog({abi:v,...g}).eventName==="TransferTokens":!1);if(!C)throw new T("INVALID_PARAMS",`unable to find a TransferTokens event in source transaction "${p.sourceTxHash}"`);let P=viem.decodeEventLog({abi:v,eventName:"TransferTokens",...C}).args.nonce;return A(p,{targetStartedAt:Date.now(),metadata:{nonce:P}},i),c(p)},delay:V(d.chainId),startAfter:te})},Ie=async(n,e)=>{let{targetProvider:r,updateListener:s,bridgeTransfer:i}=e,t={...i};if(!i.completedAt&&!i.metadata?.nonce)throw new T("INVALID_PARAMS","nonce is missing");if(!i.startBlockNumber)throw new T("INVALID_PARAMS","startBlockNumber is missing");let o=b({chain:i.targetChain,provider:r}),d=n.find(a=>a.chainId===i.targetChain.chainId);if(!d)throw new T("INVALID_PARAMS",`unknown target chain "${i.targetChain.chainId}"`);return U({promise:async a=>{if(t.completedAt)return a(t);if(!t.startBlockNumber)return A(t,{completedAt:Date.now(),errorCode:5003},s),a(t);if(t.sourceStartedAt+ee<=Date.now())return A(t,{completedAt:Date.now(),errorCode:5004},s),a(t);if(!t.targetTxHash){let l=await o.getBlockNumber(),f=t.startBlockNumber-Q,h=f>=0n?f:"earliest",C=t.startBlockNumber+Q,_=C<l?C:"latest",P=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:t.metadata?.nonce},fromBlock:h,toBlock:_});if(P[0]?.transactionHash)A(t,{targetTxHash:P[0].transactionHash},s);else {A(t,{startBlockNumber:l},s);return}}let p=await o.getTransactionReceipt({hash:t.targetTxHash});if(!t.targetNetworkFee){let l=await o.getTransaction({hash:t.targetTxHash}),f=O(l,p);f&&A(t,{targetNetworkFee:f},s);}if(p.status==="reverted")return A(t,{completedAt:Date.now(),errorCode:5005},s),a(t);let m=await o.getTransactionConfirmations({hash:t.targetTxHash}),c=m>t.targetConfirmationCount,y=m>=t.requiredTargetConfirmationCount;if(c&&A(t,{targetConfirmationCount:Number(m)},s),!!y)return A(t,{completedAt:Date.now()},s),a(t)},delay:V(d.chainId),startAfter:te})};function ne(n,e){let r,s=()=>{r?.();};return {result:(async()=>{let{sourceProvider:t,targetProvider:o,updateListener:d,bridgeTransfer:u}=e,{result:a,cancel:p}=await he(n,{sourceProvider:t,targetProvider:o,updateListener:d,bridgeTransfer:u});r=p;let m=await a,{result:c,cancel:y}=await Ie(n,{sourceProvider:t,targetProvider:o,updateListener:d,bridgeTransfer:m});return r=y,c})(),cancel:s}}var we=60000n,ae=175000n,ve=60000n,se=215000n;async function ie(n,e){let{sourceChain:r,targetChain:s,asset:i,amount:t,fromAddress:o,toAddress:d,sourceProvider:u}=e,a=d??o;if(!viem.isAddress(o)||!viem.isAddress(a))throw new T("INCORRECT_ADDRESS_PROVIDED");let{sourceChainData:p,burnToken:m}=R({sourceChain:r,targetChain:s,asset:i,amount:t},n),y=await b({chain:r,provider:u}).readContract({address:m.address,abi:N,functionName:"allowance",args:[o,p.tokenRouterAddress]}),l=p.domain===1;return y>=t?l?se:ae:l?ve+se:we+ae}var oe=async n=>{let e=await Z(n);return {type:"cctp",estimateGas:r=>ie(e,r),getAssets:()=>$(e),getFees:r=>F(e,r),transferAsset:r=>J(e,r,n),trackTransfer:r=>ne(e,r)}};var Ne=new Map([["cctp",oe]]),Pe=async(n,e)=>{let r=[...Ne].filter(([i])=>!e.includes(i)),s=await Promise.allSettled(r.map(async([i,t])=>[i,await t(n)]));return new Map(lodash.compact(s.map(i=>i.status==="fulfilled"?i.value:void 0)))},D=(n,e,r)=>{let s=e.destinations[r];for(let i of s??[]){let t=n.get(i);if(t)return {bridge:t,type:i}}throw new k};var _n=({environment:n,enabledBridgeServices:e})=>({environment:n,getAssets:async()=>(await Promise.all(Array.from(e).map(([,a])=>a.getAssets()))).reduce((a,p)=>{for(let[m,c]of Object.entries(p)){let y=a[m];if(y)for(let l of c){let f=y.findIndex(({symbol:h})=>h===l.symbol);f===-1?y.push(l):lodash.mergeWith(y[f],l,(h,C)=>{if(lodash.isArray(h))return [...new Set(h.concat(C))]});}else a[m]=c;}return a},{}),getFees:async u=>{let{bridge:a}=D(e,u.asset,u.targetChain.chainId);return a.getFees(u)},estimateGas:async u=>{let{bridge:a}=D(e,u.asset,u.targetChain.chainId);return a.estimateGas(u)},canTransferAsset:(u,a)=>{try{return D(e,u,a),!0}catch{return !1}},transferAsset:async u=>{let{bridge:a}=D(e,u.asset,u.targetChain.chainId);return a.transferAsset(u)},trackTransfer:u=>{let a=e.get(u.bridgeTransfer.type);if(!a)throw new k;return a.trackTransfer(u)}});
7
+
8
+ exports.BridgeSignatureReason = G;
9
+ exports.BridgeType = E;
10
+ exports.Environment = K;
11
+ exports.ErrorCode = B;
12
+ exports.ErrorReason = w;
13
+ exports.TokenType = H;
14
+ exports.caip2 = M;
15
+ exports.createUnifiedBridgeService = _n;
16
+ exports.getEnabledBridgeServices = Pe;
6
17
  //# sourceMappingURL=out.js.map
7
18
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors/index.ts","../src/handlers/execute-bridge-journey-step.ts","../../../packages-internal/bridge-shared/src/constants/constants.ts","../src/handlers/plan-bridge-journey.ts","../src/handlers/check-for-pending-bridge-journey.ts","../src/unified-bridge-service.ts"],"names":["BridgeError","message","code","NotImplementedError","executeBridgeJourneyStep","_params","ETHEREUM_INFO","planBridgeJourney","checkForPendingBridgeJourney","_address","_chainIds","createUnifiedBridgeService","_options"],"mappings":"AAIA,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,ECZO,IAAMG,EAA2B,MAAOC,GAA4C,CAWzF,MAAM,IAAIF,CACZ,ECjBO,IAAMG,EAAgB,CAC3B,aACA,WAAY,IACZ,sBAAuB,GACvB,OAAQ,+DACV,ECcO,IAAMC,EAAqBF,GAA4D,CAE5F,MAAM,IAAIF,CACZ,ECjBO,IAAMK,EAA+B,MAAO,CACjD,QAASC,EACT,SAAUC,CACZ,IAGM,CAKJ,MAAM,IAAIP,CACZ,ECPO,IAAMQ,EAA8BC,IAClC,CACL,kBAAAL,EACA,yBAAAH,EACA,6BAAAI,CACF","sourcesContent":["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';\n\ntype ExecuteBridgeJourneyStepParams = {\n stepIndex: number;\n journey: unknown;\n};\n\nexport const executeBridgeJourneyStep = async (_params: ExecuteBridgeJourneyStepParams) => {\n /**\n * 1. Validate the journey\n * 3. Forward request along to the right bridge platform's package.\n * 4. Return an observable that emits events when:\n * - User signs the transaction (returns the fromChain txId)\n * - Every block confirmation on fromChain\n * - fromChain tx completed, starting the toChain tx (returns the toChainTxId)\n * - Every block confirmation on toChain\n * - toChain tx completed\n */\n throw new NotImplementedError();\n};\n","import { ChainVm, type EvmChain } from '../types/chain';\n\nexport const ETHEREUM_INFO = {\n vmType: ChainVm.EthereumVM,\n evmChainId: '1',\n confirmationThreshold: 96,\n rpcUrl: 'https://mainnet.infura.io/v3/3d8a7c0b1b5a4b0e8b0b3b0f2b0b0b0b',\n} as const satisfies EvmChain;\n","import { NotImplementedError } from '../errors';\nimport { BridgePlatform, type 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 a list of transaction steps needed to complete a bridge from chain A to B.\n * The response may include multiple steps if the bridge requires multiple hops.\n */\nexport const planBridgeJourney = (_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","import type { Address } from 'viem';\nimport { NotImplementedError } from '../errors';\n\n/**\n * Checks for any currently pending bridge transactions. Useful for dApps that want\n * to display the current tx's status after a page refresh.\n */\nexport const checkForPendingBridgeJourney = async ({\n address: _address,\n chainIds: _chainIds,\n}: {\n address: Address;\n chainIds: string[];\n}) => {\n /**\n * 1. If wallet is Core, request current bridge journey. Otherwise, check glacier to see if the provided wallet has bridge tx in the past 100 transactions on the provided chains.\n * 3. Returns an array of txIds for all pending transactions\n */\n throw new NotImplementedError();\n};\n","import { executeBridgeJourneyStep } from './handlers/execute-bridge-journey-step';\nimport { planBridgeJourney } from './handlers/plan-bridge-journey';\n\nimport type { Environment, MaybePromise, NativeToken } from '@internal/bridge-shared';\nimport { checkForPendingBridgeJourney } from './handlers/check-for-pending-bridge-journey';\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 createUnifiedBridgeService = (_options: BridgeServiceConfig) => {\n return {\n planBridgeJourney,\n executeBridgeJourneyStep,\n checkForPendingBridgeJourney,\n };\n};\n"]}
1
+ {"version":3,"sources":["../src/types/asset.ts","../src/types/bridge.ts","../src/types/environment.ts","../src/types/error.ts","../src/bridges/cctp/handlers/get-assets.ts","../src/utils/client.ts","../src/utils/caip2.ts","../src/bridges/cctp/abis/token-router.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/transfer-data.ts","../src/bridges/cctp/handlers/get-fees.ts","../src/bridges/cctp/handlers/transfer-asset.ts","../src/bridges/cctp/abis/erc20.ts","../src/bridges/cctp/utils/build-tx.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/utils/config.ts","../src/bridges/cctp/handlers/estimate-gas.ts","../src/bridges/cctp/factory.ts","../src/utils/bridge-types.ts","../src/unified-bridge-service.ts"],"names":["TokenType","BridgeType","BridgeSignatureReason","Environment","ErrorCode","ErrorReason","getAssets","config","chainIds","chainData","assets","asset","destinations","chainId","createWalletClient","publicActions","custom","http","namespacePattern","referencePattern","delimeter","toJSON","identifier","namespace","reference","toString","caip2_default","_getChain","chain","getClientForChain","provider","chainInfo","transport","TOKEN_ROUTER_ABI","BridgeError","message","code","details","BridgeUnavailableError","BridgeInitializationError","InvalidParamsError","getTransferData","sourceChain","targetChain","amount","sourceChainData","targetChainData","burnToken","token","mintToken","getFees","params","feeAmount","isAddress","ERC20_ABI","encodeFunctionData","buildTransferTxData","toAddress","buildApprovalTxData","approveAndTransfer","fromAddress","maybeToAddress","sourceProvider","onStepChange","sign","client","isAllowanceApprovalRequired","requiredSignatures","data","txHash","signedTxHash","request","getStartBlockNumber","targetClient","transferAsset","environment","requiredSourceConfirmationCount","requiredTargetConfirmationCount","fees","bridgeFee","sourceStartedAt","targetBlockNumber","decodeEventLog","getNetworkFeeEVM","transaction","receipt","wait","time","res","retryPromise","promise","delay","startAfter","isRunning","isCancelled","errorCount","resolve","reject","done","cancel","rej","execute","err","CONFIG_URLS","getConfig","getTrackingDelayByChainId","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","ETH_APPROVAL_TX_GAS_ESTIMATE","ETH_TRANSFER_TX_GAS_ESTIMATE","AVAX_APPROVAL_TX_GAS_ESTIMATE","AVAX_TRANSFER_TX_GAS_ESTIMATE","estimateGas","allowance","isOffboarding","cctpBridgeFactory","compact","supportedBridges","getEnabledBridgeServices","disabledBridgeTypes","filteredBridges","bridgeType","bridgePromisesResults","factory","result","getBridgeForTransfer","enabledBridgeServices","targetChainId","bridge","isArray","mergeWith","createUnifiedBridgeService","aggregatedAssets","chainAssetMap","bridgeAssets","existingAssets","bridgeAsset","index","symbol","objValue","srcValue"],"mappings":"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,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,UAC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","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 { 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 estimateGas: (params: TransferParams) => Promise<bigint>;\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) => Promise<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 { TokenType, type ChainAssetMap, type DestinationInfo, BridgeType } from '../../../types';\nimport type { Config } from '../types/config';\n\nexport async function getAssets(config: Config) {\n const chainIds = config.map((chainData) => chainData.chainId);\n\n return 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 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 { 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, FeeParams } from '../../../types';\nimport { getClientForChain } from '../../../utils/client';\nimport { TOKEN_ROUTER_ABI } from '../abis/token-router';\nimport type { Config } from '../types/config';\nimport { getTransferData } from '../utils/transfer-data';\n\nexport async function getFees(config: Config, params: FeeParams) {\n const { sourceChain, targetChain, asset, amount, provider } = params;\n const { sourceChainData, targetChainData, burnToken } = getTransferData(\n { sourceChain, targetChain, asset, amount },\n 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 { isAddress, type PublicClient } from 'viem';\nimport {\n ErrorReason,\n BridgeType,\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';\nimport { buildApprovalTxData, buildTransferTxData } from '../utils/build-tx';\nimport type { Config } from '../types/config';\nimport { getFees } from './get-fees';\n\nconst approveAndTransfer = async (config: Config, 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 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 = buildApprovalTxData({\n amount,\n sourceChainData,\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 = buildTransferTxData({\n amount,\n burnToken,\n targetChainData,\n toAddress,\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 }\n\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\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 config: Config,\n params: TransferParams,\n environment: Environment,\n): Promise<BridgeTransfer> {\n const { minimumConfirmations: requiredSourceConfirmationCount } =\n config.find((chainData) => chainData.chainId === params.sourceChain.chainId) ?? {};\n const { minimumConfirmations: requiredTargetConfirmationCount } =\n 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 getFees(config, { ...params, provider: params.sourceProvider });\n\n const bridgeFee = (params.asset.address && fees[params.asset.address]) ?? 0n;\n const txHash = await approveAndTransfer(config, 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: BridgeType.CCTP,\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 { encodeFunctionData } from 'viem';\nimport type { ChainData, Token } from '../types/config';\nimport { TOKEN_ROUTER_ABI } from '../abis/token-router';\nimport { ERC20_ABI } from '../abis/erc20';\n\nexport function buildTransferTxData({\n amount,\n burnToken,\n targetChainData,\n toAddress,\n}: {\n targetChainData: ChainData;\n toAddress: `0x${string}`;\n burnToken: Token;\n amount: bigint;\n}) {\n return encodeFunctionData({\n abi: TOKEN_ROUTER_ABI,\n functionName: 'transferTokens',\n args: [amount, targetChainData.domain, toAddress, burnToken.address],\n });\n}\n\nexport function buildApprovalTxData({ amount, sourceChainData }: { amount: bigint; sourceChainData: ChainData }) {\n return encodeFunctionData({\n abi: ERC20_ABI,\n functionName: 'approve',\n args: [sourceChainData.tokenRouterAddress, amount],\n });\n}\n","import { decodeEventLog, type Address } from 'viem';\nimport { ErrorReason, type BridgeTransfer, type TrackingParams, ErrorCode } 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';\nimport type { Config } from '../types/config';\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: Config, 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.toLowerCase() === sourceChainData.tokenRouterAddress.toLowerCase()) {\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: Config, 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(config: Config, params: TrackingParams) {\n let abortFn: (() => void) | undefined;\n\n const cancel = () => {\n abortFn?.();\n };\n\n const executeTracking = async () => {\n const { sourceProvider, targetProvider, updateListener, bridgeTransfer } = params;\n\n const { result: sourceTracker, cancel: cancelSourceTracking } = await trackSourceTx(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(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 = 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 { 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 { isAddress } from 'viem';\n\nimport { InvalidParamsError } from '../../../errors';\nimport { getClientForChain } from '../../../utils/client';\nimport { ErrorReason, type TransferParams } from '../../../types';\n\nimport { ERC20_ABI } from '../abis/erc20';\nimport { getTransferData } from '../utils/transfer-data';\nimport { ChainDomain } from '../types/chain';\nimport type { Config } from '../types/config';\n\nconst ETH_APPROVAL_TX_GAS_ESTIMATE = 60_000n; // 55.5k gas on average (+/- 200 units)\nconst ETH_TRANSFER_TX_GAS_ESTIMATE = 175_000n; // 161.5k gas on average (+/- 200 units)\nconst AVAX_APPROVAL_TX_GAS_ESTIMATE = 60_000n; // 55.5k gas on average (+/- 200 units)\nconst AVAX_TRANSFER_TX_GAS_ESTIMATE = 215_000n; // 203k gas on average (+/- 200 units)\n/**\n * The CCTP bridging consists of up to two transactions:\n *\n * 1. Token spend approval (technically optional, but realistically performed basically every time)\n * 2. Token transfer (required)\n *\n * Since the 2nd one needs the first transaction to be complete, calling .estimateGas() is not possible.\n * The RPC call raises an error since it cannot execute the transfer transaction locally without\n * the allowance being set. For that reason, we're using hard-coded estimates here, with small buffers added.\n *\n * NOTE: These estimates are only supposed to be used to approximate the network fees in the UI.\n * DO NOT use them as `gasLimit` prop on the transactions!\n */\nexport async function estimateGas(config: Config, params: TransferParams): Promise<bigint> {\n const { sourceChain, targetChain, asset, amount, fromAddress, toAddress: maybeToAddress, sourceProvider } = 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, burnToken } = getTransferData({ sourceChain, targetChain, asset, amount }, 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 isOffboarding = sourceChainData.domain === ChainDomain.Avalanche;\n\n if (allowance >= amount) {\n return isOffboarding ? AVAX_TRANSFER_TX_GAS_ESTIMATE : ETH_TRANSFER_TX_GAS_ESTIMATE;\n }\n\n return isOffboarding\n ? AVAX_APPROVAL_TX_GAS_ESTIMATE + AVAX_TRANSFER_TX_GAS_ESTIMATE\n : ETH_APPROVAL_TX_GAS_ESTIMATE + ETH_TRANSFER_TX_GAS_ESTIMATE;\n}\n","import { type BridgeServiceFactory, BridgeType } from '../../types/bridge';\nimport { getAssets } from './handlers/get-assets';\nimport { getFees } from './handlers/get-fees';\nimport { transferAsset } from './handlers/transfer-asset';\nimport { trackTransfer } from './handlers/track-transfer';\nimport { estimateGas } from './handlers/estimate-gas';\nimport { getConfig } from './utils/config';\n\nexport const cctpBridgeFactory: BridgeServiceFactory = async (environment) => {\n const config = await getConfig(environment);\n return {\n type: BridgeType.CCTP,\n estimateGas: (params) => estimateGas(config, params),\n getAssets: () => getAssets(config),\n getFees: (params) => getFees(config, params),\n transferAsset: (params) => transferAsset(config, params, environment),\n trackTransfer: (params) => trackTransfer(config, params),\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 type { Environment } from '../types/environment';\nimport type { BridgeServicesMap } from '../types/config';\n\nimport { compact } from 'lodash';\n\nexport const supportedBridges = new Map([[BridgeType.CCTP, cctpBridgeFactory]]);\n\nexport const getEnabledBridgeServices = async (\n environment: Environment,\n disabledBridgeTypes: BridgeType[],\n): Promise<BridgeServicesMap> => {\n const filteredBridges = [...supportedBridges].filter(([bridgeType]) => !disabledBridgeTypes.includes(bridgeType));\n const bridgePromisesResults = await Promise.allSettled(\n filteredBridges.map(\n async ([bridgeType, factory]): Promise<[BridgeType, BridgeService]> => [bridgeType, await factory(environment)],\n ),\n );\n\n return new Map(\n compact(bridgePromisesResults.map((result) => (result.status === 'fulfilled' ? result.value : undefined))),\n );\n};\n\nexport const getBridgeForTransfer = (\n enabledBridgeServices: Map<BridgeType, BridgeService>,\n asset: BridgeAsset,\n targetChainId: string,\n) => {\n const destinations = asset.destinations[targetChainId];\n for (const bridgeType of destinations ?? []) {\n const bridge = enabledBridgeServices.get(bridgeType);\n if (bridge) {\n return { bridge, type: bridgeType };\n }\n }\n throw new BridgeUnavailableError();\n};\n","import type { FeeParams, TrackingParams, TransferParams } from './types/bridge';\nimport type { BridgeServiceConfig } from './types/config';\nimport { getBridgeForTransfer } from './utils';\nimport type { BridgeAsset, ChainAssetMap } from './types';\nimport { isArray, mergeWith } from 'lodash';\nimport { BridgeUnavailableError } from './errors';\n\nexport const createUnifiedBridgeService = ({ environment, enabledBridgeServices }: BridgeServiceConfig) => {\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 const estimateGas = async (params: TransferParams) => {\n const { bridge } = getBridgeForTransfer(enabledBridgeServices, params.asset, params.targetChain.chainId);\n\n return bridge.estimateGas(params);\n };\n\n return {\n environment,\n getAssets,\n getFees,\n estimateGas,\n canTransferAsset,\n transferAsset,\n trackTransfer,\n };\n};\n"]}