Docs
Hooks
API request

API requests

Orderly provides both public and private APIs. Public APIs can be visited directly. Private APIs requires authentication and signatures, and these can be performed using hooks from @orderly.network/hooks.

Reminder: Normally you would not have to use the following hooks, as @orderly.network/hooks already implements higher level hooks on top of the request module. For example, you can use usePositionStream for position management, and useOrderEntry for order placement. You may consider to use these hooks if you want to build out more advanced usage of Orderly, or if the provided hooks are not suitable for your use case.

RESTful API

@orderly.network/hooks provides the following hooks for builders to access Orderly's RESTful APIs:

The above hooks are based on swr (opens in a new tab), and have the following properties:

  • Request responses are cached. Cached data are used in priority according to the config, and is used as a global status management.
  • Removes any duplicate requests. When request parameters are the same, it will automatically cancel the duplicate request
  • When the window is focused or when the connection is recovered, automatically retries requests.
  • Automatically retries any failed network requests.
  • For more information, please check the official swr documentation (opens in a new tab).

Public APIs

Use useQuery to access any Public API, for example to get all available symbols on Orderly:

() => {
  const { data, error, loading } = useQuery<API.Symbol[]>("/v1/public/info");

  return (
    <pre className="text-sm">
      {loading && <div>Loading...</div>}
      {data && (
        <div className="text-slate-500">{JSON.stringify(data, null, 2)}</div>
      )}
    </pre>
  );
};

The data returned by useQuery is already serialized in JSON format. If you want to access the raw data, you can provide a formatter to override the default serialization of the hook. For example:

import { useQuery } from "@orderly.network/hooks";
 
const { data, error } = useQuery("/v1/public/info", {
  formatter: (data) => data,
});

Private APIs

Use usePrivateQuery, usePrivateInfiniteQuery or useMutation to access any Private API. These are slightly different from useQuery:

  • These have a built-in account status check. Builders do not have to check the current login status of the user. If the user has not logged in, the request will not be sent until the user status has changed to a logged in status.
  • These will automatically sign all requests using the OrderlyKey according to Orderly's standards.

Use usePrivateQuery to access a private API, for example to get the current user info:

const {usePrivateQuery} from "@orderly.network/hooks";
 
export const Example = ()=>{
  const {data,loading,error} = usePrivateQuery<API.AccountInfo>("/v1/client/info");
  //...
}
() => {
  const { data, loading, error } = usePrivateQuery("/v1/client/info");

  if (loading) return <div>loading...</div>;

  return (
    <div>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
};

Mutation

Note: useQuery/usePrivateQuery can only be used for GET requests.

For POST, PUT or DELETE requests, please use useMutation. For example to create a new order:

import { useMutation } from "@orderly.network/hooks";
 
const [createOrder, { data, error, isMutating }] = useMutation<
  OrderEntity,
  any
>("/v1/order");

Infinite scrolling

Position list or order lists typically requires pagination to load all the data. If an infinite scrolling effect has to be implemented, usePrivateInfiniteQuery can be used to help builders.

Slightly different from sending a incremental page parameter, usePrivateInfiniteQuery will append data from the next page to data, and not replacing the current response.

For example, to get the list of orders:

const { data: orders } = usePrivateInfiniteQuery(
  (pageIndex: number, previousPageData) => {
    // reached the end
    if (previousPageData && !previousPageData.length) return null;
 
    const search = new URLSearchParams([
      ["size", size.toString()],
      ["page", `${pageIndex + 1}`],
    ]);
 
    // order status
    if (status) {
      search.set(`status`, status);
    }
 
    if (symbol) {
      search.set(`symbol`, symbol);
    }
 
    if (side) {
      search.set(`side`, side);
    }
 
    return `/v1/orders?${search.toString()}`;
  },
  {
    initialSize: 1,
    onError: (err) => {
      console.error("fetch failed::::", err);
    },
  }
);
💡

Why are we creating different hooks for different http methods, instead of determining GET vs POST through a parameter?

  • Single responsibility principle: A function should only be responisble for one thing.

  • Reduces the complexity of the code, and prevents uncertainty from any side effects of the implementation.

WebSocket

@orderly.network/hooks provides a useWS hook for accessing Orderly's Websocket API. useWS returns the WS instance of @orderly.network/net. Builders can use WS to subscribe, cancel, or to send messages through the websocket. For more information, please see WS

For all available topics of the websocket, please check the websocket API documentation.

Subscribing to public topics

subscribe(
    topic: string|{[key:string]:any},
    callback: WSMessageHandler | Omit<WSMessageHandler, "onUnsubscribe">,
    once?: boolean,
    id?: string
  ): unsubscribe | undefined
 

Subscribing to the trade topic:

import { useEffect } from "react";
import { useWS } from "@orderly.network/hooks";
 
export const Example = () => {
  const ws = useWS();
 
  useEffect(() => {
    const unsubscript = ws.subscribe(
      {
        id: `${symbol}@trade`,
        event: "subscribe",
        topic: `${symbol}@trade`,
        ts: Date.now(),
      },
      {
        onMessage: (data: any) => {
          //
        },
      }
    );
    () => {
      // Unsubscribes when the component unloads
      unsubscribe();
    };
  }, []);
 
  //...
};

Subscribing to private topics

subscribe(
    topic: string|{[key:string]:any},
    callback: WSMessageHandler | Omit<WSMessageHandler, "onUnsubscribe">,
    once?: boolean,
    id?: string
  ): unsubscribe | undefined
 

Subscribing to the executionreport topic:

import { useWS } from "@orderly.network/hooks";
 
export const Example = () => {
  const ws = useWS();
 
  useEffect(() => {
    const unsubscript = ws.privateSubscribe(
      {
        id: "executionreport",
        event: "subscribe",
        topic: "executionreport",
        ts: Date.now(),
      },
      {
        onMessage: (data) => {
          // do something
        },
      }
    );
    () => {
      // Unsubscribes when the component unloads
      unsubscribe();
    };
  }, []);
 
  //...
};