2019-03-01 13:24:04 +01:00
|
|
|
import { Contract } from "web3-eth-contract"
|
|
|
|
import { TransactionReceipt } from "web3-core"
|
2018-10-29 10:53:22 +01:00
|
|
|
import Logger from "../../utils/Logger"
|
|
|
|
import ContractHandler from "../ContractHandler"
|
2019-02-28 21:28:57 +01:00
|
|
|
import Web3Provider from "../Web3Provider"
|
2018-10-01 18:10:26 +02:00
|
|
|
|
2018-10-18 13:12:23 +02:00
|
|
|
export default abstract class ContractBase {
|
2018-10-01 18:10:26 +02:00
|
|
|
|
2018-10-16 14:56:18 +02:00
|
|
|
protected static instance = null
|
2018-10-09 10:55:53 +02:00
|
|
|
|
2018-10-17 18:24:01 +02:00
|
|
|
private contract: Contract = null
|
2018-10-02 10:06:26 +02:00
|
|
|
private contractName: string
|
2018-10-01 18:10:26 +02:00
|
|
|
|
2018-10-16 14:56:18 +02:00
|
|
|
constructor(contractName) {
|
2018-10-02 10:06:26 +02:00
|
|
|
this.contractName = contractName
|
2018-10-01 18:10:26 +02:00
|
|
|
}
|
|
|
|
|
2019-03-01 13:24:04 +01:00
|
|
|
public async getEventData(eventName: any, options: any) {
|
2018-10-09 10:55:53 +02:00
|
|
|
if (!this.contract.events[eventName]) {
|
2018-10-29 17:28:40 +01:00
|
|
|
throw new Error(`Event "${eventName}" not found on contract "${this.contractName}"`)
|
2018-10-09 10:55:53 +02:00
|
|
|
}
|
|
|
|
return this.contract.getPastEvents(eventName, options)
|
2018-10-01 18:10:26 +02:00
|
|
|
}
|
|
|
|
|
2019-02-28 21:28:57 +01:00
|
|
|
public getAddress(): string {
|
2018-10-05 12:34:31 +02:00
|
|
|
return this.contract.options.address
|
2018-10-01 18:10:26 +02:00
|
|
|
}
|
|
|
|
|
2018-10-29 17:28:40 +01:00
|
|
|
public getSignatureOfMethod(methodName: string): string {
|
2018-11-05 14:56:14 +01:00
|
|
|
const foundMethod = this.searchMethod(methodName)
|
2018-10-29 17:28:40 +01:00
|
|
|
return foundMethod.signature
|
|
|
|
}
|
|
|
|
|
2018-11-05 14:56:14 +01:00
|
|
|
public getInputsOfMethod(methodName: string): any[] {
|
|
|
|
const foundMethod = this.searchMethod(methodName)
|
|
|
|
return foundMethod.inputs
|
|
|
|
}
|
|
|
|
|
2018-10-09 10:55:53 +02:00
|
|
|
protected async init() {
|
2018-10-16 14:56:18 +02:00
|
|
|
this.contract = await ContractHandler.get(this.contractName)
|
|
|
|
}
|
|
|
|
|
2019-03-04 13:05:27 +01:00
|
|
|
protected async getFromAddress(from?: string): Promise<string> {
|
2019-02-28 21:28:57 +01:00
|
|
|
if (!from) {
|
|
|
|
from = (await Web3Provider.getWeb3().eth.getAccounts())[0]
|
|
|
|
}
|
2019-03-04 13:05:27 +01:00
|
|
|
return from
|
|
|
|
}
|
|
|
|
|
|
|
|
protected async sendFrom(name: string, args: any[], from?: string): Promise<TransactionReceipt> {
|
|
|
|
from = await this.getFromAddress(from)
|
2019-02-28 21:28:57 +01:00
|
|
|
return this.send(name, from, args)
|
|
|
|
}
|
|
|
|
|
2019-03-01 13:24:04 +01:00
|
|
|
protected async send(name: string, from: string, args: any[]): Promise<TransactionReceipt> {
|
2018-10-16 14:56:18 +02:00
|
|
|
if (!this.contract.methods[name]) {
|
2018-10-29 17:28:40 +01:00
|
|
|
throw new Error(`Method "${name}" is not part of contract "${this.contractName}"`)
|
2018-10-16 14:56:18 +02:00
|
|
|
}
|
2018-11-22 13:14:38 +01:00
|
|
|
// Logger.log(name, args)
|
2018-11-20 11:23:39 +01:00
|
|
|
const method = this.contract.methods[name]
|
2018-10-17 18:24:01 +02:00
|
|
|
try {
|
2018-11-22 10:56:06 +01:00
|
|
|
const methodInstance = method(...args)
|
|
|
|
const estimatedGas = await methodInstance.estimateGas(args, {
|
2018-10-17 18:24:01 +02:00
|
|
|
from,
|
|
|
|
})
|
2018-11-22 10:56:06 +01:00
|
|
|
const tx = methodInstance.send({
|
2018-10-17 18:24:01 +02:00
|
|
|
from,
|
2018-11-20 11:23:39 +01:00
|
|
|
gas: estimatedGas,
|
2018-10-17 18:24:01 +02:00
|
|
|
})
|
2018-11-22 10:56:06 +01:00
|
|
|
return tx
|
2018-10-17 18:24:01 +02:00
|
|
|
} catch (err) {
|
2018-11-20 11:23:39 +01:00
|
|
|
const mappedArgs = this.searchMethod(name).inputs.map((input, i) => {
|
|
|
|
return {
|
|
|
|
name: input.name,
|
|
|
|
value: args[i],
|
|
|
|
}
|
|
|
|
})
|
2019-01-23 16:15:19 +01:00
|
|
|
Logger.error("-".repeat(40))
|
2018-10-29 17:28:40 +01:00
|
|
|
Logger.error(`Sending transaction "${name}" on contract "${this.contractName}" failed.`)
|
2019-01-23 16:15:19 +01:00
|
|
|
Logger.error(`Error: ${err.message}`)
|
|
|
|
Logger.error(`From: ${from}`)
|
|
|
|
Logger.error(`Parameters: ${JSON.stringify(mappedArgs, null, 2)}`)
|
|
|
|
Logger.error("-".repeat(40))
|
2018-10-17 18:24:01 +02:00
|
|
|
throw err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-28 21:28:57 +01:00
|
|
|
protected async call<T extends any>(name: string, args: any[], from?: string): Promise<T> {
|
2018-10-17 18:24:01 +02:00
|
|
|
if (!this.contract.methods[name]) {
|
|
|
|
throw new Error(`Method ${name} is not part of contract ${this.contractName}`)
|
|
|
|
}
|
2018-11-22 10:56:06 +01:00
|
|
|
// Logger.log(name)
|
2018-10-17 18:24:01 +02:00
|
|
|
try {
|
|
|
|
const method = this.contract.methods[name](...args)
|
|
|
|
return method.call(from ? {from} : null)
|
|
|
|
} catch (err) {
|
2018-10-29 17:28:40 +01:00
|
|
|
Logger.error(`Calling method "${name}" on contract "${this.contractName}" failed. Args: ${args}`, err)
|
2018-10-17 18:24:01 +02:00
|
|
|
throw err
|
|
|
|
}
|
2018-10-09 10:55:53 +02:00
|
|
|
}
|
|
|
|
|
2019-03-01 13:24:04 +01:00
|
|
|
private searchMethod(methodName: string) {
|
|
|
|
const foundMethod = this.contract.options.jsonInterface
|
|
|
|
.map(method => ({...method, signature: (method as any).signature}))
|
|
|
|
.find((method: any) => method.name === methodName)
|
2018-11-05 14:56:14 +01:00
|
|
|
if (!foundMethod) {
|
|
|
|
throw new Error(`Method "${methodName}" is not part of contract "${this.contractName}"`)
|
|
|
|
}
|
|
|
|
return foundMethod
|
|
|
|
}
|
2018-10-01 18:10:26 +02:00
|
|
|
}
|