import * as ethers from 'ethers' ; interface NetworkMapping { [ networkId ] : { address : string ; } ; } interface BuildArtifact { readonly contractName : string ; readonly abi : any [ ] ; readonly bytecode : string ; readonly networks : NetworkMapping ; } /**
 * Convenience class for an undeployed contract i.e. only the ABI and bytecode.
 */ export class AbstractContract { example param artifactName param links returns public static async fromArtifactName ( artifactName , links ? ) { const contract = await import ( `../../build/contracts/${ artifactName }.json` ) ; return AbstractContract . fromBuildArtifact ( contract , links , artifactName ) ; } param buildArtifact param links returns public static async fromBuildArtifact ( buildArtifact , links ? , artifactName = 'UntitledContract' ) { return new AbstractContract ( buildArtifact . abi , buildArtifact . bytecode , buildArtifact . networks , links , artifactName ) ; } public static async getNetworkID ( wallet ) { return ( await wallet . provider . getNetwork ( ) ) . chainId ; } param abi param bytecode param networks param links param contractName constructor ( readonly abi , readonly bytecode , readonly networks , readonly links ? , readonly contractName ? ) { } param Signer throws public async getDeployed ( wallet ) { if ( ! wallet . provider ) { throw new Error ( 'Signer requires provider' ) ; } const networkId = ( await wallet . provider . getNetwork ( ) ) . chainId ; const address = this . getDeployedAddress ( networkId ) ; return new ethers . Contract ( address , this . abi , wallet ) ; } param wallet param args returns public async deploy ( wallet , args ? ) { if ( ! wallet . provider ) { throw new Error ( 'Signer requires provider' ) ; } const networkId = ( await wallet . provider . getNetwork ( ) ) . chainId ; const bytecode = ( await this . links ) ? await this . generateLinkedBytecode ( networkId ) : this . bytecode ; const contractFactory = new ethers . ContractFactory ( this . abi , bytecode , wallet ) ; return contractFactory . deploy ( ... ( args || [ ] ) ) ; } param signer param address returns public async connect ( signer , address ) { return new ethers . Contract ( address , this . abi , signer ) ; } public getDeployedAddress ( networkId ) { const info = this . networks [ networkId ] ; if ( ! info ) { throw new Error ( `Abstract contract ${ this . contractName } not deployed on network ${ networkId }` ) ; } return info . address ; } public async generateLinkedBytecode ( networkId ) { if ( this . links === undefined ) { throw new Error ( 'Nothing to link' ) ; } let bytecode = this . bytecode ; for ( const name of Object . keys ( this . links ) ) { const library = this . links [ name ] ; const regex = new RegExp ( `__${ name }_+` , 'g' ) ; const address = ( await library ) . getDeployedAddress ( networkId ) ; const addressHex = address . replace ( '0x' , '' ) ; bytecode = bytecode . replace ( regex , addressHex ) ; } return bytecode ; } }