UNPKG

@velora-dex/sdk

Version:
190 lines (171 loc) 6.42 kB
import { assert } from 'ts-essentials'; import { ZERO_ADDRESS } from '../../common/orders/buildOrderData'; import { BeneficiaryType } from '../../common/orders/types'; import { Bridge } from './types'; export const ACROSS_WETH_ADDRESSES_MAP: Record<number, string> = { // Mainnet 1: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // Sepolia 11155111: '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14', // Base 8453: '0x4200000000000000000000000000000000000006', // Base Sepolia 84532: '0x4200000000000000000000000000000000000006', // Optimism 10: '0x4200000000000000000000000000000000000006', // Optimism Sepolia 11155420: '0x4200000000000000000000000000000000000006', // Polygon 137: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', // Polygon Amoy 80002: '0x52eF3d68BaB452a294342DC3e5f464d7f610f72E', // Aleph Zero 41455: '0xB3f0eE446723f4258862D949B4c9688e7e7d35d3', // Arbitrum 42161: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', // Arbitrum Sepolia 421614: '0x980B62Da83eFf3D4576C647993b0c1D7faf17c73', // Boba 288: '0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000', // Blast 81457: '0x4300000000000000000000000000000000000004', // Blast Sepolia 168587773: '0x4200000000000000000000000000000000000023', // BSC 56: '0x2170Ed0880ac9A755fd29B2688956BD959F933F8', // Ink 57073: '0x4200000000000000000000000000000000000006', // Ink Sepolia 763373: '0x4200000000000000000000000000000000000006', // Lens 232: '0xE5ecd226b3032910CEaa43ba92EE8232f8237553', // Lens Sepolia 37111: '0xaA91D645D7a6C1aeaa5988e0547267B77d33fe16', // Linea 59144: '0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f', // Lisk 1135: '0x4200000000000000000000000000000000000006', // Lisk Sepolia 4202: '0x4200000000000000000000000000000000000006', // Mode 34443: '0x4200000000000000000000000000000000000006', // Mode Sepolia 919: '0x4200000000000000000000000000000000000006', // Redstone 690: '0x4200000000000000000000000000000000000006', // Scroll 534352: '0x5300000000000000000000000000000000000004', // Scroll Sepolia 534351: '0x5300000000000000000000000000000000000004', // Soneium 1868: '0x4200000000000000000000000000000000000006', // Tatara 129399: '0x17B8Ee96E3bcB3b04b3e8334de4524520C51caB4', // Unichain 130: '0x4200000000000000000000000000000000000006', // Unichain Sepolia 1301: '0x4200000000000000000000000000000000000006', // World Chain 480: '0x4200000000000000000000000000000000000006', // ZK Sync 324: '0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91', // ZK Sync Sepolia 300: '0x2D6Db36B3117802E996f13073A08A685D3FeF7eD', // Zora 7777777: '0x4200000000000000000000000000000000000006', }; export function isAcrossWETH(tokenAddress: string, chainId: number) { return ( ACROSS_WETH_ADDRESSES_MAP[chainId]?.toLowerCase() === tokenAddress.toLowerCase() ); } const ETH_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; const ETH_ADDRESS_LOWERCASE = ETH_ADDRESS.toLowerCase() as Lowercase< typeof ETH_ADDRESS >; export function isETHaddress(tokenAddress: string): boolean { return tokenAddress.toLowerCase() === ETH_ADDRESS_LOWERCASE; } // WETH > ETH Across logic // https://docs.across.to/introduction/technical-faq#what-is-the-behavior-of-eth-weth-in-transfers // Velora API ref // https://developers.velora.xyz/api/velora-api/velora-delta-api/build-a-delta-order-to-sign export type GetDeltaBridgeAndDestTokenInput = { destTokenDestChain: string; // the token user wants to ultimately receive destChainId: number; bridgeFee: string; bridgeOutputToken: string; // the token on the destination chain, in case of WETH -> ETH, will be different from destTokenDestChain and unwrapped beneficiaryType: BeneficiaryType; getMulticallHandler: (chainId: number) => Promise<string>; }; export type GetDeltaBridgeAndDestTokenOutput = { /** @description The bridge object to be used for Order.bridge */ bridge: Bridge; }; export async function getDeltaBridge({ destTokenDestChain, destChainId, bridgeFee, bridgeOutputToken, beneficiaryType, getMulticallHandler, }: GetDeltaBridgeAndDestTokenInput): Promise<GetDeltaBridgeAndDestTokenOutput> { assert( beneficiaryType === 'EOA' || beneficiaryType === 'SmartContract', 'beneficiaryType must be EOA or SmartContract' ); const outputToken = bridgeOutputToken.toLowerCase(); // for uniformity let multiCallHandler: string = ZERO_ADDRESS; if (beneficiaryType === 'EOA' && isETHaddress(destTokenDestChain)) { /* if beneficiary is an EOA and destToken on destChain = ETH order.destToken=ETH (deltaPrice already contains correct destToken) order.bridge.outputToken=WETH_DEST_CHAIN (deltaPrice already contains correct bridge.outputToken) order.bridge.multiCallHandler=NULL_ADDRESS */ multiCallHandler = ZERO_ADDRESS; } if ( beneficiaryType === 'EOA' && isAcrossWETH(destTokenDestChain, destChainId) ) { /* if beneficiary is an EOA and destToken on destChain = WETH order.destToken=WETH (deltaPrice already contains correct destToken) order.bridge.outputToken=WETH_DEST_CHAIN (deltaPrice already contains correct bridge.outputToken) order.bridge.multiCallHandler=MULTI_CALL_HANDLER */ multiCallHandler = await getMulticallHandler(destChainId); } if (beneficiaryType === 'SmartContract' && isETHaddress(destTokenDestChain)) { /* if beneficiary is a contract and destToken on destChain = ETH order.destToken=ETH (deltaPrice already contains correct destToken) order.bridge.outputToken=WETH_DEST_CHAIN (deltaPrice already contains correct bridge.outputToken) order.bridge.multiCallHandler=MULTI_CALL_HANDLER */ multiCallHandler = await getMulticallHandler(destChainId); } if ( beneficiaryType === 'SmartContract' && isAcrossWETH(destTokenDestChain, destChainId) ) { /* if beneficiary is a contract and destToken on destChain = WETH order.destToken=WETH (deltaPrice already contains correct destToken) order.bridge.outputToken=WETH_DEST_CHAIN (deltaPrice already contains correct bridge.outputToken) order.bridge.multiCallHandler=NULL_ADDRESS */ multiCallHandler = ZERO_ADDRESS; } const bridge: Bridge = { maxRelayerFee: bridgeFee, destinationChainId: destChainId, outputToken, multiCallHandler, }; return { bridge, }; }