Generate Request Signature

Orderly Network uses the ed25519 elliptic curve standard for request authentication via signature verification. The necessary steps in order to send a valid request to Orderly Network are provided below.

1

Orderly account ID

Before being able to authenticate, you must first register your account and get your account ID. The registration steps are provided here. You need to add your account ID to the request header as orderly-account-id.

2

Access key (Orderly key)

Your Orderly public key needs to be added to the request header as orderly-key. To generate and add a new Orderly key, please refer to the documentation. You can also get Orderly keys from frontend brokers like WOOFi Pro.

3

Timestamp

Take the timestamp of the request in milliseconds and add it as orderly-timestamp to the request header.

4

Normalize request content

The message that you need to sign with your Orderly private key needs to be normalized to a string via this method:

  1. Get current timestamp in milliseconds, e.g. 1649920583000
  2. Append HTTP method in uppercase, e.g. POST
  3. Append path of request including query parameters (without base URL), e.g. /v1/orders?symbol=PERP_BTC_USDC
  4. (optional) If request has method body, JSON stringify this and append it

The resulting string could look like following:

1649920583000POST/v1/order{"symbol": "PERP_ETH_USDC", "order_type": "LIMIT", "order_price": 1521.03, "order_quantity": 2.11, "side": "BUY"}
5

Generate a signature

Use the normalized request content to generate a signature using the ed25519 algorithm, and encode the signature in base64 url-safe format. Add the result to the request headers as orderly-signature.

6

Content type

Add Content-Type header. All GET and DELETE requests use application/x-www-form-urlencoded. Any other method type uses application/json.

7

Send the request

The final request should have following headers:

Content-Type, orderly-account-id, orderly-key, orderly-signature, orderly-timestamp

Full example

import java.security.spec.PKCS8EncodedKeySpec;

import io.github.cdimascio.dotenv.Dotenv;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import org.bitcoinj.base.Base58;
import org.json.JSONObject;

public class AuthenticationExample {
   public static void main(String[] args) throws Exception {
      String baseUrl = "https://testnet-api-evm.orderly.org";
      String orderlyAccountId = "<orderly-account-id>";

      Dotenv dotenv = Dotenv.load();
      OkHttpClient client = new OkHttpClient();

      String key = dotenv.get("ORDERLY_SECRET");
      PKCS8EncodedKeySpec encoded = new PKCS8EncodedKeySpec(Base58.decode(key));
      EdDSAPrivateKey orderlyKey = new EdDSAPrivateKey(encoded);

      Signer signer = new Signer(baseUrl, orderlyAccountId, orderlyKey);

      JSONObject json = new JSONObject();
      json.put("symbol", "PERP_ETH_USDC");
      json.put("order_type", "MARKET");
      json.put("order_quantity", 0.01);
      json.put("side", "BUY");
      Request req = signer.createSignedRequest("/v1/order", "POST", json);
      String res;
      try (Response response = client.newCall(req).execute()) {
         res = response.body().string();
      }
      JSONObject obj = new JSONObject(res);
   }
}

Security

There is a three-layer checker to verify a request is valid. Orderly server only accepts the request that passes all checks. The checker contains the following:

Request Timestamp

The request would be considered expired and get rejected if the timestamp in orderly-timestamp header have 300+ seconds difference from the API server time.

HMAC Parameter Signature

The request must have a orderly-signature header that is generate from request parameters and signed with your Orderly secret key.

Orderly Key Validity Check

The request must have an orderly-key header, and the orderly-key has to be added to the network via the Add Key functionality, matched with the account and is still valid (not expired yet).