import { ethers } from 'ethers' ; import chunk from 'lodash/chunk' ; import { PARAMETER_SHORT_TYPES } from './utils' ; import { ABIParameterType , ABIParameterTypeShort , DecodedMap } from './types' ; type TransformationReference = { readonly [ key ] : ( value : any ) => string ; } ; const TRANSFORMATIONS = { bytes32 : ethers . utils . parseBytes32String , int256 : ( value ) => value . toString ( ) , uint256 : ( value ) => value . toString ( ) , } ; function buildDecodedMap ( types , nameValuePairs ) { return nameValuePairs . reduce ( ( acc , pair , index ) => { const [ encodedName , encodedValue ] = pair ; const name = ethers . utils . parseBytes32String ( encodedName ) ; const type = types [ index ] ; const transform = TRANSFORMATIONS [ type ] ; if ( ! transform ) { return { ... acc , [ name ] : encodedValue } ; } const parsedValue = transform ( encodedValue ) ; return { ... acc , [ name ] : parsedValue } ; } , { } ) ; } export function decode ( encodedData ) { if ( encodedData === '0x' ) { return { } ; } const header = ethers . utils . hexlify ( ethers . utils . arrayify ( encodedData ) . slice ( 0 , 32 ) ) ; const parsedHeader = ethers . utils . parseBytes32String ( header ) ; const encodedEncodingVersion = parsedHeader . substring ( 0 , 1 ) ; if ( encodedEncodingVersion !== '1' ) { throw new Error ( `Unknown ABI schema version: ${ encodedEncodingVersion }` ) ; } const encodedParameterTypes = parsedHeader . substring ( 1 ) ; const fullParameterTypes = Array . from ( encodedParameterTypes ) . map ( ( type ) => PARAMETER_SHORT_TYPES [ type as ABIParameterTypeShort ] ) ; const initialDecodedTypes = [ 'bytes32' ] ; const decodingTypes = fullParameterTypes . reduce ( ( acc , type ) => { return [ ... acc , 'bytes32' as const , type ] ; } , initialDecodedTypes ) ; const decodedData = ethers . utils . defaultAbiCoder . decode ( decodingTypes , encodedData ) ; const [ _version , ... decodedParameters ] = decodedData ; const nameValuePairs = chunk ( decodedParameters , 2 ) as [ string , string ] [ ] ; return buildDecodedMap ( fullParameterTypes , nameValuePairs ) ; }