@avalabs/bridge-unified 0.0.0-feat-unified-api-interface-20231127104332

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/.turbo/turbo-build.log +22 -0
  2. package/.turbo/turbo-lint.log +4 -0
  3. package/.turbo/turbo-test.log +13 -0
  4. package/CHANGELOG.md +13 -0
  5. package/README.md +39 -0
  6. package/dist/index.cjs +13 -0
  7. package/dist/index.cjs.map +1 -0
  8. package/dist/index.d.cts +150 -0
  9. package/dist/index.d.ts +150 -0
  10. package/dist/index.js +8 -0
  11. package/dist/index.js.map +1 -0
  12. package/jest.config.js +9 -0
  13. package/package.json +26 -0
  14. package/src/bridges/cctp/__mocks__/asset.mock.ts +15 -0
  15. package/src/bridges/cctp/__mocks__/chain.mocks.ts +27 -0
  16. package/src/bridges/cctp/__mocks__/config.mock.ts +38 -0
  17. package/src/bridges/cctp/abis/erc20.ts +117 -0
  18. package/src/bridges/cctp/abis/message-transmitter.ts +318 -0
  19. package/src/bridges/cctp/abis/token-router.ts +843 -0
  20. package/src/bridges/cctp/factory.test.ts +96 -0
  21. package/src/bridges/cctp/factory.ts +32 -0
  22. package/src/bridges/cctp/handlers/get-assets.ts +27 -0
  23. package/src/bridges/cctp/handlers/get-fees.ts +27 -0
  24. package/src/bridges/cctp/handlers/track-transfer.ts +303 -0
  25. package/src/bridges/cctp/handlers/transfer-asset.ts +113 -0
  26. package/src/bridges/cctp/index.ts +1 -0
  27. package/src/bridges/cctp/types/config.ts +18 -0
  28. package/src/bridges/cctp/utils/config.ts +30 -0
  29. package/src/bridges/cctp/utils/transfer-data.ts +40 -0
  30. package/src/index.ts +2 -0
  31. package/src/types/asset.ts +26 -0
  32. package/src/types/bridge.ts +50 -0
  33. package/src/types/chain.ts +10 -0
  34. package/src/types/config.ts +10 -0
  35. package/src/types/environment.ts +4 -0
  36. package/src/types/index.ts +7 -0
  37. package/src/types/provider.ts +15 -0
  38. package/src/types/transfer.ts +34 -0
  39. package/src/unified-bridge-service.ts +51 -0
  40. package/src/utils/bridge-types.ts +31 -0
  41. package/src/utils/client.ts +39 -0
  42. package/src/utils/ensure-config.ts +11 -0
  43. package/src/utils/index.ts +1 -0
  44. package/src/utils/network-fee.test.ts +24 -0
  45. package/src/utils/network-fee.ts +6 -0
  46. package/src/utils/retry-promise.ts +62 -0
  47. package/src/utils/wait.ts +4 -0
  48. package/tsconfig.jest.json +6 -0
  49. package/tsconfig.json +9 -0
  50. package/tsup.config.ts +4 -0
