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
OrderlyKeyaccording 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();
};
}, []);
//...
};