import { TransactionRequest } from '@ethersproject/abstract-provider' import { BatchFunctionResult, FNSArgs, RawFunction } from '..' import { FNSJSError } from '../utils/errors' const raw = async ( { multicallWrapper }: FNSArgs<'multicallWrapper'>, ...items: BatchFunctionResult[] ) => { const rawDataArr: { to: string; data: string }[] = await Promise.all( items.map(({ args, raw: rawRef }, i: number) => { if (!rawRef) { throw new Error(`Function ${i} is not batchable`) } return rawRef(...args) }), ) const response = await multicallWrapper.raw(rawDataArr) return { ...response, passthrough: rawDataArr } } const decode = async ( { multicallWrapper }: FNSArgs<'multicallWrapper'>, data: string, passthrough: TransactionRequest & { passthrough?: any }[], ...items: BatchFunctionResult[] ): Promise => { const response = await multicallWrapper.decode(data, passthrough) if (!response) return const results = await Promise.allSettled( response.map((ret: any, i: number) => { if (passthrough[i].passthrough) { return items[i].decode( ret.returnData, passthrough[i].passthrough, ...items[i].args, ) } return items[i].decode(ret.returnData, ...items[i].args) }), ) const reducedResults = results.reduce<{ errors: any[] data: any[] }>( (acc, result) => { if (result.status === 'fulfilled') { return { ...acc, data: [...acc.data, result.value] } } const error = result.reason instanceof FNSJSError ? (result.reason as FNSJSError) : undefined const itemData = error?.data const itemErrors = error?.errors || [{ message: 'unknown_error' }] return { errors: [...acc.errors, ...itemErrors], data: [...acc.data, itemData], } }, { data: [], errors: [] }, ) if (reducedResults.errors.length) throw new FNSJSError({ data: reducedResults.data, errors: reducedResults.errors, }) return reducedResults.data } export default { raw, decode, }