import { values } from 'lodash' ; import { Contract , FunctionDeclaration , FunctionDocumentation , getSignatureForFn , isConstant , isConstantFn , } from 'typechain' ; import { codegenAllPossibleEvents , codegenEventsDeclarations } from './events' ; import { codegenInputTypes , codegenOutputTypes } from './types' ; export function codegenContract ( contract ) { return `
import BN from "bn.js";
import { EventData, PastEventOptions } from "web3-eth-contract"

${ codegenContractInterface ( contract ) }

${ codegenEventsDeclarations ( contract ) }
${ codegenAllPossibleEvents ( contract ) }

${ codegenContractInstanceInterface ( contract ) }
  ` ; } function codegenContractInterface ( c ) { return `
export interface ${ c . name }Contract extends Truffle.Contract<${ c . name }Instance> {
  ${ c . constructor [ 0 ] ? `"new"(${ codegenInputTypes ( c . constructor [ 0 ] . inputs ) } meta?: Truffle.TransactionDetails): Promise<${ c . name }Instance>;` : `"new"(meta?: Truffle.TransactionDetails): Promise<${ c . name }Instance>;` }
}
` ; } function codegenContractInstanceInterface ( c ) { const functionsCode = values ( c . functions ) . filter ( ( v ) => v . length === 1 ) . map ( ( v ) => v [ 0 ] ) . map ( ( fn ) => generateFunction ( fn ) ) . join ( '\n' ) ; return `
export interface ${ c . name }Instance extends Truffle.ContractInstance {
  ${ functionsCode }

  methods: {
    ${ functionsCode }
    ${ values ( c . functions ) . filter ( ( v ) => v . length > 1 ) . map ( generateOverloadedFunctions ) . join ( '\n' ) }
  }

  getPastEvents(event: string): Promise<EventData[]>;
  getPastEvents(
      event: string,
      options: PastEventOptions,
      callback: (error: Error, event: EventData) => void
  ): Promise<EventData[]>;
  getPastEvents(event: string, options: PastEventOptions): Promise<EventData[]>;
  getPastEvents(
      event: string,
      callback: (error: Error, event: EventData) => void
  ): Promise<EventData[]>;
}
  ` ; } function generateFunction ( fn , overloadedName ? ) { if ( isConstant ( fn ) || isConstantFn ( fn ) ) { return generateConstantFunction ( fn , overloadedName ) ; } return `
  ${ generateFunctionDocumentation ( fn . documentation ) }
  ${ overloadedName ?? fn . name }: {
    (${ codegenInputTypes ( fn . inputs ) } txDetails?: Truffle.TransactionDetails): Promise<Truffle.TransactionResponse<AllEvents>>;
  call(${ codegenInputTypes ( fn . inputs ) } txDetails?: Truffle.TransactionDetails): Promise<${ codegenOutputTypes ( fn . outputs ) }>;
  sendTransaction(${ codegenInputTypes ( fn . inputs ) } txDetails?: Truffle.TransactionDetails): Promise<string>;
  estimateGas(${ codegenInputTypes ( fn . inputs ) } txDetails?: Truffle.TransactionDetails): Promise<number>;
  }
` ; } function generateConstantFunction ( fn , overloadedName ? ) { return `
  ${ generateFunctionDocumentation ( fn . documentation ) }
  ${ overloadedName ?? fn . name }(${ codegenInputTypes ( fn . inputs ) } txDetails?: Truffle.TransactionDetails): Promise<${ codegenOutputTypes ( fn . outputs ) }>;
` ; } function generateFunctionDocumentation ( doc ? ) { if ( ! doc ) return '' ; let docString = '/**' ; if ( doc . details ) docString += `\n * ${ doc . details }` ; if ( doc . notice ) docString += `\n * ${ doc . notice }` ; const params = Object . entries ( doc . params || { } ) ; if ( params . length ) { params . forEach ( ( [ key , value ] ) => { docString += `\n * @param ${ key } ${ value }` ; } ) ; } if ( doc . return ) docString += `\n * @returns ${ doc . return }` ; docString += '\n */' ; return docString ; } export function generateOverloadedFunctions ( fns ) { return fns . map ( ( fn ) => generateFunction ( fn , `"${ getSignatureForFn ( fn ) }"` ) ) . join ( '\n' ) ; }