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:
- 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.
- The customer chooses a Trading Pair and enters the amount that they would like to trade.
- Your solution requests a Trade and an ApprovalRequest for the Trade, which the customer must confirm.
- 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:
- Digital asset → Fiat asset
- 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.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.is_tradable
: Indicates whether or not the Trading Pair can currently be traded on the SDA platform.-
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_min_amount
: The minimum amount required to make Trades using this TradingPair.from_asset_max_amount
: The maximum amount required to make Trades using this TradingPair. If the value isnull
, then there is no maximum amount (although the Trade may still be restricted by limits applied to the Entity).
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:
{
"items": [
{
"id": "00000000000000000000000000000001trpr",
"from_asset_id": "00000000000000000000000000000001asst",
"to_asset_id": "f0000000000000000000000000000001asst",
"is_tradable": true,
"code": "BTC/EUR",
"price_precision": 2,
"from_asset_min_amount": "0.0001",
"from_asset_max_amount": "1.0",
"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:
{
"id": "00000000000000000000000000000001trpr",
"from_asset_id": "00000000000000000000000000000001asst",
"to_asset_id": "f0000000000000000000000000000001asst",
"is_tradable": true,
"code": "BTC/EUR",
"price_precision": 2,
"from_asset_min_amount": "0.0001",
"from_asset_max_amount": "1.0",
"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
The SDA API offers two endpoints for retrieving the Price of a Trading Pair:
- GET Simulate a Trade for a Trading Pair: Returns the Price of a Trading Pair along with an estimation of the actual Trade costs.
- GET Retrieve the Price of a Trading Pair: Only returns the Price of a Trading Pair.
GET Simulate a Trade for a Trading Pair
Your solution should call this endpoint to produce the estimates for a Trade with a given Trading Pair so that you may present them to the user in your frontend. This includes the estimated Price of a Trade along with the calculated fees and actual amount traded (i.e., traded_to_amount
).
Please note the following:
- The calculated
price
uses the price precision specified in the Trading Pair. - The
to_amount
andtraded_to_amount
values use the price precision of the Trading Pair'sto_asset
(i.e., the Asset to which the user is trading). - The
traded_from_amount
andfrom_amount
values use the price precision of the Trading Pair'sfrom_asset
(i.e., the Asset from which the user is trading).
note
- The API will return an estimation for the Trade. Solaris does not guarantee that the Price information contained in the response will be applied during the actual Trade on the platform.
- You can only use this endpoint with a Trading Pair that has an
is_tradable
value oftrue
.
Request URL:
GET /v1/trading/pairs/{trading_pair_id}/simulate_trade?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 theamount
query parameter in the original request; otherwise, it will default to thefrom_asset_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 usingtraded_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.
// 200 OK
{
"trading_pair_id": "00000000000000000000000000000001trpr",
"from_amount": "1.12300000",
"traded_from_amount": "1.12300000",
"traded_to_amount": "10056.47",
"to_amount": "9955.90",
"price": "9000.01",
"fee_amount": "100.57",
"created_at": "2020-07-16T11:26:41Z",
"updated_at": "2020-07-16T11:26:41Z"
}
GET Retrieve the Price of a Trading Pair
To retrieve information about the price of a Trading Price for reference purposes, use the following endpoint:
Request URL:
GET /v1/trading/pairs/{trading_pair_id}/price
Response example:
{
"trading_pair_id": "00000000000000000000000000000001trpr",
"from_amount": "1.12300000",
"to_amount": "10107.01",
"price": "9000.01",
"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 returnedprice
was valid.ends_at
: The date/time when the returnedprice
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 inamount
.amount
: A string, in EUR (with EUR asset precision), that represents the maximum cumulative amount of Trades allowed within the number of seconds specified ininterval
.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 usingamount - sum(Traded amounts in EUR)
, where thesum
represents a cumulative trade amount during a given time window that has itsstart time
defined asDATE NOW - interval
and itsend time
asDATE NOW
.
// 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:
- Call the POST Create a Trade endpoint.
- 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 thefrom_account
and at least equal themin_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
isSOBKDEB2XXX
. - The
type
isWALLET_PERSONAL
,WALLET_BUSINESS
,CHECKING_PERSONAL
, orCHECKING_BUSINESS
. - The
locking_status
isNO_BLOCK
. - The
status
isACTIVE
.
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:
{
"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.
{
"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 asfilled_from_amount / traded_from_amount
and rounded to theprice_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:
// 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.