Account Structure
A wallet owner can register an account on Orderly for each builder that is supported. Each wallet owner could thus have multiple accounts (that are not interlinked with each other) registered with Orderly.Account ID
Each account is identified by an account id, which can be calculated byAccount Registration
To register an account on Orderly:Choose a valid chain/builder to register the account on
List of chains can be found here and supported builders through Get list of builders API.
Obtain a registration nonce
Get a nonce from Get Registration Nonce API.
Example code
Example code
String baseUrl = "https://testnet-api.orderly.org";
OkHttpClient client = new OkHttpClient();
Request nonceReq = new Request.Builder()
.url(baseUrl + "/v1/registration_nonce")
.build();
String nonceRes;
try (Response response = client.newCall(nonceReq).execute()) {
nonceRes = response.body().string();
}
JSONObject nonceObj = new JSONObject(nonceRes);
String registrationNonce = nonceObj.getJSONObject("data").getString("registration_nonce");
base_url = "https://testnet-api.orderly.org"
res = requests.get("%s/v1/registration_nonce" % base_url)
response = json.loads(res.text)
registration_nonce = response["data"]["registration_nonce"]
const BASE_URL = "https://testnet-api.orderly.org";
const nonceRes = await fetch(`${BASE_URL}/v1/registration_nonce`);
const nonceJson = await nonceRes.json();
const registrationNonce = nonceJson.data.registration_nonce as string;
Obtain a signature from EIP-712
Sign a message from the wallet in the following format using the EIP-712 standard and obtain the signature.where:
{
"brokerId": "woofi_dex",
"chainId": 421614,
"timestamp": 1685973017064,
"registrationNonce": "194528949540"
}
| Name | Type | Required | Description |
|---|---|---|---|
| brokerId | string | Y | The unique identifier of the Builder (also known as Broker ID). |
| chainId | int | Y | Chain ID of registering chain (within those that are supported by the Network) |
| timestamp | timestamp | Y | timestamp in UNIX milliseconds |
| registrationNonce | string | Y | Valid nonce from Get Registration Nonce |
Example code
Example code
JSONObject MESSAGE_TYPES = new JSONObject("""
{
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "verifyingContract", "type": "address"},
],
"Registration": [
{"name": "brokerId", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "timestamp", "type": "uint64"},
{"name": "registrationNonce", "type": "uint256"},
],
}""");
JSONObject OFF_CHAIN_DOMAIN = new JSONObject("""
{
"name": "Orderly",
"version": "1",
"chainId": 421614,
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
}""");
String brokerId = "woofi_dex";
int chainId = 421614;
Dotenv dotenv = Dotenv.load();
String pk = dotenv.get("PRIVATE_KEY");
Credentials credentials = Credentials.create(ECKeyPair.create(Hex.decodeHex(pk)));
JSONObject registerMessage = new JSONObject();
registerMessage.put("brokerId", brokerId);
registerMessage.put("chainId", chainId);
registerMessage.put("timestamp", Instant.now().toEpochMilli());
registerMessage.put("registrationNonce", registrationNonce);
JSONObject jsonObject = new JSONObject();
jsonObject.put("types", MESSAGE_TYPES);
jsonObject.put("primaryType", "Registration");
jsonObject.put("domain", OFF_CHAIN_DOMAIN);
jsonObject.put("message", registerMessage);
Sign.SignatureData signature = Sign.signTypedData(jsonObject.toString(), credentials.getEcKeyPair());
MESSAGE_TYPES = {
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "verifyingContract", "type": "address"},
],
"Registration": [
{"name": "brokerId", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "timestamp", "type": "uint64"},
{"name": "registrationNonce", "type": "uint256"},
],
}
OFF_CHAIN_DOMAIN = {
"name": "Orderly",
"version": "1",
"chainId": 421614,
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
}
broker_id = "woofi_dex"
chain_id = 421614
account: Account = Account.from_key(os.environ.get("PRIVATE_KEY"))
import time
timestamp = int(time.time() * 1000)
register_message = {
"brokerId": broker_id,
"chainId": chain_id,
"timestamp": timestamp,
"registrationNonce": registration_nonce,
}
encoded_data = messages.encode_typed_data(
domain_data=OFF_CHAIN_DOMAIN,
message_types={"Registration": MESSAGE_TYPES["Registration"]},
message_data=register_message,
)
signed_message = account.sign_message(encoded_data)
const MESSAGE_TYPES = {
EIP712Domain: [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chainId", type: "uint256" },
{ name: "verifyingContract", type: "address" }
],
Registration: [
{ name: "brokerId", type: "string" },
{ name: "chainId", type: "uint256" },
{ name: "timestamp", type: "uint64" },
{ name: "registrationNonce", type: "uint256" }
]
};
const OFF_CHAIN_DOMAIN = {
name: "Orderly",
version: "1",
chainId: 421614,
verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
};
const BASE_URL = "https://testnet-api.orderly.org";
const BROKER_ID = "woofi_dex";
const CHAIN_ID = 421614;
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!);
const registerMessage = {
brokerId: BROKER_ID,
chainId: CHAIN_ID,
timestamp: Date.now(),
registrationNonce
};
const signature = await wallet.signTypedData(
OFF_CHAIN_DOMAIN,
{
Registration: MESSAGE_TYPES.Registration
},
registerMessage
);
Register account
Send all the necessary information via Register account API.
Example code
Example code
String baseUrl = "https://testnet-api.orderly.org";
JSONObject jsonBody = new JSONObject();
jsonBody.put("message", registerMessage);
jsonBody.put("signature", signatureToHashString(signature));
jsonBody.put("userAddress", credentials.getAddress());
RequestBody body = RequestBody.create(jsonBody.toString(), MediaType.get("application/json"));
Request registerReq = new Request.Builder()
.url(baseUrl + "/v1/register_account")
.post(body)
.build();
String registerRes;
try (Response response = client.newCall(registerReq).execute()) {
registerRes = response.body().string();
}
JSONObject registerObj = new JSONObject(registerRes);
String orderlyAccountId = registerObj.getJSONObject("data").getString("account_id");
System.out.println("orderlyAccountId: " + orderlyAccountId);
// ...
public static String signatureToHashString(Sign.SignatureData signature) {
byte[] retval = new byte[65];
System.arraycopy(signature.getR(), 0, retval, 0, 32);
System.arraycopy(signature.getS(), 0, retval, 32, 32);
System.arraycopy(signature.getV(), 0, retval, 64, 1);
return Numeric.toHexString(retval);
}
base_url = "https://testnet-api.orderly.org"
res = requests.post(
"%s/v1/register_account" % base_url,
headers={"Content-Type": "application/json"},
json={
"message": register_message,
"signature": signed_message.signature.hex(),
"userAddress": account.address,
},
)
response = json.loads(res.text)
orderly_account_id = response["data"]["account_id"]
print("orderly_account_id:", orderly_account_id)
const BASE_URL = "https://testnet-api.orderly.org";
const registerRes = await fetch(`${BASE_URL}/v1/register_account`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
message: registerMessage,
signature,
userAddress: await wallet.getAddress()
})
});
const registerJson = await registerRes.json();
if (!registerJson.success) {
throw new Error(registerJson.message);
}
const orderlyAccountId = registerJson.data.account_id;
console.log("orderlyAccountId", orderlyAccountId);
Full example
import java.time.Instant;
import org.apache.commons.codec.binary.Hex;
import org.json.JSONObject;
import org.web3j.crypto.*;
import io.github.cdimascio.dotenv.Dotenv;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class RegisterExample {
public static JSONObject MESSAGE_TYPES = new JSONObject("""
{
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "verifyingContract", "type": "address"},
],
"Registration": [
{"name": "brokerId", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "timestamp", "type": "uint64"},
{"name": "registrationNonce", "type": "uint256"},
],
}""");
public static JSONObject OFF_CHAIN_DOMAIN = new JSONObject("""
{
"name": "Orderly",
"version": "1",
"chainId": 421614,
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
}""");
public static void main(String[] args) throws Exception {
String baseUrl = "https://testnet-api.orderly.org";
String brokerId = "woofi_dex";
int chainId = 421614;
Dotenv dotenv = Dotenv.load();
String pk = dotenv.get("PRIVATE_KEY");
Credentials credentials = Credentials.create(ECKeyPair.create(Hex.decodeHex(pk)));
OkHttpClient client = new OkHttpClient();
Request nonceReq = new Request.Builder()
.url(baseUrl + "/v1/registration_nonce")
.build();
String nonceRes;
try (Response response = client.newCall(nonceReq).execute()) {
nonceRes = response.body().string();
}
JSONObject nonceObj = new JSONObject(nonceRes);
String registrationNonce = nonceObj.getJSONObject("data").getString("registration_nonce");
JSONObject registerMessage = new JSONObject();
registerMessage.put("brokerId", brokerId);
registerMessage.put("chainId", chainId);
registerMessage.put("timestamp", Instant.now().toEpochMilli());
registerMessage.put("registrationNonce", registrationNonce);
JSONObject jsonObject = new JSONObject();
jsonObject.put("types", MESSAGE_TYPES);
jsonObject.put("primaryType", "Registration");
jsonObject.put("domain", OFF_CHAIN_DOMAIN);
jsonObject.put("message", registerMessage);
Sign.SignatureData signature = Sign.signTypedData(jsonObject.toString(), credentials.getEcKeyPair());
JSONObject jsonBody = new JSONObject();
jsonBody.put("message", registerMessage);
jsonBody.put("signature", signatureToHashString(signature));
jsonBody.put("userAddress", credentials.getAddress());
RequestBody body = RequestBody.create(jsonBody.toString(), MediaType.get("application/json"));
Request registerReq = new Request.Builder()
.url(baseUrl + "/v1/register_account")
.post(body)
.build();
String registerRes;
try (Response response = client.newCall(registerReq).execute()) {
registerRes = response.body().string();
}
JSONObject registerObj = new JSONObject(registerRes);
String orderlyAccountId = registerObj.getJSONObject("data").getString("account_id");
System.out.println("orderlyAccountId: " + orderlyAccountId);
}
public static String signatureToHashString(Sign.SignatureData signature) {
byte[] retval = new byte[65];
System.arraycopy(signature.getR(), 0, retval, 0, 32);
System.arraycopy(signature.getS(), 0, retval, 32, 32);
System.arraycopy(signature.getV(), 0, retval, 64, 1);
return Numeric.toHexString(retval);
}
}
import json
import os
import time
import requests
from eth_account import Account, messages
MESSAGE_TYPES = {
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "verifyingContract", "type": "address"},
],
"Registration": [
{"name": "brokerId", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "timestamp", "type": "uint64"},
{"name": "registrationNonce", "type": "uint256"},
],
}
OFF_CHAIN_DOMAIN = {
"name": "Orderly",
"version": "1",
"chainId": 421614,
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
}
base_url = "https://testnet-api.orderly.org"
broker_id = "woofi_dex"
chain_id = 421614
account: Account = Account.from_key(os.environ.get("PRIVATE_KEY"))
res = requests.get("%s/v1/registration_nonce" % base_url)
response = json.loads(res.text)
registration_nonce = response["data"]["registration_nonce"]
timestamp = int(time.time() * 1000)
register_message = {
"brokerId": broker_id,
"chainId": chain_id,
"timestamp": timestamp,
"registrationNonce": registration_nonce,
}
encoded_data = messages.encode_typed_data(
domain_data=OFF_CHAIN_DOMAIN,
message_types={"Registration": MESSAGE_TYPES["Registration"]},
message_data=register_message,
)
signed_message = account.sign_message(encoded_data)
res = requests.post(
"%s/v1/register_account" % base_url,
headers={"Content-Type": "application/json"},
json={
"message": register_message,
"signature": signed_message.signature.hex(),
"userAddress": account.address,
},
)
response = json.loads(res.text)
orderly_account_id = response["data"]["account_id"]
print("orderly_account_id:", orderly_account_id)
import { config } from "dotenv";
import { ethers } from "ethers";
const MESSAGE_TYPES = {
EIP712Domain: [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chainId", type: "uint256" },
{ name: "verifyingContract", type: "address" }
],
Registration: [
{ name: "brokerId", type: "string" },
{ name: "chainId", type: "uint256" },
{ name: "timestamp", type: "uint64" },
{ name: "registrationNonce", type: "uint256" }
]
};
const OFF_CHAIN_DOMAIN = {
name: "Orderly",
version: "1",
chainId: 421614,
verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
};
const BASE_URL = "https://testnet-api.orderly.org";
const BROKER_ID = "woofi_dex";
const CHAIN_ID = 421614;
config();
async function registerAccount(): Promise<void> {
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!);
const nonceRes = await fetch(`${BASE_URL}/v1/registration_nonce`);
const nonceJson = await nonceRes.json();
const registrationNonce = nonceJson.data.registration_nonce as string;
const registerMessage = {
brokerId: BROKER_ID,
chainId: CHAIN_ID,
timestamp: Date.now(),
registrationNonce
};
const signature = await wallet.signTypedData(
OFF_CHAIN_DOMAIN,
{
Registration: MESSAGE_TYPES.Registration
},
registerMessage
);
const registerRes = await fetch(`${BASE_URL}/v1/register_account`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
message: registerMessage,
signature,
userAddress: await wallet.getAddress()
})
});
const registerJson = await registerRes.json();
if (!registerJson.success) {
throw new Error(registerJson.message);
}
const orderlyAccountId = registerJson.data.account_id;
console.log("orderlyAccountId", orderlyAccountId);
}
registerAccount();
Next Steps
After successfully registering your account, you must enable authentication by binding an Orderly Key. Proceed to the next step:[!WARNING] If you do not bind an Orderly Key to your account, you will not be able to access any private REST APIs or subscribe to private WebSocket streams.