///
import { EventEmitter } from 'events';
import Common from '@ethereumjs/common';
import { TypedTransaction } from '@ethereumjs/tx';
import { BaseController, BaseConfig, BaseState } from '../BaseController';
import type { NetworkState, NetworkController } from '../network/NetworkController';
/**
* @type Result
* @property result - Promise resolving to a new transaction hash
* @property transactionMeta - Meta information about this new transaction
*/
export interface Result {
result: Promise;
transactionMeta: TransactionMeta;
}
/**
* @type Fetch All Options
* @property fromBlock - String containing a specific block decimal number
* @property etherscanApiKey - API key to be used to fetch token transactions
*/
export interface FetchAllOptions {
fromBlock?: string;
etherscanApiKey?: string;
}
/**
* @type Transaction
*
* Transaction representation
* @property chainId - Network ID as per EIP-155
* @property data - Data to pass with this transaction
* @property from - Address to send this transaction from
* @property gas - Gas to send with this transaction
* @property gasPrice - Price of gas with this transaction
* @property gasUsed - Gas used in the transaction
* @property nonce - Unique number to prevent replay attacks
* @property to - Address to send this transaction to
* @property value - Value associated with this transaction
*/
export interface Transaction {
chainId?: number;
data?: string;
from: string;
gas?: string;
gasPrice?: string;
gasUsed?: string;
nonce?: string;
to?: string;
value?: string;
maxFeePerGas?: string;
maxPriorityFeePerGas?: string;
estimatedBaseFee?: string;
estimateGasError?: string;
}
export interface GasPriceValue {
gasPrice: string;
}
export interface FeeMarketEIP1559Values {
maxFeePerGas: string;
maxPriorityFeePerGas: string;
}
/**
* The status of the transaction. Each status represents the state of the transaction internally
* in the wallet. Some of these correspond with the state of the transaction on the network, but
* some are wallet-specific.
*/
export declare enum TransactionStatus {
approved = "approved",
cancelled = "cancelled",
confirmed = "confirmed",
failed = "failed",
rejected = "rejected",
signed = "signed",
submitted = "submitted",
unapproved = "unapproved"
}
/**
* Options for wallet device.
*/
export declare enum WalletDevice {
MM_MOBILE = "metamask_mobile",
MM_EXTENSION = "metamask_extension",
OTHER = "other_device"
}
declare type TransactionMetaBase = {
isTransfer?: boolean;
transferInformation?: {
symbol: string;
contractAddress: string;
decimals: number;
};
id: string;
networkID?: string;
chainId?: string;
origin?: string;
rawTransaction?: string;
time: number;
toSmartContract?: boolean;
transaction: Transaction;
transactionHash?: string;
blockNumber?: string;
deviceConfirmedOn?: WalletDevice;
verifiedOnBlockchain?: boolean;
};
/**
* @type TransactionMeta
*
* TransactionMeta representation
* @property error - Synthesized error information for failed transactions
* @property id - Generated UUID associated with this transaction
* @property networkID - Network code as per EIP-155 for this transaction
* @property origin - Origin this transaction was sent from
* @property deviceConfirmedOn - string to indicate what device the transaction was confirmed
* @property rawTransaction - Hex representation of the underlying transaction
* @property status - String status of this transaction
* @property time - Timestamp associated with this transaction
* @property toSmartContract - Whether transaction recipient is a smart contract
* @property transaction - Underlying Transaction object
* @property transactionHash - Hash of a successful transaction
* @property blockNumber - Number of the block where the transaction has been included
*/
export declare type TransactionMeta = ({
status: Exclude;
} & TransactionMetaBase) | ({
status: TransactionStatus.failed;
error: Error;
} & TransactionMetaBase);
/**
* @type EtherscanTransactionMeta
*
* EtherscanTransactionMeta representation
* @property blockNumber - Number of the block where the transaction has been included
* @property timeStamp - Timestamp associated with this transaction
* @property hash - Hash of a successful transaction
* @property nonce - Nonce of the transaction
* @property blockHash - Hash of the block where the transaction has been included
* @property transactionIndex - Etherscan internal index for this transaction
* @property from - Address to send this transaction from
* @property to - Address to send this transaction to
* @property gas - Gas to send with this transaction
* @property gasPrice - Price of gas with this transaction
* @property isError - Synthesized error information for failed transactions
* @property txreceipt_status - Receipt status for this transaction
* @property input - input of the transaction
* @property contractAddress - Address of the contract
* @property cumulativeGasUsed - Amount of gas used
* @property confirmations - Number of confirmations
*/
export interface EtherscanTransactionMeta {
blockNumber: string;
timeStamp: string;
hash: string;
nonce: string;
blockHash: string;
transactionIndex: string;
from: string;
to: string;
value: string;
gas: string;
gasPrice: string;
cumulativeGasUsed: string;
gasUsed: string;
isError: string;
txreceipt_status: string;
input: string;
contractAddress: string;
confirmations: string;
tokenDecimal: string;
tokenSymbol: string;
}
/**
* @type TransactionConfig
*
* Transaction controller configuration
* @property interval - Polling interval used to fetch new currency rate
* @property provider - Provider used to create a new underlying EthQuery instance
* @property sign - Method used to sign transactions
*/
export interface TransactionConfig extends BaseConfig {
interval: number;
sign?: (transaction: Transaction, from: string) => Promise;
txHistoryLimit: number;
}
/**
* @type MethodData
*
* Method data registry object
* @property registryMethod - Registry method raw string
* @property parsedRegistryMethod - Registry method object, containing name and method arguments
*/
export interface MethodData {
registryMethod: string;
parsedRegistryMethod: Record;
}
/**
* @type TransactionState
*
* Transaction controller state
* @property transactions - A list of TransactionMeta objects
* @property methodData - Object containing all known method data information
*/
export interface TransactionState extends BaseState {
transactions: TransactionMeta[];
methodData: {
[key: string]: MethodData;
};
}
/**
* Multiplier used to determine a transaction's increased gas fee during cancellation
*/
export declare const CANCEL_RATE = 1.5;
/**
* Multiplier used to determine a transaction's increased gas fee during speed up
*/
export declare const SPEED_UP_RATE = 1.1;
/**
* Controller responsible for submitting and managing transactions.
*/
export declare class TransactionController extends BaseController {
private ethQuery;
private registry;
private handle?;
private mutex;
private getNetworkState;
private failTransaction;
private registryLookup;
/**
* Normalizes the transaction information from etherscan
* to be compatible with the TransactionMeta interface.
*
* @param txMeta - The transaction.
* @param currentNetworkID - The current network ID.
* @param currentChainId - The current chain ID.
* @returns The normalized transaction.
*/
private normalizeTx;
private normalizeTokenTx;
/**
* EventEmitter instance used to listen to specific transactional events
*/
hub: EventEmitter;
/**
* Name of this controller used during composition
*/
name: string;
/**
* Method used to sign transactions
*/
sign?: (transaction: TypedTransaction, from: string) => Promise;
/**
* Creates a TransactionController instance.
*
* @param options - The controller options.
* @param options.getNetworkState - Gets the state of the network controller.
* @param options.onNetworkStateChange - Allows subscribing to network controller state changes.
* @param options.getProvider - Returns a provider for the current network.
* @param config - Initial options used to configure this controller.
* @param state - Initial state to set on this controller.
*/
constructor({ getNetworkState, onNetworkStateChange, getProvider, }: {
getNetworkState: () => NetworkState;
onNetworkStateChange: (listener: (state: NetworkState) => void) => void;
getProvider: () => NetworkController['provider'];
}, config?: Partial, state?: Partial);
/**
* Starts a new polling interval.
*
* @param interval - The polling interval used to fetch new transaction statuses.
*/
poll(interval?: number): Promise;
/**
* Handle new method data request.
*
* @param fourBytePrefix - The method prefix.
* @returns The method data object corresponding to the given signature prefix.
*/
handleMethodData(fourBytePrefix: string): Promise;
/**
* Add a new unapproved transaction to state. Parameters will be validated, a
* unique transaction id will be generated, and gas and gasPrice will be calculated
* if not provided. If A `:unapproved` hub event will be emitted once added.
*
* @param transaction - The transaction object to add.
* @param origin - The domain origin to append to the generated TransactionMeta.
* @param deviceConfirmedOn - An enum to indicate what device the transaction was confirmed to append to the generated TransactionMeta.
* @returns Object containing a promise resolving to the transaction hash if approved.
*/
addTransaction(transaction: Transaction, origin?: string, deviceConfirmedOn?: WalletDevice): Promise;
prepareUnsignedEthTx(txParams: Record): TypedTransaction;
/**
* `@ethereumjs/tx` uses `@ethereumjs/common` as a configuration tool for
* specifying which chain, network, hardfork and EIPs to support for
* a transaction. By referencing this configuration, and analyzing the fields
* specified in txParams, @ethereumjs/tx is able to determine which EIP-2718
* transaction type to use.
*
* @returns {Common} common configuration object
*/
getCommonConfiguration(): Common;
/**
* Approves a transaction and updates it's status in state. If this is not a
* retry transaction, a nonce will be generated. The transaction is signed
* using the sign configuration property, then published to the blockchain.
* A `:finished` hub event is fired after success or failure.
*
* @param transactionID - The ID of the transaction to approve.
*/
approveTransaction(transactionID: string): Promise;
/**
* Cancels a transaction based on its ID by setting its status to "rejected"
* and emitting a `:finished` hub event.
*
* @param transactionID - The ID of the transaction to cancel.
*/
cancelTransaction(transactionID: string): void;
/**
* Attempts to cancel a transaction based on its ID by setting its status to "rejected"
* and emitting a `:finished` hub event.
*
* @param transactionID - The ID of the transaction to cancel.
* @param gasValues - The gas values to use for the cancellation transation.
*/
stopTransaction(transactionID: string, gasValues?: GasPriceValue | FeeMarketEIP1559Values): Promise;
/**
* Attempts to speed up a transaction increasing transaction gasPrice by ten percent.
*
* @param transactionID - The ID of the transaction to speed up.
* @param gasValues - The gas values to use for the speed up transation.
*/
speedUpTransaction(transactionID: string, gasValues?: GasPriceValue | FeeMarketEIP1559Values): Promise;
/**
* Estimates required gas for a given transaction.
*
* @param transaction - The transaction to estimate gas for.
* @returns The gas and gas price.
*/
estimateGas(transaction: Transaction): Promise<{
gas: string;
gasPrice: any;
estimateGasError?: undefined;
} | {
gas: string;
gasPrice: any;
estimateGasError: string | undefined;
}>;
/**
* Check the status of submitted transactions on the network to determine whether they have
* been included in a block. Any that have been included in a block are marked as confirmed.
*/
queryTransactionStatuses(): Promise;
/**
* Updates an existing transaction in state.
*
* @param transactionMeta - The new transaction to store in state.
*/
updateTransaction(transactionMeta: TransactionMeta): void;
/**
* Removes all transactions from state, optionally based on the current network.
*
* @param ignoreNetwork - Determines whether to wipe all transactions, or just those on the
* current network. If `true`, all transactions are wiped.
*/
wipeTransactions(ignoreNetwork?: boolean): void;
/**
* Get transactions from Etherscan for the given address. By default all transactions are
* returned, but the `fromBlock` option can be given to filter just for transactions from a
* specific block onward.
*
* @param address - The address to fetch the transactions for.
* @param opt - Object containing optional data, fromBlock and Etherscan API key.
* @returns The block number of the latest incoming transaction.
*/
fetchAll(address: string, opt?: FetchAllOptions): Promise;
/**
* Trim the amount of transactions that are set on the state. Checks
* if the length of the tx history is longer then desired persistence
* limit and then if it is removes the oldest confirmed or rejected tx.
* Pending or unapproved transactions will not be removed by this
* operation. For safety of presenting a fully functional transaction UI
* representation, this function will not break apart transactions with the
* same nonce, created on the same day, per network. Not accounting for transactions of the same
* nonce, same day and network combo can result in confusing or broken experiences
* in the UI. The transactions are then updated using the BaseController update.
*
* @param transactions - The transactions to be applied to the state.
* @returns The trimmed list of transactions.
*/
private trimTransactionsForState;
/**
* Determines if the transaction is in a final state.
*
* @param status - The transaction status.
* @returns Whether the transaction is in a final state.
*/
private isFinalState;
/**
* Method to verify the state of a transaction using the Blockchain as a source of truth.
*
* @param meta - The local transaction to verify on the blockchain.
* @returns A tuple containing the updated transaction, and whether or not an update was required.
*/
private blockchainTransactionStateReconciler;
/**
* Method to check if a tx has failed according to their receipt
* According to the Web3 docs:
* TRUE if the transaction was successful, FALSE if the EVM reverted the transaction.
* The receipt is not available for pending transactions and returns null.
*
* @param txHash - The transaction hash.
* @returns Whether the transaction has failed.
*/
private checkTxReceiptStatusIsFailed;
/**
* Method to verify the state of transactions using Etherscan as a source of truth.
*
* @param remoteTxs - Transactions to reconcile that are from a remote source.
* @param localTxs - Transactions to reconcile that are local.
* @returns A tuple containing a boolean indicating whether or not an update was required, and the updated transaction.
*/
private etherscanTransactionStateReconciler;
/**
* Get all transactions that are in the remote transactions array
* but not in the local transactions array.
*
* @param remoteTxs - Array of transactions from remote source.
* @param localTxs - Array of transactions stored locally.
* @returns The new transactions.
*/
private getNewTransactions;
/**
* Get all the transactions that are locally outdated with respect
* to a remote source (etherscan or blockchain). The returned array
* contains the transactions with the updated data.
*
* @param remoteTxs - Array of transactions from remote source.
* @param localTxs - Array of transactions stored locally.
* @returns The updated transactions.
*/
private getUpdatedTransactions;
/**
* Verifies if a local transaction is outdated with respect to the remote transaction.
*
* @param remoteTx - The remote transaction from Etherscan.
* @param localTx - The local transaction.
* @returns Whether the transaction is outdated.
*/
private isTransactionOutdated;
/**
* Verifies if the status of a local transaction is outdated with respect to the remote transaction.
*
* @param remoteTxHash - Remote transaction hash.
* @param localTxHash - Local transaction hash.
* @param remoteTxStatus - Remote transaction status.
* @param localTxStatus - Local transaction status.
* @returns Whether the status is outdated.
*/
private isStatusOutdated;
/**
* Verifies if the gas data of a local transaction is outdated with respect to the remote transaction.
*
* @param remoteGasUsed - Remote gas used in the transaction.
* @param localGasUsed - Local gas used in the transaction.
* @returns Whether the gas data is outdated.
*/
private isGasDataOutdated;
}
export default TransactionController;