UNPKG

@atomiqlabs/chain-evm

Version:

EVM specific base implementation

186 lines (167 loc) 7.12 kB
import {BaseTokenType, BitcoinNetwork, BitcoinRpc, ChainData, ChainInitializer, ChainSwapType} from "@atomiqlabs/base"; import {JsonRpcApiProvider, JsonRpcProvider, WebSocketProvider} from "ethers"; import {EVMChainInterface, EVMConfiguration, EVMRetryPolicy} from "../../evm/chain/EVMChainInterface"; import {CitreaChainType} from "./CitreaChainType"; import {EVMChainEventsBrowser} from "../../evm/events/EVMChainEventsBrowser"; import {EVMSwapData} from "../../evm/swaps/EVMSwapData"; import {EVMSpvVaultData} from "../../evm/spv_swap/EVMSpvVaultData"; import {EVMSpvWithdrawalData} from "../../evm/spv_swap/EVMSpvWithdrawalData"; import {CitreaFees} from "./CitreaFees"; import {CitreaBtcRelay} from "./CitreaBtcRelay"; import {CitreaSwapContract} from "./CitreaSwapContract"; import {CitreaTokens} from "./CitreaTokens"; import {CitreaSpvVaultContract} from "./CitreaSpvVaultContract"; const CitreaChainIds = { MAINNET: null, TESTNET4: 5115 }; const CitreaContractAddresses = { MAINNET: { executionContract: "", swapContract: "", btcRelayContract: "", btcRelayDeploymentHeight: 0, spvVaultContract: "", spvVaultDeploymentHeight: 0, handlerContracts: { refund: { timelock: "" }, claim: { [ChainSwapType.HTLC]: "", [ChainSwapType.CHAIN_TXID]: "", [ChainSwapType.CHAIN]: "", [ChainSwapType.CHAIN_NONCED]: "" } } }, TESTNET4: { executionContract: "0x9e289512965A0842b342A6BB3F3c41F22a555Cfe", swapContract: "0xBbf7755b674dD107d59F0650D1A3fA9C60bf6Fe6", btcRelayContract: "0x00D122E9f9766cd81a38D2dd44f9AFfb94c67Af7", btcRelayDeploymentHeight: 12346223, spvVaultContract: "0x9Bf990C6088F716279797a602b05941c40591533", spvVaultDeploymentHeight: 12346223, handlerContracts: { refund: { timelock: "0x4699450973c21d6Fe09e36A8A475EaE4D78a3137" }, claim: { [ChainSwapType.HTLC]: "0x1120e1Eb3049148AeBEe497331774BfE1f6c174D", [ChainSwapType.CHAIN_TXID]: "0xf61D1da542111216337FeEA5586022130D468842", [ChainSwapType.CHAIN]: "0xBe8C784b03F0c6d54aC35a4D41bd6CF2EDb6e012", [ChainSwapType.CHAIN_NONCED]: "0x65faec5DC334bf2005eC2DFcf012da87a832f1F0" } } } }; export type CitreaAssetsType = BaseTokenType<"CBTC" | "USDC">; export const CitreaAssets: CitreaAssetsType = { CBTC: { address: "0x0000000000000000000000000000000000000000", decimals: 18, displayDecimals: 8 }, USDC: { address: "0x2C8abD2A528D19AFc33d2ebA507c0F405c131335", decimals: 6, displayDecimals: 6 } } as const; export type CitreaOptions = { rpcUrl: string | JsonRpcApiProvider, retryPolicy?: EVMRetryPolicy, chainType?: "MAINNET" | "TESTNET4", swapContract?: string, btcRelayContract?: string, btcRelayDeploymentHeight?: number, spvVaultContract?: string, spvVaultDeploymentHeight?: number, handlerContracts?: { refund?: { timelock?: string }, claim?: { [type in ChainSwapType]?: string } } fees?: CitreaFees, evmConfig?: Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag"> } export function initializeCitrea( options: CitreaOptions, bitcoinRpc: BitcoinRpc<any>, network: BitcoinNetwork ): ChainData<CitreaChainType> { if(options.chainType==null) { switch (network) { case BitcoinNetwork.TESTNET4: options.chainType = "TESTNET4"; break; case BitcoinNetwork.MAINNET: options.chainType = "MAINNET"; break; } } const defaultContractAddresses = CitreaContractAddresses[options.chainType]; const chainId = CitreaChainIds[options.chainType]; const provider = typeof(options.rpcUrl)==="string" ? ( options.rpcUrl.startsWith("ws") ? new WebSocketProvider(options.rpcUrl, {name: "Citrea", chainId}) : new JsonRpcProvider(options.rpcUrl, {name: "Citrea", chainId}) ): options.rpcUrl; const Fees = options.fees ?? new CitreaFees(provider, 2n * 1_000_000_000n, 100_000n); const chainInterface = new EVMChainInterface("CITREA", chainId, provider, { safeBlockTag: "latest", finalizedBlockTag: "safe", maxLogsBlockRange: options?.evmConfig?.maxLogsBlockRange ?? 950, maxLogTopics: options?.evmConfig?.maxLogTopics ?? 64, maxParallelLogRequests: options?.evmConfig?.maxParallelLogRequests ?? 5, maxParallelCalls: options?.evmConfig?.maxParallelCalls ?? 5, useAccessLists: options?.evmConfig?.useAccessLists, defaultAccessListAddresses: options?.evmConfig?.defaultAccessListAddresses }, options.retryPolicy, Fees); chainInterface.Tokens = new CitreaTokens(chainInterface); //Override with custom token module allowing l1 state diff based fee calculation const btcRelay = new CitreaBtcRelay( chainInterface, bitcoinRpc, network, options.btcRelayContract ?? defaultContractAddresses.btcRelayContract, options.btcRelayDeploymentHeight ?? defaultContractAddresses.btcRelayDeploymentHeight ); const swapContract = new CitreaSwapContract( chainInterface, btcRelay, options.swapContract ?? defaultContractAddresses.swapContract, { refund: { ...defaultContractAddresses.handlerContracts.refund, ...options?.handlerContracts?.refund }, claim: { ...defaultContractAddresses.handlerContracts.claim, ...options?.handlerContracts?.claim } } ); const spvVaultContract = new CitreaSpvVaultContract( chainInterface, btcRelay, bitcoinRpc, options.spvVaultContract ?? defaultContractAddresses.spvVaultContract, options.spvVaultDeploymentHeight ?? defaultContractAddresses.spvVaultDeploymentHeight ) const chainEvents = new EVMChainEventsBrowser(chainInterface, swapContract, spvVaultContract); return { chainId: "CITREA", btcRelay, chainInterface, swapContract, chainEvents, swapDataConstructor: EVMSwapData, spvVaultContract, spvVaultDataConstructor: EVMSpvVaultData, spvVaultWithdrawalDataConstructor: EVMSpvWithdrawalData } }; export type CitreaInitializerType = ChainInitializer<CitreaOptions, CitreaChainType, CitreaAssetsType>; export const CitreaInitializer: CitreaInitializerType = { chainId: "CITREA", chainType: null as CitreaChainType, initializer: initializeCitrea, tokens: CitreaAssets, options: null as CitreaOptions } as const;