import { BigNumber } from "@joincivil/typescript-types"; import { EthAddress, TwoStepEthTransaction } from "../../types"; import { EthApi } from "@joincivil/ethapi"; import { MultiSigWalletContract } from "../generated/wrappers/multi_sig_wallet"; import { createTwoStepTransaction } from "../utils/contracts"; // TODO(ritave): Move to ABI v2 to get support for structs export class MultisigTransaction { public static async fromId( ethApi: EthApi, instance: MultiSigWalletContract, id: number, ): Promise { const data = await instance.transactions.callAsync(ethApi.toBigNumber(id).toString()); return new MultisigTransaction(ethApi, instance, id, { destination: data[0], value: new BigNumber(data[1]), data: data[2], executed: data[3], }); } public readonly id: number; public readonly information: Readonly; private readonly ethApi: EthApi; private readonly instance: MultiSigWalletContract; private constructor( ethApi: EthApi, instance: MultiSigWalletContract, id: number, transactionData: MultisigTransactionStruct, ) { this.ethApi = ethApi; this.instance = instance; this.id = id; this.information = transactionData; } /** * Returns whether this transaction can be executed: * - Wasn't executed beforehand * - Has enough confirmations */ public async canBeExecuted(): Promise { return !this.information.executed && this.instance.isConfirmed.callAsync(this.ethApi.toBigNumber(this.id)); } /** * Returns how many confirmations this Transaction needs to be executed * This is a sugar function, which is the same as the one in the main Multisig wrapper */ public async requiredConfirmations(): Promise { return new BigNumber(await this.instance.required.callAsync()).toNumber(); } /** * How many owners (and who) have confirmed this transaction */ public async confirmations(): Promise { return this.instance.getConfirmations.callAsync(this.ethApi.toBigNumber(this.id)); } /** * Execute a transaction. * Most of the time, the transaction is executed during confirmation or submition. * This call is mostly useful when you change owners or requirements * and then need to execute transactions * @returns This transaction with the updated state */ public async execute(): Promise> { return createTwoStepTransaction( this.ethApi, await this.instance.executeTransaction.sendTransactionAsync(this.ethApi.toBigNumber(this.id)), async receipt => MultisigTransaction.fromId(this.ethApi, this.instance, this.id), ); } /** * Confirms that you as an owner want to send this transaction * If after this confirmation, the requirements are met, the transaction is additionally executed * @returns This transaction with the updated state */ public async confirmTransaction(): Promise> { return createTwoStepTransaction( this.ethApi, await this.instance.confirmTransaction.sendTransactionAsync(this.ethApi.toBigNumber(this.id)), receipt => this, ); } /** * Revokes your confirmation before the transaction is executed. * @returns This transaciton with the updated state */ public async revokeConfirmation(): Promise> { return createTwoStepTransaction( this.ethApi, await this.instance.revokeConfirmation.sendTransactionAsync(this.ethApi.toBigNumber(this.id)), receipt => this, ); } } export interface MultisigTransactionStruct { destination: EthAddress; value: BigNumber; data: string; executed: boolean; }