Skip to content
Last update: January 26, 2024

Transactions

Info

Relevant JSON-RPC method: custodian_createTransaction

Areas of responsibility - transactions

MMI creates/proposes transactions to the custodian API, including a proposed gas price. However, custodians may (at their users’ request, or automatically) use a different gas price. Custodians are responsible for the ordering of transactions.

Transaction updates

  • MMI needs to know when transactions are signed and pushed to the blockchain so that the user can interact with Dapps.

Info

Normally, once the transaction is on-chain and it has the transaction hash, MetaMask yields control to the Dapp so that the Dapp can do something with the result.

MetaMask shows the status of a transaction in the activity pane.

  • We expect the custodian to have some way of communicating updates to the MMI web service; the ideal method being webhooks to a specific HTTPS URL.

  • The custodian sends updates to our web service. They may have an Oauth2 JWT in the Authorization header, described on the authentication page. It must be possible to match the incoming transaction to the user and customer.

  • Read the webhook specification

Rules

  • To give users access to the Defi ecosystem, they must have the power to make calls to smart contracts and conduct other types of transactions, such as:

    • ETH transfers.
    • ERC-20 transfers and approves - a special case of smart contract calls.
    • General smart contract calls, i.e. transactions where the to parameter is a smart contract address and the data.
  • We expect custodians to have their own rules on what contracts their customers can call.

Call failure

  • If a call fails due to non-compliance with such a rule, a 4xx HTTP response including a descriptive error message helps users to remedy the situation.

Parameters

The parameters we send with our HTTP request are similar to the ITXParams in the appendices, and closely resemble the parameters of eth_sendTransaction in the Ethereum JSON-RPC API. Hexlified string values are necessary for supporting large numbers.

  • from: the Ethereum address of the user.
  • to: the Ethereum address of the contract we are calling, or the recipient in the case of a simple transfer.
  • value: stringified integer of the value sent with this transaction, in Wei.
  • gasLimit: same as value, set by the user, but can be overridden.
  • data: the calldata, i.e. the 4 byte prefix and the contract method parameters.
  • Gas parameters: see the next section.

Nonce

We do not send a nonce. We expect the custodian to manage the nonce as well as publish the transaction. This is essential for avoiding stuck transactions.

MMI signing and sending transactions flow

Transactions FAQ

Who handles gas prices?

See Gas.

Who handles the nonce field?

This must be set by the custodian to facilitate transaction retries. Updated nonces should be included in webhooks and in the response to custodian_getTransactionById, as they are used by the extension UI to order transactions.

Who broadcasts the transaction?

Normally, Metamask broadcasts the transaction using whatever JSON-RPC API it is connected to; Infura by default. In MMI, generally, we expect the custodian to broadcast transactions, for the following reasons:

  • Due to approval processes within the custodian, transactions may take a long time (minutes to days) to actually sign. There is a chance that the original MMI user who initiated the transaction is now offline.
  • Transactions may fail due to incorrect nonce, gas prices, and other reasons. For this reason, it is better if the entity which sets these parameters (the custodian) broadcasts transactions.
  • Custodians will need to monitor transactions in order to show their users via UIs whether they were successful and also to communicate this to MMI.

There are some exceptions, however. See Transaction broadcast.

How do transaction statuses work?

In transaction methods and webhooks, the status field has the following content:

{
  finished: boolean
  signed: boolean
  submitted: boolean
  success: boolean
  displayText: string
  reason: string
}

Subfield explanations

  • finished - whether the transaction is done, i.e. it is no longer necessary to poll for the status of this transaction. This should be true whether or not the transaction was successful
  • signed - Whether the transaction has been signed - it has an available hash
  • submitted - Whether the transaction has been broadcast to an RPC network and made available in the mempool
  • success - Whether the transaction was successful - for example it has been validated by a node, and not reverted or rejected
  • displayText - a short, capitalised name for the transaction status, for example: Pending, Proposed, Rejected, Complete, Failed. This is shown to the user by the extension.
  • reason - an explanation for the current status. For example “Transaction was rejected by approver”, or if an error was received from an EVM node, this could be included here. This is displayed to the user by the extension if the transaction is not successful.