// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { BlockParam, BlockParamLiteral, CallData, ContractAbi, ContractArtifact, DecodedLogArgs, MethodAbi, TransactionReceiptWithDecodedLogs, TxData, TxDataPayable, SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; import { SimpleContractArtifact } from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; // tslint:enable:no-unused-variable /* istanbul ignore next */ // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class IWalletContract extends BaseContract { /** * Verifies that a signature is valid. */ public isValidSignature = { /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas * since they don't modify state. * @param hash Message hash that is signed. * @param signature Proof of signing. * @returns Validity of order signature. */ async callAsync( hash: string, signature: string, callData: Partial = {}, defaultBlock?: BlockParam, ): Promise { assert.isString('hash', hash); assert.isString('signature', signature); assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ schemas.addressSchema, schemas.numberSchema, schemas.jsNumber, ]); if (defaultBlock !== undefined) { assert.isBlockParam('defaultBlock', defaultBlock); } const self = (this as any) as IWalletContract; const encodedData = self._strictEncodeArguments('isValidSignature(bytes32,bytes)', [hash, signature]); const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( { to: self.address, ...callData, data: encodedData, }, self._web3Wrapper.getContractDefaults(), ); callDataWithDefaults.from = callDataWithDefaults.from ? callDataWithDefaults.from.toLowerCase() : callDataWithDefaults.from; const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,bytes)'); // tslint:disable boolean-naming const result = abiEncoder.strictDecodeReturnValue(rawCallResult); // tslint:enable boolean-naming return result; }, /** * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used * to create a 0x transaction (see protocol spec for more details). * @param hash Message hash that is signed. * @param signature Proof of signing. */ getABIEncodedTransactionData(hash: string, signature: string): string { assert.isString('hash', hash); assert.isString('signature', signature); const self = (this as any) as IWalletContract; const abiEncodedTransactionData = self._strictEncodeArguments('isValidSignature(bytes32,bytes)', [ hash, signature, ]); return abiEncodedTransactionData; }, getABIDecodedTransactionData(callData: string): boolean { const self = (this as any) as IWalletContract; const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,bytes)'); // tslint:disable boolean-naming const abiDecodedCallData = abiEncoder.strictDecode(callData); return abiDecodedCallData; }, getABIDecodedReturnData(returnData: string): boolean { const self = (this as any) as IWalletContract; const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,bytes)'); // tslint:disable boolean-naming const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); return abiDecodedReturnData; }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, supportedProvider: SupportedProvider, txDefaults: Partial, logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, ): Promise { assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ schemas.addressSchema, schemas.numberSchema, schemas.jsNumber, ]); if (artifact.compilerOutput === undefined) { throw new Error('Compiler output not found in the artifact file'); } const provider = providerUtils.standardizeOrThrow(supportedProvider); const bytecode = artifact.compilerOutput.evm.bytecode.object; const abi = artifact.compilerOutput.abi; const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {}; if (Object.keys(logDecodeDependencies) !== undefined) { for (const key of Object.keys(logDecodeDependencies)) { logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi; } } return IWalletContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly); } public static async deployAsync( bytecode: string, abi: ContractAbi, supportedProvider: SupportedProvider, txDefaults: Partial, logDecodeDependencies: { [contractName: string]: ContractAbi }, ): Promise { assert.isHexString('bytecode', bytecode); assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ schemas.addressSchema, schemas.numberSchema, schemas.jsNumber, ]); const provider = providerUtils.standardizeOrThrow(supportedProvider); const constructorAbi = BaseContract._lookupConstructorAbi(abi); [] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString); const iface = new ethers.utils.Interface(abi); const deployInfo = iface.deployFunction; const txData = deployInfo.encode(bytecode, []); const web3Wrapper = new Web3Wrapper(provider); const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( { data: txData }, txDefaults, web3Wrapper.estimateGasAsync.bind(web3Wrapper), ); const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults); logUtils.log(`transactionHash: ${txHash}`); const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash); logUtils.log(`IWallet successfully deployed at ${txReceipt.contractAddress}`); const contractInstance = new IWalletContract( txReceipt.contractAddress as string, provider, txDefaults, logDecodeDependencies, ); contractInstance.constructorArgs = []; return contractInstance; } /** * @returns The contract ABI */ public static ABI(): ContractAbi { const abi = [ { constant: true, inputs: [ { name: 'hash', type: 'bytes32', }, { name: 'signature', type: 'bytes', }, ], name: 'isValidSignature', outputs: [ { name: 'isValid', type: 'bool', }, ], payable: false, stateMutability: 'view', type: 'function', }, ] as ContractAbi; return abi; } constructor( address: string, supportedProvider: SupportedProvider, txDefaults?: Partial, logDecodeDependencies?: { [contractName: string]: ContractAbi }, ) { super('IWallet', IWalletContract.ABI(), address, supportedProvider, txDefaults, logDecodeDependencies); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); } } // tslint:disable:max-file-line-count // tslint:enable:no-unbound-method no-parameter-reassignment no-consecutive-blank-lines ordered-imports align // tslint:enable:trailing-comma whitespace no-trailing-whitespace