Skip to content
This repository was archived by the owner on Jun 30, 2021. It is now read-only.

Latest commit

 

History

History
120 lines (97 loc) · 6.4 KB

transaction_request_flow.md

File metadata and controls

120 lines (97 loc) · 6.4 KB

Transaction Request Flow

Introduction

Transaction requests are a way to create pre-transactions with only one side (either sender or receiver). That pre-transaction will become a full transaction once the other side has consumed it.

Here is a quick example to give you a better idea of how it works:

  1. Alice generates a transaction request to receive 10 OMG. The transaction request ID can be embedded in a QR code to provide a better user experience.
  2. Alice shows her QR code to Bob.
  3. Bob scans it, see the transaction request, updates some parts of it if needed, finalizes it and sends 10 OMG to Alice.

That's the simple version. Transaction requests come with a bunch of options to make them as flexible as possible.

A look at transaction requests

When creating transaction requests, a certain number of fields are optional but allow the configuration of the request. Walking through those fields is a good way to get a better understanding.

See the Swagger doc for more details.

Here is the model attributes when creating transaction requests:

type:
  type: string
  enum:
    - send
    - receive
token_id:
  type: string
  description: "The token ID to use for the transaction."
amount:
  type: integer
  default: null
  description:
    "The amount to transfer. If not specified, the consumption will need to set
     the amount."
correlation_id:
  type: string
  default: null
  description: "Optional unique identifier to tie a request with your system."
account_id:
  type: string
  description: The owner of the given address. Either account_id or provider_user_id needs to be filled.
provider_user_id:
  type: string
  description: The owner of the given address. Either account_id or provider_user_id needs to be filled.
address:
  type: string
  description:
    "If not specified, the current user's primary wallet will be used.
     If specified, it needs to be one of the account's or user's addresses."
require_confirmation:
  type: boolean
  default: false
  description:
    "Indicates if a consumption of the created request needs to be approved before
    being processed."
max_consumptions:
  type: integer
  default: null
  description:
    "The number of times this created request can be consumed."
consumption_lifetime:
  type: integer
  default: null
  description:
    "The lifetime in milliseconds of how long a consumption can stay
     'pending' before being expired. If a consumption is not approved before its
     expiration date, it will become invalid and be cancelled. This property
     can be used to avoid stale consumptions blocking the 'max_consumptions' count."
expiration_date:
  type: string
  default: null
  description:
    "The datetime at which the created request should expire (no one will be
     able to consume it anymore). The format is yyyy-MM-dd'T'HH:mm:ssZZZZZ."
allow_amount_override:
  type: boolean
  default: true
  description:
    "Defines if the amount set in the created request can be overriden in a
     consumption. Cannot be set to true if the amount property is not set at
     creation"
metadata:
  type: object
  default: {}
encrypted_metadata:
  type: object
  default: {}

Transaction Consumptions: Understanding the estimated amounts and finalized

When consuming a transaction request, the consumer will receive a consumption right away. If that request didn't require approval, it is finalized right away and the consumption will contain the fields:

  • estimated_request_amount: An estimate of the amount that will be sent/received in the token specified in the request.
  • estimated_consumption_amount: An estimate of the amount that will be sent/received in the token specified in the consumption.
  • finalized_request_amount: The actual amount that was sent/received in the currency of the request.
  • finalized_consumption_amount: The actual amount that was sent/received in the currency of the consumption.

When an approval is required, however, the consumption received after consumption will be pending, with the estimated_ amounts set, but no finalized_ ones yet. Once the request creator has approved it, those amounts will be populated with the actual values of the transaction.

Flow

Here is the flow used in the sample OMGShop application:

  1. Alice using the OMGShop iOS application generates a transaction request. The endpoint called is /me.create_transaction_request. The id of that is embedded in a QR Code and displayed on the screen of the device.

  2. Bob uses the scan feature in OMGShop on his own device to scan the QR Code. The app uses /me.get_transaction_request to get the details of the request.

  3. Bob can then see what kind of request he just scanned. Is it going to send or receive money, the amount, and so on. He can then decide to consume the request using /me.consume_transaction_request.

  4. The path can now have two different outputs. If the request does not require confirmation (require_confirmation=false), the consumption will be finalized and an actual transaction will be generated.

  5. If a confirmation is required (for example, Alice was sending money and wants to see who is trying to get her money and approve it), Alice's app needs to be listening to websocket events. By joining the websocket channel transaction_request:{alice_transaction_request_id}, she will receive events such as transaction_consumption_request. When receiving those events, she can then approve or reject it.

  6. Bob's app should be listening to the transaction_consumption:{bob_consumption_id} in order to know if it was approved or rejected by Alice. He will receive a transaction_consumption_finalized with either a confirmed consumption, or a rejected one (or potentially a failed one if the sender didn't have enough funds).

You can check the Websocket docs for more details on the available events.