import { Fragment , FunctionFragment , JsonFragment } from '@ethersproject/abi' ; import { utils } from 'ethers' ; export class Contract { private _address : string ; private _abi : Fragment [ ] ; private _functions : FunctionFragment [ ] ; get address ( ) { return this . _address ; } get abi ( ) { return this . _abi ; } get functions ( ) { return this . _functions ; } constructor ( address , abi ) { this . _address = address ; this . _abi = toFragment ( abi ) ; this . _functions = this . _abi . filter ( x => x . type === 'function' ) . map ( x => FunctionFragment . from ( x ) ) ; const callFunctions = this . _functions . filter ( x => x . stateMutability === 'pure' || x . stateMutability === 'view' ) ; for ( const callFunction of callFunctions ) { const { name } = callFunction ; const getCall = makeCallFunction ( this , name ) ; if ( ! this [ name ] ) { defineReadOnly ( this , name , getCall ) ; } } } [ method ] : any ; } function toFragment ( abi ) { return abi . map ( ( item ) => utils . Fragment . from ( item ) ) ; } function makeCallFunction ( contract , name ) { return ( ... params ) => { const { address } = contract ; const { inputs } = contract . functions . find ( f => f . name === name ) ; const { outputs } = contract . functions . find ( f => f . name === name ) ; return { contract : { address , } , name , inputs , outputs , params , } ; } ; } function defineReadOnly ( object , name , value ) { Object . defineProperty ( object , name , { enumerable : true , value , writable : false , } ) ; }