Skip to content

Instantly share code, notes, and snippets.

@gakonst
Created September 30, 2018 14:22
Show Gist options
  • Save gakonst/4557dd20f7a687202bed107e9995f187 to your computer and use it in GitHub Desktop.
Save gakonst/4557dd20f7a687202bed107e9995f187 to your computer and use it in GitHub Desktop.
Allows offline signing of a contract instance with web3.js
import Web3 from 'web3'
import { Contract, Account, Signature } from 'web3/types';
// Converts any contract to a signed contract
class SignedContract {
account: Account
contract: Contract
address: string
web3: Web3
get instance() {
return this.contract
}
constructor(web3: Web3, abi: any, address: string, key: string) {
// Get the function names from the ABI
this.web3 = web3
this.address = address
this.account = web3.eth.accounts.privateKeyToAccount(key)
const mutable = abi.filter((element : any)=> element.type === 'function' && (!element.constant) )
const nonMutable = abi.filter((element : any)=> element.type === 'function' && (element.constant) )
const mutableFuncNames : string[] = mutable.map((f :any) => f.name)
const nonMutableFuncNames : string[] = nonMutable.map((f :any) => f.name)
this.contract = new web3.eth.Contract(abi, address)
// Create a signed function for each
mutableFuncNames.map(func => this.signedFunc(func) )
nonMutableFuncNames.map(func => { this.wrapConstant(func) } )
}
wrapConstant(func: string) {
const method = this.contract.methods[func]
const wrappedNonConstant = async (...args: any[]): Promise<any> => {
return await method(...args).call()
}
// @ts-ignore
this.contract[func] = wrappedNonConstant
}
// Will sign the tx
signedFunc(func: string) {
const method = this.contract.methods[func]
const wrappedFunction = async (...args: any[]): Promise<any> => {
const data = method(...args).encodeABI()
const to = this.address
const nonce = await this.web3.eth.getTransactionCount(this.account.address)
const tx: any = {
to: to,
data: data,
chainId: await this.web3.eth.net.getId(),
nonce: nonce,
}
const gas = await method(...args).estimateGas({from: this.account.address})
tx['gas'] = gas
const signedTx = await <Signature>this.web3.eth.accounts.signTransaction(tx, this.account.privateKey)
// @ts-ignore
// Bug in ts-types
return this.web3.eth.sendSignedTransaction(signedTx.rawTransaction, console.log)
}
// @ts-ignore
this.contract[func] = wrappedFunction
}
}
export default SignedContract
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment