import { first } from 'lodash-unified' ; import urlcat from 'urlcat' ; import BigNumber from 'bignumber.js' ; import { ChainId , getExplorerConstants , getITOConstants , isSameAddress } from '@masknet/web3-shared-evm' ; import { Interface } from '@ethersproject/abi' ; import ITO_ABI from '@masknet/web3-contracts/abis/ITO2.json' ; import type { PoolFromNetwork , JSON_PayloadFromChain } from '../../types' ; import { MSG_DELIMITER , ITO_CONTRACT_BASE_TIMESTAMP } from '../../constants' ; import { getTransactionReceipt } from '../../../../extension/background-script/EthereumService' ; import { checkAvailability } from './checkAvailability' ; const interFace = new Interface ( ITO_ABI ) ; export async function getAllPoolsAsSeller ( chainId , startBlock , endBlock , sellerAddress ) { const { EXPLORER_API , API_KEYS = [ ] } = getExplorerConstants ( chainId ) ; const { ITO2_CONTRACT_ADDRESS } = getITOConstants ( chainId ) ; if ( ! EXPLORER_API || ! ITO2_CONTRACT_ADDRESS || ! startBlock ) return [ ] ; const response = await fetch ( urlcat ( EXPLORER_API , { apikey : first ( API_KEYS ) , action : 'txlist' , module : 'account' , sort : 'desc' , startBlock , endBlock , address : ITO2_CONTRACT_ADDRESS , } ) ) ; if ( ! response . ok ) return [ ] ; type TxType = { hash : string ; input : string ; from : string ; to : string ; blockNumber : string ; } ; type FillPoolInputParam = { _end : BigNumber ; _exchange_addrs : string [ ] ; _hash : string ; _limit : BigNumber ; _message : string ; _qualification : string ; _ratios : BigNumber [ ] ; _start : BigNumber ; _token_addr : string ; _total_tokens : BigNumber ; _unlock_time : BigNumber ; } ; const payloadList = ( await response . json ( ) ) . result . reduce ( ( acc , cur ) => { if ( ! isSameAddress ( cur . from , sellerAddress ) ) return acc ; try { const decodedInputParam = interFace . decodeFunctionData ( 'fill_pool' , cur . input ) as unknown as FillPoolInputParam ; const [ sellerName = '' , message = '' , regions = '-' ] = decodedInputParam . _message . split ( MSG_DELIMITER ) ; const payload = { end_time : ( decodedInputParam . _end . toNumber ( ) + ITO_CONTRACT_BASE_TIMESTAMP / 1000 ) * 1000 , exchange_token_addresses : decodedInputParam . _exchange_addrs , limit : decodedInputParam . _limit . toString ( ) , message , qualification_address : decodedInputParam . _qualification , exchange_amounts : decodedInputParam . _ratios . map ( ( v ) => v . toString ( ) ) , start_time : ( decodedInputParam . _start . toNumber ( ) + ITO_CONTRACT_BASE_TIMESTAMP / 1000 ) * 1000 , token_address : decodedInputParam . _token_addr , total : decodedInputParam . _total_tokens . toString ( ) , unlock_time : ( decodedInputParam . _unlock_time . toNumber ( ) + ITO_CONTRACT_BASE_TIMESTAMP / 1000 ) * 1000 , seller : { address : cur . from , name : sellerName , } , contract_address : cur . to , chain_id : chainId , regions , block_number : Number ( cur . blockNumber ) , pid : '' , creation_time : 0 , total_remaining : '' , password : '' , } ; return acc . concat ( { payload , hash : cur . hash } ) ; } catch { return acc ; } } , [ ] ) ; type FillPoolSuccessEventParams = { id : string ; creation_time : BigNumber ; } ; const eventLogResponse = await Promise . allSettled ( payloadList . map ( async ( entity ) => { const result = await getTransactionReceipt ( entity . hash ) ; if ( ! result ) return null ; const log = result . logs . find ( ( log ) => isSameAddress ( log . address , ITO2_CONTRACT_ADDRESS ) ) ; if ( ! log ) return null ; const eventParams = interFace . decodeEventLog ( 'FillSuccess' , log . data , log . topics ) as unknown as FillPoolSuccessEventParams ; entity . payload . pid = eventParams . id ; entity . payload . creation_time = eventParams . creation_time . toNumber ( ) ; const data = await checkAvailability ( entity . payload . pid , entity . payload . seller . address , entity . payload . contract_address , chainId ) ; entity . payload . total_remaining = new BigNumber ( data . remaining ) . toString ( ) ; return { pool : entity . payload , exchange_in_volumes : data . exchanged_tokens , exchange_out_volumes : [ ] , } ; } ) ) ; return eventLogResponse . map ( ( v ) => ( v . status === 'fulfilled' && v . value ? v . value : null ) ) . filter ( ( v ) => Boolean ( v ) ) as PoolFromNetwork [ ] ; }