Brokerage

note

Before you can incorporate the Brokerage product into your solution, you must first incorporate Solaris Digital Banking as well as Custody. See the following guides for step-by-step instructions:

Introduction

The Solaris Digital Assets (SDA) Brokerage product allows your customers to trade crypto assets using fiat currency.

At a high level, the Brokerage product works as follows:

  1. You present your customer with a list of crypto/fiat Trading Pairs and their respective exchange rates in your frontend. For example, you could allow your customers to trade between EUR and BTC, ETH, USDC, and other digital assets.
  2. The customer chooses a Trading Pair and enters the amount that they would like to trade.
  3. Your solution requests a Trade and an ApprovalRequest for the Trade, which the customer must confirm.
  4. Upon successful confirmation, the SDA platform will process the Trade.

Follow the steps in the guide to integrate the Brokerage product into your SDA solution.

Step 1: Trading Terms and Conditions

All customers must agree to the Solaris Digital Assets Trading Terms and Conditions before they can start trading on the SDA platform.

You must display these Terms and Conditions along with the Solaris Digital Assets Terms and Conditions during onboarding:

When they accept the Terms and Conditions, call the endpoint below to record their consent on their Entity resource using the SDA API.

POST Accept Terms and Conditions for trading

This endpoint records an Entity's acceptance of the SDA Trading Terms and Conditions. The API will store the acceptance as a UTC timestamp in the Entity's trading_terms_conditions_signed_at property.

Request URL:

POST /entities/{entity_id}/trading_terms_and_conditions

Response example:

201 Created

Click here to view the full API reference.

Step 2: Retrieve Trading Pairs

When a customer logs in to your solution and wishes to trade crypto, then your frontend must display the Trading Pairs available for trading. A Trading Pair can have one of two forms:

  1. Digital asset → Fiat asset
  2. Fiat asset → Digital asset

Use the API endpoints described below to query information about Trading Pair resources so that you can display them to your customers.

The Trading Pair resource contains the following properties:

  • id: The unique identifier for the Trading Pair. Use this property to query the Trading Pair with the API.
  • code: A string containing the two Assets of the Trading Pair, separated by a slash. The first asset is the base asset, and the second asset is the quote asset. Trades always proceed from the first asset in the Trading Pair to the second.

    • Example: "BTC/EUR" means "I trade BTC for EUR" (i.e., "I sell BTC").
    • Example: "EUR/BTC" means "I trade EUR for BTC" (i.e., "I purchase BTC").
  • from_asset_id: The unique identifier of the base Asset in the Trading Pair.
  • to_asset_id: The unique identifier of the quote Asset in the Trading Pair.
  • min_amount: The minimum amount that customers must request in Trades with this Trading Pair.
  • is_tradable: Indicates whether or not the Trading Pair can currently be traded on the SDA platform.
note

The id of a Trading Pair is the only way to refer to a specific Trading Pair using the SDA API. All other forms of reference (e.g., the code) are not considered immutable and/or unique.

GET List all Trading Pairs

This endpoint returns an array containing all Trading Pairs on the platform.

Request URL:

GET /trading/pairs

Response example:

Copy
Copied
{
  "items": [
    {
      "id": "00000000000000000000000000000001trpr",
      "from_asset_id": "00000000000000000000000000000001asst",
      "to_asset_id": "f0000000000000000000000000000001asst",
      "code": "BTC/EUR",
      "precision": 2,
      "min_amount": "0.0001",
      "created_at": "2019-03-01T21:47:06Z",
      "updated_at": "2019-03-01T21:47:06Z"
    }
  ],
  "pagination": {
    "next": 0,
    "prev": 0
  }
}

Click here to view the full API reference.

GET Retrieve a Trading Pair

This endpoint returns information about the Trading Pair specified in the request URL.

Request URL:

GET /trading/pairs/{trading_pair_id}

Response example:

Copy
Copied
{
  "id": "00000000000000000000000000000001trpr",
  "from_asset_id": "00000000000000000000000000000001asst",
  "to_asset_id": "f0000000000000000000000000000001asst",
  "code": "BTC/EUR",
  "precision": 2,
  "min_amount": "0.0001",
  "created_at": "2019-03-01T21:47:06Z",
  "updated_at": "2019-03-01T21:47:06Z"
}

Click here to view the full API reference.

Step 3: Get the Price for a Trading Pair

Next, you can retrieve the Price for each Trading Pair that you present to your customers using the API endpoint described below.

Optionally, you can get the Price of a specific trade amount by supplying the amount query parameter in the request. The API will return a Price calculated based on this amount. Otherwise, the API will default to the min_amount attribute of the Trading Pair.

note

You can only get the Price of a Trading Pair with an is_tradable value of true.

GET Request the Price for a Trading Pair