@@ -0,0 +1,22 @@
1
+
2
+ > @avalabs/bridge-unified@1.0.1 build /home/runner/work/consumer-sdks/consumer-sdks/packages/bridge-unified
3
+ > tsup
4
+
5
+ CLI Building entry: ./src/index.ts
6
+ CLI Using tsconfig: tsconfig.json
7
+ CLI tsup v7.2.0
8
+ CLI Using tsup config: /home/runner/work/consumer-sdks/consumer-sdks/packages/bridge-unified/tsup.config.ts
9
+ CLI Target: es2021
10
+ CLI Cleaning output folder
11
+ CJS Build start
12
+ ESM Build start
13
+ CJS dist/index.cjs 19.98 KB
14
+ CJS dist/index.cjs.map 68.43 KB
15
+ CJS ⚡️ Build success in 1417ms
16
+ ESM dist/index.js 19.98 KB
17
+ ESM dist/index.js.map 68.43 KB
18
+ ESM ⚡️ Build success in 1411ms
19
+ DTS Build start
20
+ DTS ⚡️ Build success in 8414ms
21
+ DTS dist/index.d.cts 4.04 KB
22
+ DTS dist/index.d.ts 4.04 KB
@@ -0,0 +1,4 @@
1
+
2
+ > @avalabs/bridge-unified@1.0.1 lint /home/runner/work/consumer-sdks/consumer-sdks/packages/bridge-unified
3
+ > eslint "src/**/*.ts"
4
+
@@ -0,0 +1,13 @@
1
+
2
+ > @avalabs/bridge-unified@1.0.1 test /home/runner/work/consumer-sdks/consumer-sdks/packages/bridge-unified
3
+ > jest
4
+
5
+ ts-jest[config] (WARN) message TS151001: If you have issues related to imports, you should consider setting `esModuleInterop` to `true` in your TypeScript configuration file (usually `tsconfig.json`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information.
6
+ PASS src/bridges/cctp/factory.test.ts (9.982 s)
7
+ PASS src/utils/network-fee.test.ts
8
+
9
+ Test Suites: 2 passed, 2 total
10
+ Tests: 3 passed, 3 total
11
+ Snapshots: 0 total
12
+ Time: 10.538 s
13
+ Ran all test suites.
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @avalabs/unified-bridge
2
+
3
+ ## 0.0.0-feat-unified-api-interface-20231127104332
4
+
5
+ ### Major Changes
6
+
7
+ - 8be3950: CCTP integration
8
+
9
+ ## 1.0.1
10
+
11
+ ### Patch Changes
12
+
13
+ - a397015: Shared tsup config
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ <p align="center">
2
+ <a href="https://subnets.avax.network/">
3
+ <picture>
4
+ <img alt="Avalanche Logo" src="https://images.ctfassets.net/gcj8jwzm6086/Gse8dqDEnJtT87RsbbEf4/1609daeb09e9db4a6617d44623028356/Avalanche_Horizontal_White.svg" width="auto" height="60">
5
+ </picture>
6
+ </a>
7
+ </p>
8
+
9
+ <p align="center">
10
+ A package for routing tokens from Chain A to Chain B, and unifying multiple bridge tools into one.
11
+ <p>
12
+
13
+ ## What is this?
14
+
15
+ The bridging ecosystem is complex. There are often multiple tools that can be used to bridge tokens from one chain to another, and sometimes to get a token from chain A to C you need to use multiple bridging tools and route through chain B first. This package simplifies that process by creating the _Unified Bridge API_, a standard interface for bridging tokens from one chain to another without having to worry about the underlying tools or the underlying intermediary chains.
16
+
17
+ These are the bridges we currently support:
18
+
19
+ - **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.
21
+
22
+ Future bridges we plan to support:
23
+
24
+ - **Teleporter** - for moving tokens between subnets.
25
+ - **Cross-Chain Transfer** - for moving tokens between the three Avalanche Primary Network chains (X-Chain, C-Chain, and P-Chain).
26
+
27
+ ## Getting Started
28
+
29
+ ```sh
30
+ npm install @avalabs/bridge-unified
31
+ # or
32
+ yarn add @avalabs/bridge-unified
33
+ # or
34
+ pnpm add @avalabs/bridge-unified
35
+ ```
36
+
37
+ ## How it works
38
+
39
+ TODO: Explain details of this api.
package/dist/index.cjs ADDED
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ var lodash = require('lodash');
4
+ var viem = require('viem');
5
+
6
+ var I=(a=>(a.NATIVE="native",a.ERC20="erc20",a))(I||{});var b=(n=>(n.CCTP="cctp",n))(b||{});var E=(a=>(a.PROD="production",a.TEST="test",a))(E||{});var j={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"},R=async e=>{try{return await(await fetch(j[e])).json()}catch(n){throw new Error(`Error while fetching CCTP config: ${n.message}`)}},x=e=>{switch(e){case 43114:case 43113:return 1e3;default:return 2e4}};async function S(e){await e.ensureHasConfig();let n=e.config.map(a=>a.chainId);return e.config.reduce((a,s)=>(a[s.chainId]=s.tokens.map(r=>({...r,type:"erc20",destinations:n.reduce((t,i)=>(s.chainId!==i&&(t[i]||(t[i]=[]),t[i]?.push("cctp")),t),{})})),a),{})}var X=e=>({id:e.chainId,name:e.chainName,nativeCurrency:{decimals:e.networkToken.decimals,symbol:e.networkToken.symbol,name:e.networkToken.name},network:e.chainName,rpcUrls:{default:{http:[e.rpcUrl]},public:{http:[e.rpcUrl]}},...e.utilityAddresses.multicall&&{contracts:{multicall3:{address:e.utilityAddresses.multicall}}}}),f=({chain:e,provider:n})=>{let a=X(e),s=n?viem.custom(n):viem.http(e.rpcUrl);return viem.createWalletClient({chain:a,transport:s}).extend(viem.publicActions)};var g=[{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 h=({sourceChain:e,targetChain:n,amount:a,asset:s},r)=>{if(e.chainId===n.chainId)throw new Error("Source and target chains are the same");if(a<=0n)throw new Error("Amount must be greater than zero");let t=r.find(o=>o.chainId===e.chainId);if(!t)throw new Error(`Not supported on source chain "${e.chainId}"`);let i=r.find(o=>o.chainId===n.chainId);if(!i)throw new Error(`Not supported on target chain "${n.chainId}"`);let c=t.tokens.find(o=>o.symbol===s.symbol),p=i.tokens.find(o=>o.symbol===s.symbol);if(!c||!p)throw new Error(`Not supported asset "${s.symbol}"`);return {sourceChainData:t,targetChainData:i,burnToken:c,mintToken:p}};async function N(e,n){await e.ensureHasConfig();let{sourceChain:a,targetChain:s,asset:r,amount:t,provider:i}=n,{sourceChainData:c,targetChainData:p,burnToken:o}=h({sourceChain:a,targetChain:s,asset:r,amount:t},e.config),d=await f({chain:a,provider:i}).readContract({address:c.tokenRouterAddress,abi:g,functionName:"calculateFee",args:[t,p.domain]});return {[o.address]:d}}var v=[{constant:!0,inputs:[],name:"name",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_spender",type:"address"},{name:"_value",type:"uint256"}],name:"approve",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"totalSupply",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_from",type:"address"},{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transferFrom",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"decimals",outputs:[{name:"",type:"uint8"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"balanceOf",outputs:[{name:"balance",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[],name:"symbol",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transfer",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"},{name:"_spender",type:"address"}],name:"allowance",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{payable:!0,stateMutability:"payable",type:"fallback"},{anonymous:!1,inputs:[{indexed:!0,name:"owner",type:"address"},{indexed:!0,name:"spender",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Approval",type:"event"},{anonymous:!1,inputs:[{indexed:!0,name:"from",type:"address"},{indexed:!0,name:"to",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Transfer",type:"event"}];var J=async(e,n)=>{let{sourceChain:a,targetChain:s,asset:r,amount:t,addressC:i,sourceProvider:c}=n;await e.ensureHasConfig();let{sourceChainData:p,targetChainData:o,burnToken:u}=h({sourceChain:a,targetChain:s,asset:r,amount:t},e.config),d=f({chain:a,provider:c});if(await d.readContract({address:u.address,abi:v,functionName:"allowance",args:[i,p.tokenRouterAddress]})<t)if(c.sign){let m=viem.encodeFunctionData({abi:v,functionName:"approve",args:[p.tokenRouterAddress,t]}),y=await c.sign({from:i,to:u.address,data:m}),T=await d.sendRawTransaction({serializedTransaction:y});await d.waitForTransactionReceipt({hash:T,pollingInterval:1e3});}else {let{request:m}=await d.simulateContract({account:i,address:u.address,abi:v,functionName:"approve",args:[p.tokenRouterAddress,t]}),y=await d.writeContract(m);await d.waitForTransactionReceipt({hash:y,pollingInterval:1e3});}if(c.sign){let m=viem.encodeFunctionData({abi:g,functionName:"transferTokens",args:[t,o.domain,i,u.address]}),y=await c.sign({from:i,to:p.tokenRouterAddress,data:m});return d.sendRawTransaction({serializedTransaction:y})}else {let{request:m}=await d.simulateContract({account:i,address:p.tokenRouterAddress,abi:g,functionName:"transferTokens",args:[t,o.domain,i,u.address]});return d.writeContract(m)}};async function _(e,n,a){let s=await e.getFees({...n,provider:n.sourceProvider}),r=(n.asset.address&&s[n.asset.address])??0n,t=await J(e,n),i=Date.now(),p=await f({chain:n.targetChain,provider:n.targetProvider}).getBlockNumber();return {type:e.type,environment:a,addressC:n.addressC,addressBtc:n.addressBtc,amount:n.amount,symbol:n.asset.symbol,bridgeFee:r,sourceChain:n.sourceChain,sourceStartedAt:i,sourceTxHash:t,sourceConfirmationCount:0,requiredSourceConfirmationCount:1,targetChain:n.targetChain,targetConfirmationCount:0,requiredTargetConfirmationCount:1,startBlockNumber:p}}async function H(e){if(!e.config&&(await e.updateConfig(),!e.config))throw new Error("Config is not available")}var k=(e,n)=>e.gasPrice&&BigInt(e.gasPrice*n.gasUsed);var A=async e=>new Promise(n=>{setTimeout(n,e);});var B=({promise:e,delay:n})=>{let a=!1,s=!1,r=0,t,i,c=u=>{t&&a&&(a=!1,t(u));},p=()=>{s=!0,i&&a&&(a=!1,i("cancelled"));};return {result:new Promise((u,d)=>{a=!0,t=u,i=d;let l=async()=>{if(!(!a||s)){try{await e(c),await A(n);}catch(m){console.error(m.message),r+=1,await A(2**r*n);}await l();}};l();}),cancel:p}};var U=1e3*60*60*3,Q=2048n,Y=async(e,n)=>{let{sourceProvider:a,targetProvider:s,updateListener:r,bridgeTransfer:t}=n,i=f({chain:t.sourceChain,provider:a}),c=e.find(d=>d.chainId===t.sourceChain.chainId),p=f({chain:t.targetChain,provider:s}),o=e.find(d=>d.chainId===t.targetChain.chainId);if(!c)throw new Error(`BridgeTransfer: unknown source chain "${t.sourceChain.chainId}"`);if(!o)throw new Error(`BridgeTransfer: unknown target chain "${t.targetChain.chainId}"`);return B({promise:async d=>{if(t.completedAt||t.metadata?.nonce)return d(t);if(t.sourceStartedAt+U<=Date.now())return t.completedAt=Date.now(),t.error="timeout",d(t);let l=await i.getTransactionReceipt({hash:t.sourceTxHash});if(!t.sourceNetworkFee){let C=await i.getTransaction({hash:t.sourceTxHash}),w=k(C,l);w&&(t.sourceNetworkFee=w,r(t));}if(l.status==="reverted")return t.completedAt=Date.now(),t.error=`source transaction "${t.sourceTxHash}" reverted`,d(t);let m=await i.getTransactionConfirmations({hash:t.sourceTxHash}),y=m>t.sourceConfirmationCount,T=m>=t.requiredSourceConfirmationCount;if(y&&(t.sourceConfirmationCount=Number(m),T||(t.startBlockNumber=await p.getBlockNumber()),r(t)),!T)return;let P=l.logs.find(C=>C.address===c.tokenRouterAddress?viem.decodeEventLog({abi:g,...C}).eventName==="TransferTokens":!1);if(!P)throw new Error(`BridgeTransfer: can't find a TransferTokens event in source transaction "${t.sourceTxHash}"`);let K=viem.decodeEventLog({abi:g,eventName:"TransferTokens",...P}).args.nonce,M={...n.bridgeTransfer,targetStartedAt:Date.now(),metadata:{nonce:K}};return r(M),d(M)},delay:x(c.chainId)})},Z=async(e,n)=>{let{targetProvider:a,updateListener:s,bridgeTransfer:r}=n;if(!r.completedAt&&!r.metadata?.nonce)throw new Error("BridgeTransfer: nonce is missing");if(!r.startBlockNumber)throw new Error("BridgeTransfer: startBlockNumber is missing");let t=f({chain:r.targetChain,provider:a}),i=e.find(p=>p.chainId===r.targetChain.chainId);if(!i)throw new Error(`BridgeTransfer: unknown target chain "${r.targetChain.chainId}"`);return B({promise:async p=>{if(r.completedAt)return p(r);if(r.sourceStartedAt+U<=Date.now())return r.completedAt=Date.now(),r.error="timeout",p(r);if(!r.targetTxHash){let m=await t.getLogs({address:i.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:r.metadata.nonce},fromBlock:r.startBlockNumber-5n,toBlock:r.startBlockNumber+Q});if(m[0]?.transactionHash)r.targetTxHash=m[0].transactionHash,s(r);else return}let o=await t.getTransactionReceipt({hash:r.targetTxHash});if(!r.targetNetworkFee){let m=await t.getTransaction({hash:r.targetTxHash}),y=k(m,o);y&&(r.targetNetworkFee=y,s(r));}if(o.status==="reverted")return r.completedAt=Date.now(),r.error=`target transaction "${r.targetTxHash}" reverted`,p(r);let u=await t.getTransactionConfirmations({hash:r.targetTxHash}),d=u>r.targetConfirmationCount,l=u>=r.requiredTargetConfirmationCount;if(d&&(r.targetConfirmationCount=Number(u),s(r)),!!l)return r.completedAt=Date.now(),s(r),p(r)},delay:x(i.chainId)})};function L(e,n){let a;return {result:(async()=>{await e.ensureHasConfig();let{result:r,cancel:t}=await Y(e.config,n);a=t;let i=await r,{result:c,cancel:p}=await Z(e.config,{...n,bridgeTransfer:i});return a=p,c})(),cancel:a}}var $=e=>({type:"cctp",config:null,updateConfig:async function(){this.config=await R(e);},ensureHasConfig:async function(){return H(this)},getAssets:async function(){return S(this)},getFees:async function(n){return N(this,n)},transferAsset:async function(n){return _(this,n,e)},trackTransfer:function(n){return L(this,n)}});var ee=new Map([["cctp",$]]),q=(e,n)=>new Map([...ee].filter(([a])=>!n?.includes(a)).map(([a,s])=>[a,s(e)])),F=(e,n,a)=>{let s=n.destinations[a]?.find(r=>e.has(r));if(!s)throw new Error(`No enabled implementation found for transfering ${n.symbol} to ${a}`);return {type:s,bridge:e.get(s)}};var ut=({environment:e,disabledBridgeTypes:n})=>{let a=q(e,n),s=async()=>Promise.all(Array.from(a).map(([,o])=>o.updateConfig()));return {bridges:a,init:async()=>{await s();},updateConfigs:s,getAssets:async()=>(await Promise.all(Array.from(a).map(([,u])=>u.getAssets()))).flat().reduce(lodash.merge),getFees:async o=>{let{bridge:u}=F(a,o.asset,o.targetChain.chainId);return u.getFees(o)},transferAsset:async o=>{let{bridge:u}=F(a,o.asset,o.targetChain.chainId);return u.transferAsset(o)},trackTransfer:o=>{let u=a.get(o.bridgeTransfer.type);if(!u)throw new Error(`No enabled implementation found for tracking ${o.bridgeTransfer.type} transactions.`);return u.trackTransfer(o)}}};
7
+
8
+ exports.BridgeType = b;
9
+ exports.Environment = E;
10
+ exports.TokenType = I;
11
+ exports.createUnifiedBridgeService = ut;
12
+ //# sourceMappingURL=out.js.map
13
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types/asset.ts","../src/types/bridge.ts","../src/types/environment.ts","../src/unified-bridge-service.ts","../src/bridges/cctp/utils/config.ts","../src/bridges/cctp/handlers/get-assets.ts","../src/utils/client.ts","../src/bridges/cctp/abis/token-router.ts","../src/bridges/cctp/utils/transfer-data.ts","../src/bridges/cctp/handlers/get-fees.ts","../src/bridges/cctp/handlers/transfer-asset.ts","../src/bridges/cctp/abis/erc20.ts","../src/utils/ensure-config.ts","../src/bridges/cctp/handlers/track-transfer.ts","../src/utils/network-fee.ts","../src/utils/wait.ts","../src/utils/retry-promise.ts","../src/bridges/cctp/factory.ts","../src/utils/bridge-types.ts"],"names":["TokenType","BridgeType","Environment","merge","CONFIG_URLS","getConfig","environment","err","getTrackingDelayByChainId","chainId","getAssets","bridge","chainIds","chainData","assets","asset","destinations","createWalletClient","publicActions","custom","http","_getChain","chain","getClientForChain","provider","chainInfo","transport","TOKEN_ROUTER_ABI","getTransferData","sourceChain","targetChain","amount","config","sourceChainData","targetChainData","burnToken","token","mintToken","getFees","params","feeAmount","encodeFunctionData","ERC20_ABI","approveAndTransfer","addressC","sourceProvider","client","data","signedHex","txHash","request","transferAsset","fees","bridgeFee","sourceStartedAt","targetBlockNumber","ensureHasConfig","decodeEventLog","getNetworkFeeEVM","transaction","receipt","wait","time","res","retryPromise","promise","delay","isRunning","isCancelled","errorCount","resolve","reject","done","cancel","rej","execute","TRACKING_LIMIT_MS","MAX_BLOCKS","trackSourceTx","targetProvider","updateListener","bridgeTransfer","sourceClient","targetClient","txReceipt","tx","networkFee","confirmationCount","hasMoreConfirmations","hasRequiredConfirmations","transferEventLog","log","nonce","transfer","trackTargetTx","targetLogs","trackTransfer","sourceTracker","cancelSourceTracking","transferAfterSourceFinished","targetTracker","cancelTargetTracking","cctpBridgeFactory","supportedBridges","getEnabledBridgeServices","disabledBridgeTypes","bridgeType","factory","getBridgeForTransfer","enabledBridgeServices","targetChainId","createUnifiedBridgeService","updateConfigs","bridgeService"],"mappings":"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,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,aACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,eACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,iBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,mBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,eACN,KAAM,SACR,CACF,EACA,KAAM,oBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,eACN,KAAM,SACR,CACF,EACA,KAAM,sBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,SACd,KAAM,SACN,KAAM,QACR,EACA,CACE,WAAY,CACV,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,SACd,KAAM,gBACN,KAAM,QACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,OACd,KAAM,YACN,KAAM,MACR,CACF,EACA,QAAS,GACT,aAAc,wCACd,KAAM,mBACN,KAAM,OACR,CACF,EACA,KAAM,0BACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,gBACN,KAAM,SACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,WACN,KAAM,SACR,CACF,EACA,KAAM,uBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,SACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,SACd,KAAM,QACN,KAAM,QACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,YACN,KAAM,SACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,YACN,KAAM,SACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,gBACN,KAAM,SACR,EACA,CACE,QAAS,GACT,aAAc,SACd,KAAM,oBACN,KAAM,QACR,EACA,CACE,QAAS,GACT,aAAc,UACd,KAAM,WACN,KAAM,SACR,CACF,EACA,KAAM,iBACN,KAAM,OACR,EACA,CACE,UAAW,GACX,OAAQ,CACN,CACE,QAAS,GACT,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,WACN,KAAM,OACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,WACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,eACN,KAAM,SACR,CACF,EACA,KAAM,kBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,wBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,SACd,KAAM,oBACN,KAAM,QACR,CACF,EACA,KAAM,eACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,uBACN,QAAS,CACP,CACE,aAAc,iCACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,8BACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,cACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,gBACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,sBACN,QAAS,CACP,CACE,WAAY,CACV,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,SACd,KAAM,gBACN,KAAM,QACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,OACd,KAAM,YACN,KAAM,MACR,CACF,EACA,aAAc,wCACd,KAAM,GACN,KAAM,OACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,mBACN,QAAS,CACP,CACE,aAAc,SACd,KAAM,GACN,KAAM,QACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,YACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,YACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,YACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,UACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,iBACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,uBACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,CACF,EACA,KAAM,oBACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,QACN,QAAS,CACP,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,QACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,SACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,UACN,KAAM,SACR,CACF,EACA,KAAM,cACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,eACN,KAAM,SACR,CACF,EACA,KAAM,qBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,QACN,KAAM,SACR,CACF,EACA,KAAM,2BACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CAAC,EACT,KAAM,oBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,SACd,KAAM,SACN,KAAM,QACR,EACA,CACE,WAAY,CACV,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,SACd,KAAM,gBACN,KAAM,QACR,EACA,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,OACd,KAAM,YACN,KAAM,MACR,CACF,EACA,aAAc,wCACd,KAAM,mBACN,KAAM,OACR,CACF,EACA,KAAM,sBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,GACN,KAAM,SACR,CACF,EACA,KAAM,sBACN,QAAS,CACP,CACE,aAAc,OACd,KAAM,GACN,KAAM,MACR,CACF,EACA,gBAAiB,OACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,WACN,KAAM,SACR,CACF,EACA,KAAM,oBACN,QAAS,CAAC,EACV,gBAAiB,aACjB,KAAM,UACR,EACA,CACE,OAAQ,CACN,CACE,aAAc,UACd,KAAM,SACN,KAAM,SACR,EACA,CACE,aAAc,SACd,KAAM,oBACN,KAAM,QACR,EACA,CACE,aAAc,UACd,KAAM,gBACN,KAAM,SACR,EACA,CACE,aAAc,UACd,KAAM,YACN,KAAM,SACR,CACF,EACA,KAAM,iBACN,QAAS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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<number, BridgeType[]>;\n\nexport type BridgeAsset = Asset & {\n destinations: DestinationInfo;\n};\n\nexport type ChainAssetMap = Record<number, BridgeAsset[]>;\n\nexport type AssetFeeMap = Record<Address, bigint>;\n","import type { Address } from 'viem';\nimport type { AssetFeeMap, BridgeAsset, ChainAssetMap } from './asset';\nimport type { Chain } from './chain';\nimport type { BridgeConfig } from './config';\nimport type { Environment } from './environment';\nimport type { Provider } from './provider';\nimport type { 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 type TransferParams = {\n asset: BridgeAsset;\n amount: bigint;\n addressC: Address;\n addressBtc: string;\n sourceChain: Chain;\n targetChain: Chain;\n sourceProvider: Provider;\n targetProvider?: Provider;\n};\n\nexport type TrackingParams = {\n bridgeTransfer: BridgeTransfer;\n sourceProvider?: Provider;\n targetProvider?: Provider;\n updateListener: (transfer: BridgeTransfer) => void;\n};\n\nexport type BridgeService = {\n type: BridgeType;\n config: BridgeConfig | null;\n ensureHasConfig: () => Promise<void>;\n updateConfig: () => Promise<void>;\n getAssets: () => Promise<ChainAssetMap>;\n getFees: (params: FeeParams) => Promise<AssetFeeMap>;\n transferAsset: (params: TransferParams) => Promise<BridgeTransfer>;\n trackTransfer: (transfer: TrackingParams) => { cancel?: () => void; result: Promise<BridgeTransfer> };\n};\n\nexport type BridgeServiceFactory = (environment: Environment) => BridgeService;\n","export enum Environment {\n PROD = 'production',\n TEST = 'test',\n}\n","import { merge } from 'lodash';\nimport type { FeeParams, TrackingParams, TransferParams } from './types/bridge';\nimport type { BridgeServiceConfig } from './types/config';\nimport { getBridgeForTransfer, getEnabledBridgeServices } from './utils';\n\nexport const createUnifiedBridgeService = ({ environment, disabledBridgeTypes }: BridgeServiceConfig) => {\n const enabledBridgeServices = getEnabledBridgeServices(environment, disabledBridgeTypes);\n\n const updateConfigs = async () => {\n return Promise.all(Array.from(enabledBridgeServices).map(([, bridgeService]) => bridgeService.updateConfig()));\n };\n\n const init = async () => {\n await updateConfigs();\n };\n\n const getAssets = async () => {\n const assets = await Promise.all(Array.from(enabledBridgeServices).map(([, bridge]) => bridge.getAssets()));\n return assets.flat().reduce(merge);\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 trackTransfer = (params: TrackingParams) => {\n const bridge = enabledBridgeServices.get(params.bridgeTransfer.type);\n\n if (!bridge) {\n throw new Error(`No enabled implementation found for tracking ${params.bridgeTransfer.type} transactions.`);\n }\n\n return bridge.trackTransfer(params);\n };\n\n return {\n bridges: enabledBridgeServices,\n init,\n updateConfigs,\n getAssets,\n getFees,\n transferAsset,\n trackTransfer,\n };\n};\n","import { Environment } from '../../../types/environment';\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 = await response.json();\n\n return config;\n } catch (err) {\n throw new Error(`Error while fetching CCTP config: ${(err as unknown as Error).message}`);\n }\n};\n\nexport const getTrackingDelayByChainId = (chainId: number) => {\n switch (chainId) {\n case 43114:\n case 43113:\n return 1000;\n default:\n return 20000;\n }\n};\n","import { TokenType, type BridgeService, type ChainAssetMap, type DestinationInfo, BridgeType } from '../../../types';\n\nexport async function getAssets(bridge: BridgeService) {\n await bridge.ensureHasConfig();\n\n const chainIds = bridge.config!.map((chainData) => chainData.chainId);\n\n return bridge.config!.reduce<ChainAssetMap>((assets, chainData) => {\n assets[chainData.chainId] = chainData.tokens.map((asset) => ({\n ...asset,\n type: TokenType.ERC20,\n destinations: chainIds.reduce<DestinationInfo>((destinations, chainId) => {\n if (chainData.chainId !== chainId) {\n if (!destinations[chainId]) {\n destinations[chainId] = [];\n }\n\n destinations[chainId]?.push(BridgeType.CCTP);\n }\n\n return destinations;\n }, {}),\n }));\n\n return assets;\n }, {});\n}\n","import { createWalletClient, publicActions, custom, http } from 'viem';\nimport type { Chain } from '../types/chain';\nimport type { Provider } from '../types';\n\nconst _getChain = (chain: Chain) => ({\n id: chain.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\nexport const getClientForChain = ({ chain, provider }: { chain: Chain; provider?: Provider }) => {\n const chainInfo = _getChain(chain);\n const transport = provider ? custom(provider) : http(chain.rpcUrl);\n\n return createWalletClient({\n chain: chainInfo,\n transport,\n }).extend(publicActions);\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 { 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 Error(`Source and target chains are the same`);\n }\n\n if (amount <= 0n) {\n throw new Error(`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 Error(`Not supported on source chain \"${sourceChain.chainId}\"`);\n }\n\n const targetChainData = config.find((chainData) => chainData.chainId === targetChain.chainId);\n\n if (!targetChainData) {\n throw new Error(`Not supported on target chain \"${targetChain.chainId}\"`);\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 Error(`Not supported asset \"${asset.symbol}\"`);\n }\n\n return {\n sourceChainData,\n targetChainData,\n burnToken,\n mintToken,\n };\n};\n","import type { AssetFeeMap, BridgeService, FeeParams } from '../../../types';\nimport { getClientForChain } from '../../../utils/client';\nimport { TOKEN_ROUTER_ABI } from '../abis/token-router';\nimport { getTransferData } from '../utils/transfer-data';\n\nexport async function getFees(bridge: BridgeService, params: FeeParams) {\n await bridge.ensureHasConfig();\n\n const { sourceChain, targetChain, asset, amount, provider } = params;\n\n const { sourceChainData, targetChainData, burnToken } = getTransferData(\n { sourceChain, targetChain, asset, amount },\n bridge.config!,\n );\n\n const client = getClientForChain({ chain: sourceChain, provider });\n const feeAmount = await client.readContract({\n address: sourceChainData.tokenRouterAddress,\n abi: TOKEN_ROUTER_ABI,\n functionName: 'calculateFee',\n args: [amount, targetChainData.domain],\n });\n\n return {\n [burnToken.address]: feeAmount,\n } as AssetFeeMap;\n}\n","import { encodeFunctionData } from 'viem';\nimport type { BridgeService, Environment, TransferParams } 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';\n\nconst approveAndTransfer = async (bridge: BridgeService, params: TransferParams) => {\n const { sourceChain, targetChain, asset, amount, addressC, sourceProvider } = params;\n\n await bridge.ensureHasConfig();\n\n const { sourceChainData, targetChainData, burnToken } = getTransferData(\n { sourceChain, targetChain, asset, amount },\n bridge.config!,\n );\n const client = getClientForChain({ chain: sourceChain, provider: sourceProvider });\n\n const allowance = await client.readContract({\n address: burnToken.address,\n abi: ERC20_ABI,\n functionName: 'allowance',\n args: [addressC, sourceChainData.tokenRouterAddress],\n });\n\n if (allowance < amount) {\n if (sourceProvider.sign) {\n const data = encodeFunctionData({\n abi: ERC20_ABI,\n functionName: 'approve',\n args: [sourceChainData.tokenRouterAddress, amount],\n });\n\n const signedHex = await sourceProvider.sign({\n from: addressC,\n to: burnToken.address,\n data,\n });\n\n const txHash = await client.sendRawTransaction({ serializedTransaction: signedHex });\n await client.waitForTransactionReceipt({ hash: txHash, pollingInterval: 1_000 });\n } else {\n const { request } = await client.simulateContract({\n account: addressC,\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 if (sourceProvider.sign) {\n const data = encodeFunctionData({\n abi: TOKEN_ROUTER_ABI,\n functionName: 'transferTokens',\n args: [amount, targetChainData.domain, addressC, burnToken.address],\n });\n\n const signedHex = await sourceProvider.sign({\n from: addressC,\n to: sourceChainData.tokenRouterAddress,\n data,\n });\n\n return client.sendRawTransaction({ serializedTransaction: signedHex });\n } else {\n const { request } = await client.simulateContract({\n account: addressC,\n address: sourceChainData.tokenRouterAddress,\n abi: TOKEN_ROUTER_ABI,\n functionName: 'transferTokens',\n args: [amount, targetChainData.domain, addressC, burnToken.address],\n });\n\n return client.writeContract(request);\n }\n};\n\nexport async function transferAsset(bridge: BridgeService, params: TransferParams, environment: Environment) {\n const fees = await bridge.getFees({ ...params, provider: params.sourceProvider });\n const bridgeFee = (params.asset.address && fees[params.asset.address]) ?? 0n;\n const txHash = await approveAndTransfer(bridge, params);\n const sourceStartedAt = Date.now();\n const targetClient = getClientForChain({ chain: params.targetChain, provider: params.targetProvider });\n const targetBlockNumber = await targetClient.getBlockNumber();\n\n return {\n type: bridge.type,\n environment,\n addressC: params.addressC,\n addressBtc: params.addressBtc,\n amount: params.amount,\n symbol: params.asset.symbol,\n\n bridgeFee,\n\n sourceChain: params.sourceChain,\n sourceStartedAt,\n sourceTxHash: txHash,\n sourceConfirmationCount: 0,\n requiredSourceConfirmationCount: 1, // TODO: define in config for source / target\n\n targetChain: params.targetChain,\n targetConfirmationCount: 0,\n requiredTargetConfirmationCount: 1, // TODO: define in config for source / target\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 type { BridgeService } from '../types';\n\nexport async function ensureHasConfig(bridge: BridgeService) {\n if (!bridge.config) {\n await bridge.updateConfig();\n\n if (!bridge.config) {\n throw new Error('Config is not available');\n }\n }\n}\n","import { decodeEventLog, type Address } from 'viem';\nimport type { BridgeConfig, BridgeService, BridgeTransfer, TrackingParams } 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';\n\n// Maximum time (in ms) before the transaction is considered \"timed out\"\nconst TRACKING_LIMIT_MS = 1000 * 60 * 60 * 3;\n// The max blocks that can be queried before receiving an error response\nconst MAX_BLOCKS = 2048n;\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 */\nconst trackSourceTx = async (config: BridgeConfig, params: TrackingParams) => {\n const { sourceProvider, targetProvider, updateListener, bridgeTransfer } = params;\n const sourceClient = getClientForChain({ chain: bridgeTransfer.sourceChain, provider: sourceProvider });\n const sourceChainData = config.find((chainData) => chainData.chainId === bridgeTransfer.sourceChain.chainId);\n const targetClient = getClientForChain({ chain: bridgeTransfer.targetChain, provider: targetProvider });\n const targetChainData = config.find((chainData) => chainData.chainId === bridgeTransfer.targetChain.chainId);\n\n if (!sourceChainData) {\n throw new Error(`BridgeTransfer: unknown source chain \"${bridgeTransfer.sourceChain.chainId}\"`);\n }\n\n if (!targetChainData) {\n throw new Error(`BridgeTransfer: unknown target chain \"${bridgeTransfer.targetChain.chainId}\"`);\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 (bridgeTransfer.completedAt || bridgeTransfer.metadata?.nonce) {\n return done(bridgeTransfer);\n }\n\n /**\n * Check if the transaction has timed out\n */\n if (bridgeTransfer.sourceStartedAt + TRACKING_LIMIT_MS <= Date.now()) {\n bridgeTransfer.completedAt = Date.now();\n bridgeTransfer.error = 'timeout';\n return done(bridgeTransfer);\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: bridgeTransfer.sourceTxHash as Address,\n });\n\n /**\n * Calculate the network fee if needed.\n */\n if (!bridgeTransfer.sourceNetworkFee) {\n const tx = await sourceClient.getTransaction({ hash: bridgeTransfer.sourceTxHash as Address });\n const networkFee = getNetworkFeeEVM(tx, txReceipt);\n\n if (networkFee) {\n bridgeTransfer.sourceNetworkFee = networkFee;\n updateListener(bridgeTransfer);\n }\n }\n\n /**\n * Update the state and terminate if the transaction was reverted\n */\n if (txReceipt.status === 'reverted') {\n bridgeTransfer.completedAt = Date.now();\n bridgeTransfer.error = `source transaction \"${bridgeTransfer.sourceTxHash}\" reverted`;\n return done(bridgeTransfer);\n }\n\n /**\n * Check the confirmation count.\n * - update the sourceConfirmationCount if it increased\n * - update the startBlockNumber if it increased but is not enough\n * - keeps polling until it's greater than requiredSourceConfirmationCount\n */\n const confirmationCount = await sourceClient.getTransactionConfirmations({\n hash: bridgeTransfer.sourceTxHash as Address,\n });\n const hasMoreConfirmations = confirmationCount > bridgeTransfer.sourceConfirmationCount;\n const hasRequiredConfirmations = confirmationCount >= bridgeTransfer.requiredSourceConfirmationCount;\n\n if (hasMoreConfirmations) {\n bridgeTransfer.sourceConfirmationCount = Number(confirmationCount);\n\n if (!hasRequiredConfirmations) {\n bridgeTransfer.startBlockNumber = await targetClient.getBlockNumber();\n }\n\n updateListener(bridgeTransfer);\n }\n\n if (!hasRequiredConfirmations) {\n return;\n }\n\n /**\n * Get the `TransferTokens` event's log entry from the receipt\n */\n const transferEventLog = txReceipt.logs.find((log) => {\n if (log.address === sourceChainData.tokenRouterAddress) {\n const event = decodeEventLog({\n abi: TOKEN_ROUTER_ABI,\n ...log,\n });\n\n return event.eventName === 'TransferTokens';\n }\n\n return false;\n });\n\n if (!transferEventLog) {\n throw new Error(\n `BridgeTransfer: can't find a TransferTokens event in source transaction \"${bridgeTransfer.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 const transfer = { ...params.bridgeTransfer, targetStartedAt: Date.now(), metadata: { nonce } };\n updateListener(transfer);\n return done(transfer);\n };\n\n return retryPromise<BridgeTransfer>({\n promise: tracker,\n delay: getTrackingDelayByChainId(sourceChainData.chainId),\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 */\nconst trackTargetTx = async (config: BridgeConfig, params: TrackingParams) => {\n const { targetProvider, updateListener, bridgeTransfer } = params;\n\n if (!bridgeTransfer.completedAt && !bridgeTransfer.metadata?.nonce) {\n throw new Error(`BridgeTransfer: nonce is missing`);\n }\n\n if (!bridgeTransfer.startBlockNumber) {\n throw new Error(`BridgeTransfer: 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 Error(`BridgeTransfer: unknown target chain \"${bridgeTransfer.targetChain.chainId}\"`);\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 (bridgeTransfer.completedAt) {\n return done(bridgeTransfer);\n }\n\n /**\n * Check if the transaction has timed out\n */\n if (bridgeTransfer.sourceStartedAt + TRACKING_LIMIT_MS <= Date.now()) {\n bridgeTransfer.completedAt = Date.now();\n bridgeTransfer.error = 'timeout';\n return done(bridgeTransfer);\n }\n\n if (!bridgeTransfer.targetTxHash) {\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: bridgeTransfer.metadata!.nonce as bigint },\n fromBlock: bridgeTransfer.startBlockNumber! - 5n,\n toBlock: bridgeTransfer.startBlockNumber! + MAX_BLOCKS,\n });\n\n if (targetLogs[0]?.transactionHash) {\n bridgeTransfer.targetTxHash = targetLogs[0].transactionHash;\n updateListener(bridgeTransfer);\n } else {\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: bridgeTransfer.targetTxHash as Address,\n });\n\n /**\n * Calculate the network fee if needed.\n */\n if (!bridgeTransfer.targetNetworkFee) {\n const tx = await targetClient.getTransaction({ hash: bridgeTransfer.targetTxHash as Address });\n const networkFee = getNetworkFeeEVM(tx, txReceipt);\n\n if (networkFee) {\n bridgeTransfer.targetNetworkFee = networkFee;\n updateListener(bridgeTransfer);\n }\n }\n\n /**\n * Update the state and terminate if the transaction was reverted\n */\n if (txReceipt.status === 'reverted') {\n bridgeTransfer.completedAt = Date.now();\n bridgeTransfer.error = `target transaction \"${bridgeTransfer.targetTxHash}\" reverted`;\n return done(bridgeTransfer);\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: bridgeTransfer.targetTxHash as Address,\n });\n const hasMoreConfirmations = confirmationCount > bridgeTransfer.targetConfirmationCount;\n const hasRequiredConfirmations = confirmationCount >= bridgeTransfer.requiredTargetConfirmationCount;\n\n if (hasMoreConfirmations) {\n bridgeTransfer.targetConfirmationCount = Number(confirmationCount);\n updateListener(bridgeTransfer);\n }\n\n if (!hasRequiredConfirmations) {\n return;\n }\n\n bridgeTransfer.completedAt = Date.now();\n updateListener(bridgeTransfer);\n return done(bridgeTransfer);\n };\n\n return retryPromise<BridgeTransfer>({\n promise: tracker,\n delay: getTrackingDelayByChainId(targetChainData.chainId),\n });\n};\n\nexport function trackTransfer(bridge: BridgeService, params: TrackingParams) {\n let cancel: (() => void) | undefined;\n\n const executeTracking = async () => {\n await bridge.ensureHasConfig();\n\n const { result: sourceTracker, cancel: cancelSourceTracking } = await trackSourceTx(bridge.config!, params);\n cancel = cancelSourceTracking;\n const transferAfterSourceFinished = await sourceTracker;\n\n const { result: targetTracker, cancel: cancelTargetTracking } = await trackTargetTx(bridge.config!, {\n ...params,\n bridgeTransfer: transferAfterSourceFinished,\n });\n cancel = 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 gwei (10^-9)\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};\n\nexport const retryPromise = <T>({ promise, delay }: Params<T>) => {\n let isRunning = false;\n let isCancelled = false;\n let errorCount: number = 0;\n let resolve: ((data: T) => void) | undefined = undefined;\n let reject: ((reason?: string) => void) | undefined = undefined;\n\n const done = (data: T) => {\n if (resolve && isRunning) {\n isRunning = false;\n resolve(data);\n }\n };\n\n const cancel = () => {\n isCancelled = true;\n\n if (reject && isRunning) {\n isRunning = false;\n reject('cancelled');\n }\n };\n\n const result = new Promise<T>((res, rej) => {\n isRunning = true;\n resolve = res;\n reject = rej;\n\n const execute = async (): Promise<void> => {\n if (!isRunning || isCancelled) {\n return;\n }\n\n try {\n await promise(done);\n 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 execute();\n });\n\n return {\n result,\n cancel,\n };\n};\n","import { type BridgeServiceFactory, BridgeType } from '../../types/bridge';\nimport { getConfig } from './utils/config';\nimport { getAssets } from './handlers/get-assets';\nimport { getFees } from './handlers/get-fees';\nimport { transferAsset } from './handlers/transfer-asset';\nimport { ensureHasConfig } from '../../utils/ensure-config';\nimport { trackTransfer } from './handlers/track-transfer';\n\nexport const cctpBridgeFactory: BridgeServiceFactory = (environment) => {\n return {\n type: BridgeType.CCTP,\n config: null,\n updateConfig: async function () {\n this.config = await getConfig(environment);\n },\n ensureHasConfig: async function () {\n return ensureHasConfig(this);\n },\n getAssets: async function () {\n return getAssets(this);\n },\n getFees: async function (params) {\n return getFees(this, params);\n },\n transferAsset: async function (params) {\n return transferAsset(this, params, environment);\n },\n trackTransfer: function (params) {\n return trackTransfer(this, params);\n },\n };\n};\n","import { cctpBridgeFactory } from '../bridges/cctp/factory';\nimport type { BridgeAsset } from '../types/asset';\nimport { type BridgeService, BridgeType } from '../types/bridge';\nimport { Environment } from '../types/environment';\n\nexport const supportedBridges = new Map([[BridgeType.CCTP, cctpBridgeFactory]]);\n\nexport const getEnabledBridgeServices = (environment: Environment, disabledBridgeTypes?: BridgeType[]) => {\n return new Map(\n [...supportedBridges]\n .filter(([bridgeType]) => !disabledBridgeTypes?.includes(bridgeType))\n .map(([bridgeType, factory]) => [bridgeType, factory(environment)]),\n );\n};\n\nexport const getBridgeForTransfer = (\n enabledBridgeServices: Map<BridgeType, BridgeService>,\n asset: BridgeAsset,\n targetChainId: number,\n) => {\n const bridgeType = asset.destinations[targetChainId]?.find((bridgeType) => enabledBridgeServices.has(bridgeType));\n\n if (!bridgeType) {\n throw new Error(`No enabled implementation found for transfering ${asset.symbol} to ${targetChainId}`);\n }\n\n return {\n type: bridgeType,\n bridge: enabledBridgeServices.get(bridgeType)!,\n };\n};\n"]}
@@ -0,0 +1,150 @@
1
+ import { Address, TransactionRequest, Hex } from 'viem';
2
+
3
+ type Chain = {
4
+ chainName: string;
5
+ chainId: number;
6
+ rpcUrl: string;
7
+ utilityAddresses: {
8
+ multicall: Address;
9
+ };
10
+ networkToken: Asset;
11
+ };
12
+
13
+ type Token = {
14
+ address: Address;
15
+ name: string;
16
+ symbol: string;
17
+ decimals: number;
18
+ };
19
+ type ChainData = {
20
+ chainId: number;
21
+ domain: number;
22
+ tokenRouterAddress: Address;
23
+ messageTransmitterAddress: Address;
24
+ tokens: Token[];
25
+ };
26
+ type Config = ChainData[];
27
+
28
+ declare enum Environment {
29
+ PROD = "production",
30
+ TEST = "test"
31
+ }
32
+
33
+ type BridgeServiceConfig = {
34
+ environment: Environment;
35
+ disabledBridgeTypes?: BridgeType[];
36
+ };
37
+ type BridgeConfig = Config;
38
+
39
+ type RequestArguments = {
40
+ method: string;
41
+ params?: unknown[] | Record<string | number, unknown>;
42
+ };
43
+ type Provider = {
44
+ /**
45
+ * EIP-1193 compatible request method
46
+ * https://eips.ethereum.org/EIPS/eip-1193#request-1
47
+ */
48
+ request: (args: RequestArguments) => Promise<unknown>;
49
+ sign?: (data: TransactionRequest) => Promise<Hex>;
50
+ };
51
+
52
+ type BridgeTransfer = {
53
+ type: BridgeType;
54
+ environment: Environment;
55
+ addressC: Address;
56
+ addressBtc: string;
57
+ amount: bigint;
58
+ symbol: string;
59
+ completedAt?: number;
60
+ error?: string;
61
+ bridgeFee: bigint;
62
+ sourceChain: Chain;
63
+ sourceStartedAt: number;
64
+ sourceTxHash: string;
65
+ sourceNetworkFee?: bigint;
66
+ sourceConfirmationCount: number;
67
+ requiredSourceConfirmationCount: number;
68
+ targetChain: Chain;
69
+ targetStartedAt?: number;
70
+ targetTxHash?: string;
71
+ targetNetworkFee?: bigint;
72
+ targetConfirmationCount: number;
73
+ requiredTargetConfirmationCount: number;
74
+ startBlockNumber?: bigint;
75
+ metadata?: Record<string, unknown>;
76
+ };
77
+
78
+ declare enum BridgeType {
79
+ CCTP = "cctp"
80
+ }
81
+ type FeeParams = {
82
+ asset: BridgeAsset;
83
+ amount: bigint;
84
+ sourceChain: Chain;
85
+ targetChain: Chain;
86
+ provider?: Provider;
87
+ };
88
+ type TransferParams = {
89
+ asset: BridgeAsset;
90
+ amount: bigint;
91
+ addressC: Address;
92
+ addressBtc: string;
93
+ sourceChain: Chain;
94
+ targetChain: Chain;
95
+ sourceProvider: Provider;
96
+ targetProvider?: Provider;
97
+ };
98
+ type TrackingParams = {
99
+ bridgeTransfer: BridgeTransfer;
100
+ sourceProvider?: Provider;
101
+ targetProvider?: Provider;
102
+ updateListener: (transfer: BridgeTransfer) => void;
103
+ };
104
+ type BridgeService = {
105
+ type: BridgeType;
106
+ config: BridgeConfig | null;
107
+ ensureHasConfig: () => Promise<void>;
108
+ updateConfig: () => Promise<void>;
109
+ getAssets: () => Promise<ChainAssetMap>;
110
+ getFees: (params: FeeParams) => Promise<AssetFeeMap>;
111
+ transferAsset: (params: TransferParams) => Promise<BridgeTransfer>;
112
+ trackTransfer: (transfer: TrackingParams) => {
113
+ cancel?: () => void;
114
+ result: Promise<BridgeTransfer>;
115
+ };
116
+ };
117
+ type BridgeServiceFactory = (environment: Environment) => BridgeService;
118
+
119
+ declare enum TokenType {
120
+ NATIVE = "native",
121
+ ERC20 = "erc20"
122
+ }
123
+ type Asset = {
124
+ type: TokenType;
125
+ address?: Address;
126
+ name: string;
127
+ symbol: string;
128
+ decimals: number;
129
+ };
130
+ type DestinationInfo = Record<number, BridgeType[]>;
131
+ type BridgeAsset = Asset & {
132
+ destinations: DestinationInfo;
133
+ };
134
+ type ChainAssetMap = Record<number, BridgeAsset[]>;
135
+ type AssetFeeMap = Record<Address, bigint>;
136
+
137
+ declare const createUnifiedBridgeService: ({ environment, disabledBridgeTypes }: BridgeServiceConfig) => {
138
+ bridges: Map<BridgeType, BridgeService>;
139
+ init: () => Promise<void>;
140
+ updateConfigs: () => Promise<void[]>;
141
+ getAssets: () => Promise<ChainAssetMap>;
142
+ getFees: (params: FeeParams) => Promise<AssetFeeMap>;
143
+ transferAsset: (params: TransferParams) => Promise<BridgeTransfer>;
144
+ trackTransfer: (params: TrackingParams) => {
145
+ cancel?: (() => void) | undefined;
146
+ result: Promise<BridgeTransfer>;
147
+ };
148
+ };
149
+
150
+ export { Asset, AssetFeeMap, BridgeAsset, BridgeConfig, BridgeService, BridgeServiceConfig, BridgeServiceFactory, BridgeTransfer, BridgeType, Chain, ChainAssetMap, DestinationInfo, Environment, FeeParams, Provider, TokenType, TrackingParams, TransferParams, createUnifiedBridgeService };
@@ -0,0 +1,150 @@
1
+ import { Address, TransactionRequest, Hex } from 'viem';
2
+
3
+ type Chain = {
4
+ chainName: string;
5
+ chainId: number;
6
+ rpcUrl: string;
7
+ utilityAddresses: {
8
+ multicall: Address;
9
+ };
10
+ networkToken: Asset;
11
+ };
12
+
13
+ type Token = {
14
+ address: Address;
15
+ name: string;
16
+ symbol: string;
17
+ decimals: number;
18
+ };
19
+ type ChainData = {
20
+ chainId: number;
21
+ domain: number;
22
+ tokenRouterAddress: Address;
23
+ messageTransmitterAddress: Address;
24
+ tokens: Token[];
25
+ };
26
+ type Config = ChainData[];
27
+
28
+ declare enum Environment {
29
+ PROD = "production",
30
+ TEST = "test"
31
+ }
32
+
33
+ type BridgeServiceConfig = {
34
+ environment: Environment;
35
+ disabledBridgeTypes?: BridgeType[];
36
+ };
37
+ type BridgeConfig = Config;
38
+
39
+ type RequestArguments = {
40
+ method: string;
41
+ params?: unknown[] | Record<string | number, unknown>;
42
+ };
43
+ type Provider = {
44
+ /**
45
+ * EIP-1193 compatible request method
46
+ * https://eips.ethereum.org/EIPS/eip-1193#request-1
47
+ */
48
+ request: (args: RequestArguments) => Promise<unknown>;
49
+ sign?: (data: TransactionRequest) => Promise<Hex>;
50
+ };
51
+
52
+ type BridgeTransfer = {
53
+ type: BridgeType;
54
+ environment: Environment;
55
+ addressC: Address;
56
+ addressBtc: string;
57
+ amount: bigint;
58
+ symbol: string;
59
+ completedAt?: number;
60
+ error?: string;
61
+ bridgeFee: bigint;
62
+ sourceChain: Chain;
63
+ sourceStartedAt: number;
64
+ sourceTxHash: string;
65
+ sourceNetworkFee?: bigint;
66
+ sourceConfirmationCount: number;
67
+ requiredSourceConfirmationCount: number;
68
+ targetChain: Chain;
69
+ targetStartedAt?: number;
70
+ targetTxHash?: string;
71
+ targetNetworkFee?: bigint;
72
+ targetConfirmationCount: number;
73
+ requiredTargetConfirmationCount: number;
74
+ startBlockNumber?: bigint;
75
+ metadata?: Record<string, unknown>;
76
+ };
77
+
78
+ declare enum BridgeType {
79
+ CCTP = "cctp"
80
+ }
81
+ type FeeParams = {
82
+ asset: BridgeAsset;
83
+ amount: bigint;
84
+ sourceChain: Chain;
85
+ targetChain: Chain;
86
+ provider?: Provider;
87
+ };
88
+ type TransferParams = {
89
+ asset: BridgeAsset;
90
+ amount: bigint;
91
+ addressC: Address;
92
+ addressBtc: string;
93
+ sourceChain: Chain;
94
+ targetChain: Chain;
95
+ sourceProvider: Provider;
96
+ targetProvider?: Provider;
97
+ };
98
+ type TrackingParams = {
99
+ bridgeTransfer: BridgeTransfer;
100
+ sourceProvider?: Provider;
101
+ targetProvider?: Provider;
102
+ updateListener: (transfer: BridgeTransfer) => void;
103
+ };
104
+ type BridgeService = {
105
+ type: BridgeType;
106
+ config: BridgeConfig | null;
107
+ ensureHasConfig: () => Promise<void>;
108
+ updateConfig: () => Promise<void>;
109
+ getAssets: () => Promise<ChainAssetMap>;
110
+ getFees: (params: FeeParams) => Promise<AssetFeeMap>;
111
+ transferAsset: (params: TransferParams) => Promise<BridgeTransfer>;
112
+ trackTransfer: (transfer: TrackingParams) => {
113
+ cancel?: () => void;
114
+ result: Promise<BridgeTransfer>;
115
+ };
116
+ };
117
+ type BridgeServiceFactory = (environment: Environment) => BridgeService;
118
+
119
+ declare enum TokenType {
120
+ NATIVE = "native",
121
+ ERC20 = "erc20"
122
+ }
123
+ type Asset = {
124
+ type: TokenType;
125
+ address?: Address;
126
+ name: string;
127
+ symbol: string;
128
+ decimals: number;
129
+ };
130
+ type DestinationInfo = Record<number, BridgeType[]>;
131
+ type BridgeAsset = Asset & {
132
+ destinations: DestinationInfo;
133
+ };
134
+ type ChainAssetMap = Record<number, BridgeAsset[]>;
135
+ type AssetFeeMap = Record<Address, bigint>;
136
+
137
+ declare const createUnifiedBridgeService: ({ environment, disabledBridgeTypes }: BridgeServiceConfig) => {
138
+ bridges: Map<BridgeType, BridgeService>;
139
+ init: () => Promise<void>;
140
+ updateConfigs: () => Promise<void[]>;
141
+ getAssets: () => Promise<ChainAssetMap>;
142
+ getFees: (params: FeeParams) => Promise<AssetFeeMap>;
143
+ transferAsset: (params: TransferParams) => Promise<BridgeTransfer>;
144
+ trackTransfer: (params: TrackingParams) => {
145
+ cancel?: (() => void) | undefined;
146
+ result: Promise<BridgeTransfer>;
147
+ };
148
+ };
149
+
150
+ export { Asset, AssetFeeMap, BridgeAsset, BridgeConfig, BridgeService, BridgeServiceConfig, BridgeServiceFactory, BridgeTransfer, BridgeType, Chain, ChainAssetMap, DestinationInfo, Environment, FeeParams, Provider, TokenType, TrackingParams, TransferParams, createUnifiedBridgeService };