file author Marek Kotewicz <marek@ethdev.com>
 *  date import * as utils from './utils/utils' ; import { coder } from './solidity/coder' ; import { RequestManager } from './RequestManager' ; import { Contract } from './Contract' ; import { future } from 'fp-future' ; import { TransactionOptions , TxHash , AbiItem } from './Schema' ; import { toDecimal } from './utils/utils' ; param requestManager async function checkForContractAddress ( requestManager , txId ) { const receiptFuture = future ( ) ; let count = 0 ; const fetcher = ( ) => { count ++ ; if ( count > 50 ) { receiptFuture . reject ( new Error ( "Contract transaction couldn't be found after 50 blocks" ) ) ; } else { requestManager . eth_getTransactionReceipt ( txId ) . then ( ( receipt ) => { if ( receipt && receipt . blockHash ) { receiptFuture . resolve ( receipt ) ; } else { setTimeout ( fetcher , 1000 ) ; } } , ( error ) => receiptFuture . reject ( error ) ) ; } } ; fetcher ( ) ; const receipt = await receiptFuture ; const code = await requestManager . eth_getCode ( receipt . contractAddress , 'latest' ) ; if ( code && code . length > 3 ) { return receipt . contractAddress ; } throw Object . assign ( new Error ( "The contract code couldn't be stored, please check your gas amount." ) , { response : code , receipt } ) ; } param abi function encodeConstructorParams ( abi , params ) { return ( abi . filter ( function ( json ) { return json . type === 'constructor' && json . inputs && json . inputs . length === params . length ; } ) . map ( function ( json ) { return json . inputs || [ ] ; } ) . map ( function ( types ) { return coder . encodeParams ( types , params ) ; } ) [ 0 ] || '' ) ; } public export class ContractFactory { constructor ( public requestManager , public abi ) { } /**
     * Should be called to create new contract on a blockchain
     */ async deploy ( param1 , param2 , options ) ; async deploy ( param1 , options ) ; async deploy ( options ) ; async deploy ( ... args ) { let options = undefined ; let last = args [ args . length - 1 ] ; if ( utils . isObject ( last ) && ! utils . isArray ( last ) ) { options = args . pop ( ) ; } if ( ! options ) { throw new Error ( 'Missing options object' ) ; } if ( ! options . data || typeof options . data !== 'string' ) { throw new Error ( 'Invalid options.data' ) ; } if ( toDecimal ( options . value ! ) > 0 ) { let constructorAbi = this . abi . filter ( function ( json ) { return json . type === 'constructor' && json . inputs . length === args . length ; } ) [ 0 ] || { } ; if ( ! constructorAbi . payable ) { throw new Error ( 'Cannot send value to non-payable constructor' ) ; } } let bytes = encodeConstructorParams ( this . abi , args ) ; options . data += bytes ; if ( ! options . gas ) { options . gas = await this . requestManager . eth_estimateGas ( options ) ; } const hash = await this . requestManager . eth_sendTransaction ( options ) ; if ( ! hash ) { throw new Error ( 'Error while sending contract creation transaction. A TxHash was not retrieved' ) ; } const address = await checkForContractAddress ( this . requestManager , hash ) ; const contract = await this . at ( address ) ; contract . transactionHash = hash ; return contract ; } param address async at ( address ) { if ( ! utils . isAddress ( address ) ) { throw new TypeError ( `Invalid address ${ JSON . stringify ( address ) }` ) ; } return new Contract ( this . requestManager , this . abi , address ) ; } }