UNPKG

@0xsplits/splits-sdk

Version:

SDK for the 0xSplits protocol

531 lines (488 loc) 15.2 kB
import { Address, GetLogsReturnType } from 'viem' import { SplitV2Type } from '../types' import { splitMainPolygonAbi } from './abi/splitMain' import { splitV2ABI } from './abi/splitV2' import { splitV2FactoryABI } from './abi/splitV2Factory' import { InvalidArgumentError } from '../errors' export const PERCENTAGE_SCALE = BigInt(1e6) // https://github.com/mds1/multicall export const MULTICALL_3_ADDRESS = '0xca11bde05977b3631167028862be2a173976ca11' export const REVERSE_RECORDS_ADDRESS = '0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C' const SPLIT_MAIN_ADDRESS = '0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE' const VESTING_MODULE_FACTORY_ADDRESS = '0x0a2841630f198745a55c4dab3fe98f77271949e5' const WATERFALL_MODULE_FACTORY_ADDRESS = '0x4Df01754eBd055498C8087b1e9a5c7a9ad19b0F6' const LIQUID_SPLIT_FACTORY_ADDRESS = '0xdEcd8B99b7F763e16141450DAa5EA414B7994831' const RECOUP_ADDRESS = '0xCbB386B801Ec72A5aB02AEB723dECd12f96EdE41' const PASS_THROUGH_WALLET_FACTORY_ADDRESS_MAINNET = '0xF5aCC1568706Fbf9A55a77DdBe8DF907Da95dD6B' const PASS_THROUGH_WALLET_FACTORY_ADDRESS = '0x52d6838957ec268cc5B50F17F9b490cbAb0A9E40' const SWAPPER_FACTORY_ADDRESS = '0xa244bbe019cf1BA177EE5A532250be2663Fb55cA' const UNI_V3_SWAP_ADDRESS = '0x981a6aC55c7D39f50666938CcD0df53D59797e87' // Keep in sync with subgraph const DIVERSIFIER_FACTORY_ADDRESS_MAINNET = '0x78791997483f25217F4C3FE2a568Fe3eFaf77884' const DIVERSIFIER_FACTORY_ADDRESS = '0x1f3f5C7342Ae19E2b35b657864106f227201eF8A' const SPLIT_MAIN_ADDRESS_BSC = '0x5924cD81dC672151527B1E4b5Ef57B69cBD07Eda' const VESTING_MODULE_FACTORY_ADDRESS_BSC = '0x7205d93721837c45Be23C930D9fba842e968Ad69' const WATERFALL_MODULE_FACTORY_ADDRESS_BSC = '0xB7CCCcCeb459F0910589556123dC5fA6DC8dE4E0' const LIQUID_SPLIT_FACTORY_ADDRESS_BSC = '0xCDe071bE119024EdC970B3Da15003ee834ae40D2' const RECOUP_ADDRESS_BSC = '0x5ff0C88311F79803B43e9Dc3F2B20F49A6b680fd' const SPLIT_MAIN_ADDRESS_HOLESKY = '0xfC8a305728051367797DADE6Aa0344E0987f5286' const LIQUID_SPLIT_FACTORY_ADDRESS_HOLESKY = '0xAbA0E852f1EB10196b55f877903A87a2588b7aa8' const RECOUP_ADDRESS_HOLESKY = '0xcFba37C5Ee4d80c286593342470EB881deb9799e' const SPLIT_MAIN_ADDRESS_SEPOLIA = '0x54E4a6014D36c381fC43b7E24A1492F556139a6F' const LIQUID_SPLIT_FACTORY_ADDRESS_SEPOLIA = '0xb3Af150A5902e06373A2D3f177d85435A48c6b33' const RECOUP_ADDRESS_SEPOLIA = '0x8Cbb4e187ce8A29BACC13Fd999a107f3c4b46D3B' const DIVERSIFIER_FACTORY_ADDRESS_SEPOLIA = '0x0eAeAfD1c82563B6005c7D09031462D9FF68Adab' const WAREHOUSE_ADDRESS = '0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8' export const PULL_SPLIT_FACTORY_ADDRESS = '0x80f1B766817D04870f115fEBbcCADF8DBF75E017' export const PUSH_SPLIT_FACTORY_ADDRESS = '0xaDC87646f736d6A82e9a6539cddC488b2aA07f38' export const PULL_SPLIT_V2o1_FACTORY_ADDRESS = '0x5cbA88D55Cec83caD5A105Ad40C8c9aF20bE21d1' export const PUSH_SPLIT_V2o1_FACTORY_ADDRESS = '0xDc6259E13ec0621e6F19026b2e49D846525548Ed' export const PULL_SPLIT_V2o1_ADDRESS = '0xF9C25250523Df26343222fC46de932355B850c97' export const PUSH_SPLIT_V2o1_ADDRESS = '0x3f81D81e0884abD8Cc4583a704a9397972623214' export const getSplitMainAddress = (chainId: number): Address => { if (chainId === ChainId.BSC) return SPLIT_MAIN_ADDRESS_BSC if (chainId === ChainId.HOLESKY) return SPLIT_MAIN_ADDRESS_HOLESKY if (chainId === ChainId.SEPOLIA) return SPLIT_MAIN_ADDRESS_SEPOLIA return SPLIT_MAIN_ADDRESS } export const getVestingFactoryAddress = (chainId: number): Address => { if (chainId === ChainId.BSC) return VESTING_MODULE_FACTORY_ADDRESS_BSC return VESTING_MODULE_FACTORY_ADDRESS } export const getWaterfallFactoryAddress = (chainId: number): Address => { if (chainId === ChainId.BSC) return WATERFALL_MODULE_FACTORY_ADDRESS_BSC return WATERFALL_MODULE_FACTORY_ADDRESS } export const getLiquidSplitFactoryAddress = (chainId: number): Address => { if (chainId === ChainId.BSC) return LIQUID_SPLIT_FACTORY_ADDRESS_BSC if (chainId === ChainId.HOLESKY) return LIQUID_SPLIT_FACTORY_ADDRESS_HOLESKY if (chainId === ChainId.SEPOLIA) return LIQUID_SPLIT_FACTORY_ADDRESS_SEPOLIA return LIQUID_SPLIT_FACTORY_ADDRESS } export const getRecoupAddress = (chainId: number): Address => { if (chainId === ChainId.BSC) return RECOUP_ADDRESS_BSC if (chainId === ChainId.HOLESKY) return RECOUP_ADDRESS_HOLESKY if (chainId === ChainId.SEPOLIA) return RECOUP_ADDRESS_SEPOLIA return RECOUP_ADDRESS } export const getPassThroughWalletFactoryAddress = ( chainId: number, ): Address => { if (chainId == ChainId.MAINNET) return PASS_THROUGH_WALLET_FACTORY_ADDRESS_MAINNET return PASS_THROUGH_WALLET_FACTORY_ADDRESS } export const getSwapperFactoryAddress = (): Address => { return SWAPPER_FACTORY_ADDRESS } /** * @param chainId - The chain ID to get the UniV3Swap address for. * @returns The UniV3Swap address for the given chain ID. * @dev It is recommended to pass in the chainId. */ export const getUniV3SwapAddress = (chainId?: number): Address => { if (!chainId) return UNI_V3_SWAP_ADDRESS if (!PERMISSIONLESS_SWAPPER_CHAIN_IDS.includes(chainId)) throw new InvalidArgumentError( `Chain - ${chainId} is not supported for permissionless swaps`, ) if (chainId === ChainId.POLYGON) return '0x8d582AEDf0326348960054021ab0b748B3A2BA66' if (chainId === ChainId.OPTIMISM) return '0x8d582AEDf0326348960054021ab0b748B3A2BA66' return UNI_V3_SWAP_ADDRESS } export const getDiversifierFactoryAddress = (chainId: number): Address => { if (chainId === ChainId.MAINNET) return DIVERSIFIER_FACTORY_ADDRESS_MAINNET if (chainId === ChainId.SEPOLIA) return DIVERSIFIER_FACTORY_ADDRESS_SEPOLIA return DIVERSIFIER_FACTORY_ADDRESS } export const getWarehouseAddress = (): Address => { return WAREHOUSE_ADDRESS } export const getSplitV2FactoryAddress = ( _chainId: number, type: SplitV2Type, ): Address => { if (type === SplitV2Type.Pull) return PULL_SPLIT_FACTORY_ADDRESS else return PUSH_SPLIT_FACTORY_ADDRESS } export const getSplitV2o1FactoryAddress = ( _chainId: number, type: SplitV2Type, ): Address => { if (type === SplitV2Type.Pull) return PULL_SPLIT_V2o1_FACTORY_ADDRESS else return PUSH_SPLIT_V2o1_FACTORY_ADDRESS } export const getSplitV1StartBlock = (chainId: number): bigint => { if (!CHAIN_INFO[chainId].startBlock) throw new Error('Chain not supported') return BigInt(CHAIN_INFO[chainId].startBlock as number) } export const getSplitV2FactoriesStartBlock = (chainId: number): bigint => { if (!CHAIN_INFO[chainId].startBlockV2) throw new Error('Chain not supported') return BigInt(CHAIN_INFO[chainId].startBlockV2 as number) } export enum ChainId { MAINNET = 1, SEPOLIA = 11155111, HOLESKY = 17000, HOODI = 560048, POLYGON = 137, OPTIMISM = 10, OPTIMISM_SEPOLIA = 11155420, ARBITRUM = 42161, GNOSIS = 100, BSC = 56, ZORA = 7777777, ZORA_SEPOLIA = 999999999, BASE = 8453, BASE_SEPOLIA = 84532, FOUNDRY = 31337, BLAST = 81457, SHAPE = 360, WORLDCHAIN = 480, PLUME = 98866, PLUME_TESTNET = 98867, } export const ETHEREUM_CHAIN_IDS = [ChainId.MAINNET] export const ETHEREUM_TEST_CHAIN_IDS = [ ChainId.SEPOLIA, ChainId.HOLESKY, ChainId.HOODI, ] export const POLYGON_CHAIN_IDS = [ChainId.POLYGON] export const OPTIMISM_CHAIN_IDS = [ChainId.OPTIMISM, ChainId.OPTIMISM_SEPOLIA] export const ARBITRUM_CHAIN_IDS = [ChainId.ARBITRUM] export const GNOSIS_CHAIN_IDS = [ChainId.GNOSIS] export const BSC_CHAIN_IDS = [ChainId.BSC] export const ZORA_CHAIN_IDS = [ChainId.ZORA, ChainId.ZORA_SEPOLIA] export const BASE_CHAIN_IDS = [ChainId.BASE, ChainId.BASE_SEPOLIA] export const BLAST_CHAIN_IDS = [ChainId.BLAST] export const SHAPE_CHAIN_IDS = [ChainId.SHAPE] export const WORLD_CHAIN_IDS = [ChainId.WORLDCHAIN] export const PLUME_CHAIN_IDS = [ChainId.PLUME, ChainId.PLUME_TESTNET] export const ALL_CHAIN_IDS = [ ...ETHEREUM_CHAIN_IDS, ...ETHEREUM_TEST_CHAIN_IDS, ...POLYGON_CHAIN_IDS, ...OPTIMISM_CHAIN_IDS, ...ARBITRUM_CHAIN_IDS, ...GNOSIS_CHAIN_IDS, ...BSC_CHAIN_IDS, ...ZORA_CHAIN_IDS, ...BASE_CHAIN_IDS, ...BLAST_CHAIN_IDS, ...SHAPE_CHAIN_IDS, ...WORLD_CHAIN_IDS, ...PLUME_CHAIN_IDS, ] export const SPLITS_SUPPORTED_CHAIN_IDS = [ 3, 4, 42, ...ETHEREUM_CHAIN_IDS, ChainId.SEPOLIA, ChainId.HOLESKY, ...POLYGON_CHAIN_IDS, ...OPTIMISM_CHAIN_IDS, ...ARBITRUM_CHAIN_IDS, ...GNOSIS_CHAIN_IDS, ...BSC_CHAIN_IDS, ...ZORA_CHAIN_IDS, ...BASE_CHAIN_IDS, ...BLAST_CHAIN_IDS, ] export const SPLITS_V2_SUPPORTED_CHAIN_IDS = [ ChainId.MAINNET, ChainId.OPTIMISM, ChainId.BASE, ChainId.ZORA, ChainId.POLYGON, ChainId.ARBITRUM, ChainId.SEPOLIA, ChainId.HOLESKY, ChainId.HOODI, ChainId.BASE_SEPOLIA, ChainId.ZORA_SEPOLIA, ChainId.OPTIMISM_SEPOLIA, ChainId.FOUNDRY, ChainId.GNOSIS, ChainId.BSC, ChainId.SHAPE, ChainId.WORLDCHAIN, ChainId.PLUME, ChainId.PLUME_TESTNET, ] // These chains use a different value for block.number than the actual block number // for the transaction. This breaks the regular flow in the SDK for the splitV2o1 // contract. Need to fall back to the regular logs flow for these chains. export const INVALID_BLOCK_NUMBER_CHAIN_IDS = [ ChainId.ARBITRUM, ChainId.PLUME, ChainId.PLUME_TESTNET, ] export const SPLITS_SUBGRAPH_CHAIN_IDS = [ ChainId.MAINNET, ChainId.OPTIMISM, ChainId.BASE, ChainId.ZORA, ChainId.POLYGON, ChainId.ARBITRUM, ChainId.GNOSIS, ChainId.BSC, ChainId.BLAST, ChainId.HOLESKY, ChainId.SEPOLIA, ChainId.BASE_SEPOLIA, ] export const WATERFALL_CHAIN_IDS = ALL_CHAIN_IDS.slice().filter( (id) => id !== ChainId.ZORA_SEPOLIA && id !== ChainId.BASE_SEPOLIA && id !== ChainId.BLAST, ) export const LIQUID_SPLIT_CHAIN_IDS = ALL_CHAIN_IDS.slice().filter( (id) => id !== ChainId.ZORA_SEPOLIA && id !== ChainId.BASE_SEPOLIA && id !== ChainId.BLAST, ) export const VESTING_CHAIN_IDS = ALL_CHAIN_IDS.slice().filter( (id) => id !== ChainId.ZORA_SEPOLIA && id !== ChainId.BASE_SEPOLIA && id !== ChainId.BLAST, ) export const TEMPLATES_CHAIN_IDS = ALL_CHAIN_IDS.slice().filter( (id) => id !== ChainId.ZORA_SEPOLIA && id !== ChainId.BASE_SEPOLIA && id !== ChainId.BLAST, ) export const SWAPPER_CHAIN_IDS = [ ChainId.MAINNET, ChainId.SEPOLIA, ChainId.BASE, ChainId.POLYGON, ChainId.OPTIMISM, ChainId.ARBITRUM, ] export const PERMISSIONLESS_SWAPPER_CHAIN_IDS = [ ChainId.MAINNET, ChainId.POLYGON, ChainId.OPTIMISM, ChainId.ARBITRUM, ] export const PASS_THROUGH_WALLET_CHAIN_IDS = SWAPPER_CHAIN_IDS.slice() export const ORACLE_CHAIN_IDS = SWAPPER_CHAIN_IDS.slice() export const DIVERSIFIER_CHAIN_IDS = SWAPPER_CHAIN_IDS.slice() export const SPLITS_MAX_PRECISION_DECIMALS = 4 export const LIQUID_SPLITS_MAX_PRECISION_DECIMALS = 1 export const LIQUID_SPLIT_NFT_COUNT = 1000 export const LIQUID_SPLIT_URI_BASE_64_HEADER = 'data:application/json;base64,' export const CHAIN_INFO: { [chainId: number]: { startBlock: number wrappedNativeTokenAddress?: Address nativeCurrency: { symbol: string } startBlockV2?: number } } = { [ChainId.MAINNET]: { startBlock: 14206768, nativeCurrency: { symbol: 'ETH', }, wrappedNativeTokenAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', startBlockV2: 19451952, }, [ChainId.SEPOLIA]: { startBlock: 4836125, nativeCurrency: { symbol: 'ETH', }, wrappedNativeTokenAddress: '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14', startBlockV2: 5467056, }, [ChainId.HOLESKY]: { startBlock: 148241, nativeCurrency: { symbol: 'ETH', }, startBlockV2: 1121603, }, [ChainId.HOODI]: { startBlock: 106772, nativeCurrency: { symbol: 'ETH', }, startBlockV2: 106772, }, [ChainId.POLYGON]: { startBlock: 25303316, nativeCurrency: { symbol: 'MATIC', }, wrappedNativeTokenAddress: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', startBlockV2: 54572664, }, [ChainId.OPTIMISM]: { startBlock: 24704537, nativeCurrency: { symbol: 'ETH', }, wrappedNativeTokenAddress: '0x4200000000000000000000000000000000000006', startBlockV2: 117327692, }, [ChainId.ARBITRUM]: { startBlock: 26082503, nativeCurrency: { symbol: 'ETH', }, wrappedNativeTokenAddress: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', startBlockV2: 189649987, }, [ChainId.GNOSIS]: { startBlock: 26014830, nativeCurrency: { symbol: 'xDai', }, startBlockV2: 33277147, }, [ChainId.BSC]: { startBlock: 24962607, nativeCurrency: { symbol: 'BNB', }, startBlockV2: 37570236, }, [ChainId.ZORA]: { startBlock: 1860322, nativeCurrency: { symbol: 'ETH', }, startBlockV2: 11780035, }, [ChainId.ZORA_SEPOLIA]: { startBlock: 2296044, nativeCurrency: { symbol: 'ETH', }, startBlockV2: 6062586, }, [ChainId.BASE]: { startBlock: 2293907, nativeCurrency: { symbol: 'ETH', }, wrappedNativeTokenAddress: '0x4200000000000000000000000000000000000006', startBlockV2: 11732477, }, [ChainId.BASE_SEPOLIA]: { startBlock: 3324413, nativeCurrency: { symbol: 'ETH', }, startBlockV2: 7243250, }, [ChainId.BLAST]: { startBlock: 220516, nativeCurrency: { symbol: 'ETH', }, }, [ChainId.SHAPE]: { startBlock: 5448039, nativeCurrency: { symbol: 'ETH', }, startBlockV2: 5448039, }, [ChainId.WORLDCHAIN]: { startBlock: 9116639, nativeCurrency: { symbol: 'ETH', }, startBlockV2: 9116639, }, [ChainId.PLUME]: { startBlock: 865172, nativeCurrency: { symbol: 'PLUME', }, startBlockV2: 865172, }, [ChainId.PLUME_TESTNET]: { startBlock: 1759, nativeCurrency: { symbol: 'PLUME', }, startBlockV2: 1759, }, } export enum TransactionType { Transaction = 'Transaction', CallData = 'CallData', GasEstimate = 'GasEstimate', Signature = 'Signature', } export const ZERO = BigInt(0) export const ONE = BigInt(1) export const TWO = BigInt(2) export const NATIVE_TOKEN_ADDRESS: Address = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' export const splitV1UpdatedEvent = splitMainPolygonAbi[18] export const splitV1CreatedEvent = splitMainPolygonAbi[14] type SplitV1UpdatedEventType = typeof splitV1UpdatedEvent export type SplitV1UpdatedLogType = GetLogsReturnType< SplitV1UpdatedEventType, [SplitV1UpdatedEventType], true, bigint, bigint >[0] type SplitV1CreatedEventType = typeof splitV1CreatedEvent export type SplitV1CreatedLogType = GetLogsReturnType< SplitV1CreatedEventType, [SplitV1CreatedEventType], true, bigint, bigint >[0] export const splitV2UpdatedEvent = splitV2ABI[28] export const splitV2CreatedEvent = splitV2FactoryABI[8] type SplitV2UpdatedEventType = typeof splitV2UpdatedEvent export type SplitV2UpdatedLogType = GetLogsReturnType< SplitV2UpdatedEventType, [SplitV2UpdatedEventType], true, bigint, bigint >[0] type SplitV2CreatedEventType = typeof splitV2CreatedEvent export type SplitV2CreatedLogType = GetLogsReturnType< SplitV2CreatedEventType, [SplitV2CreatedEventType], true, bigint, bigint >[0]