This endpoint returns an indicative trade price for the Trading Pair specified in the request URL.

note

The price provided in the result can only be used as an estimation and does not guarantee the price during the actual trade on the platform.

Request URL:

GET /v1/trading/pairs/{trading_pair_id}/price?amount=1.123

Response example:

The API will return a Price object containing the following properties:

  • from_amount: The amount of the base Asset to be traded. You can specify this using the amount query parameter in the original request; otherwise, it will default to the min_amount of the Trading Pair.
  • traded_from_amount: The amount traded on the Exchange.
  • traded_to_amount: The amount received from the Exchange.
  • to_amount: The final amount sent to the recipient.
  • fee_amount: The amount collected in platform fees.
  • price: The price of the trade, calculated using traded_to_amount / traded_from_amount.

The example below shows a Price calculated for a Trade from BTC to EUR. The displayed price is in EUR. Note that the response values will use the decimal precision specified in the Asset.

Copy
Copied
// 200 OK

{
  "trading_pair_id": "00000000000000000000000000000001trpr",
  "from_amount": "1.12300000",
  "traded_from_amount": "1.12300000",
  "traded_to_amount": "9956.64",
  "to_amount": "9857.07",
  "price": "8866.11",
  "fee_amount": "99.57",
  "created_at": "2020-07-16T11:26:41Z",
  "updated_at": "2020-07-16T11:26:41Z"
}

Step 4: Get historical Exchange Rates

The SDA platform allows you to query the historical Exchange Rates for a given Trading Pair. Each Exchange Rate resource contains the following properties:

  • price: The Price of the Trading Pair during the given time frame.
  • starts_at: The date/time from which the returned price was valid.
  • ends_at: The date/time when the returned price expired.

Exchange Rate API endpoints

The API allows you to query Exchange Rates along the following time intervals:

Click the links above to view the full API reference for each endpoint.

Step 5: Get the customer's Trading Limit

The SDA platform limits how much customers can trade over a given time interval. Before allowing them to make a Trade, your solution must query the customer's remaining Trading Limit.

GET Retrieve Trading Limit for an Entity

This endpoint returns the current trading limit configuration for the Entity specified in the request URL as well as the remaining amount they are allowed to trade.

Request URL:

GET /v1/entities/{entity_id}/trading_limits

Response example:

The Trading Limit object includes the following attributes:

  • interval: An integer that represents a time interval, in seconds, during which the customer can only make the number of Trades specified in amount.
  • amount: A string, in EUR (with EUR asset precision), that represents the maximum cumulative amount of Trades allowed within the number of seconds specified in interval.
  • remaining_amount A string, in EUR (with EUR asset precision), that represents the remaining amount that the customer may trade within the current interval. The platform calculates this value using amount - sum(Traded amounts in EUR), where the sum represents a cumulative trade amount during a given time window that has its start time defined as DATE NOW - interval and its end time as DATE NOW.
Copy
Copied
// 200 OK

{
  "entity_id": "e0a26b1b54a6009d9ad9c6efd3aa5c77enty",
  "interval": 604800,
  "amount": "50000.00",
  "remaining_amount": "49686.69",
  "created_at": "2021-02-11T22:40:59Z",
  "updated_at": "2021-02-11T22:40:59Z"
}

Click here to view the full API reference.

Step 6: Make a Trade

The final step in the Brokerage product flow is to request a Trade from the platform. This consists of two operations:

  1. Call the POST Create a Trade endpoint.
  2. If the trade initiator's ApprovalMethod requires it, then call the POST Request an ApprovalRequest endpoint for the Trade.

The request body must contain the following parameters:

  • reference: UUID used as an idempotency key for the Trade request.
  • trading_pair_id: The Trading Pair that corresponds with the Trade.
  • from_amount: The amount of the base Asset to trade for the quote Asset. The funds must be available on the from_account and at least equal the min_amount specified on the Trading Pair.
  • entity_id: The Entity initiating the Trade.
  • from_account_id: A Solaris Account (either Digital Banking or Digital Assets) from which the funds in the base Asset will be withdrawn.
  • to_account_id: A Solaris Account (either Digital Banking or Digital Assets) to which the funds will be transferred.

If the from_account or to_account corresponds with a Solaris Digital Banking account, then it must meet the following requirements:

  • The Account's bic is SOBKDEB2XXX.
  • The type is WALLET_PERSONAL, WALLET_BUSINESS, CHECKING_PERSONAL, or CHECKING_BUSINESS.
  • The locking_status is NO_BLOCK.
  • The status is ACTIVE.
note

Only Trading Pairs with an is_tradable value of true can be used for Trades.

POST Create a new Trade

This endpoint creates a new Trade on the platform. Please note the requirements described above.

Request URL:

POST /trading/trades

Request example:

Copy
Copied
{
  "from_amount": "209.1",
  "entity_id": "b6ef80668690fa4dfbb51a3bc49a1fb7enty",
  "trading_pair_id": "00000000000000000000000000000002trpr",
  "from_account_id": "57e837a08685eff2cee29e82b6b09857cacc",
  "to_account_id": "d4f01daea26362d0de5fe89cb0f8d905acct",
  "reference": "9bcf5ffa4bb4d4ebbf92fb74f3a61f85"
}

Response example:

The API will respond with a new Trade. Initially, it will have a state of PENDING and include an estimations object, which indicates the estimated amount of funds to be transferred and fees to be paid.

note

The customer must approve the related ApprovalRequest for the Trade before the SDA platform will process it. See the Strong Customer Authentication guide for more information about ApprovalRequests.

Copy
Copied
{
  "id": "82d19e27542a21c950eaae13059cf5f5trad",
  "from_amount": "209.10",
  "traded_from_amount": null,
  "traded_to_amount": null,
  "to_amount": null,
  "fee_amount": null,
  "price": null,
  "state": "PENDING",
  "reference": "9bcf5ffa4bb4d4ebbf92fb74f3a61f85",
  "entity_id": "b6ef80668690fa4dfbb51a3bc49a1fb7enty",
  "trading_pair_id": "00000000000000000000000000000002trpr",
  "from_account_id": "57e837a08685eff2cee29e82b6b09857cacc",
  "to_account_id": "d4f01daea26362d0de5fe89cb0f8d905acct",
  "failure_reason": null,
  "estimations": {
    "traded_from_amount": "207.00",
    "traded_to_amount": "0.02288435",
    "to_amount": "0.02288435",
    "fee_amount": "2.10",
    "price": "0.00011055"
  },
  "created_at": "2021-11-26T14:35:45Z",
  "updated_at": "2021-11-26T14:35:45Z"
}

Click here to view the full API reference.

Trade lifecycle

A Trade can have one of the following statuses:

Status value Meaning
PENDING The Trade has been created, and now the customer must approve the corresponding ApprovalRequest.
APPROVED The Trade has been approved, and now the Platform will collect the payment of from_amount from the from_account and execute the Trade.
EXECUTED The Trade has been executed and can no longer fail or be canceled. The Platform will now settle the to_amount to the to_account.
COMPLETED All funds have been exchanged, and the Trade is now complete.
CANCELLED The Trade was canceled by the initiating Entity.
FAILING The Trade was approved but ultimately could not be executed, so the Platform has begun to refund the Trade amount.
FAILED The Trade failed, and all funds were refunded to the initiating Entity.

Once the SDA platform approves and executes the Trade, then the Trade will transition to the COMPLETED state. The API will populate the following fields:

  • fee_amount: The amount collected in platform fees. This amount is always denominated in EUR. The platform collects it prior to the exchange for FIAT → CRYPTO Trades and after the exchange for CRYPTO → FIAT Trades.
  • traded_from_amount: The amount that was submitted on the exchange.
  • filled_from_amount: The amount that was executed on the exchange.
  • traded_to_amount: The amount received from the exchange.
  • to_amount: The amount received on the destination account.
  • price: The price of the trade, calculated as filled_from_amount / traded_from_amount and rounded to the precision of the Trading Pair.

POST Cancel a Trade

Call the endpoint below to cancel a Trade. Note that the Trade must have a state of PENDING.

Request URL:

POST /v1/trading/trades/{trade_id}/cancel

Response example:

Copy
Copied
// 200 OK

{
  "id": "82d19e27542a21c950eaae13059cf5f5trad",
  "from_amount": "209.10",
  "traded_from_amount": null,
  "filled_from_amount": null,
  "traded_to_amount": null,
  "to_amount": null,
  "fee_amount": null,
  "price": null,
  "state": "CANCELLED",
  "reference": "9bcf5ffa4bb4d4ebbf92fb74f3a61f85",
  "entity_id": "b6ef80668690fa4dfbb51a3bc49a1fb7enty",
  "trading_pair_id": "00000000000000000000000000000002trpr",
  "from_account_id": "57e837a08685eff2cee29e82b6b09857cacc",
  "to_account_id": "d4f01daea26362d0de5fe89cb0f8d905acct",
  "failure_reason": null,
  "estimations": {
    "traded_from_amount": "207.00",
    "traded_to_amount": "0.02288435",
    "to_amount": "0.02288435",
    "fee_amount": "2.10",
    "price": "0.00011055"
  },
  "created_at": "2021-11-26T14:35:45Z",
  "updated_at": "2021-11-26T14:35:45Z"
}

Click here to view the full API reference.

Trade callbacks

All Trade state transitions that affect external parties generate callbacks. See the callbacks guide for more information.