@nktkas/hyperliquid
Version:
Hyperliquid API SDK for all major JS runtimes, written in TypeScript.
41 lines (40 loc) • 1.86 kB
JavaScript
/**
* Common execution shell shared by L1 and user-signed Exchange API actions.
* @module
*/ import { getWalletAddress } from "../../../../signing/mod.js";
import { assertSuccessResponse } from "./errors.js";
import { globalNonceManager } from "./_nonce.js";
import { withLock } from "./_semaphore.js";
/**
* Common shell for executing an Exchange API request:
* acquires per-`(walletAddress × isTestnet)` lock, generates nonce, calls `build` to construct
* the signed payload, sends to the Exchange endpoint, and validates the response.
*
* @param config Exchange API configuration.
* @param build Callback that, given the nonce, returns the action, signature, and any extras.
* @param signal Optional {@link AbortSignal} to cancel the request.
* @return The validated API response.
*
* @throws {ApiRequestError} If the API returns an error response.
*/ export async function executeWithShell(config, build, signal) {
const leader = "wallet" in config ? config.wallet : config.signers[0];
const walletAddress = await getWalletAddress(leader);
// Lock per (wallet × testnet) ensures requests arrive at the server in nonce order.
const key = `${walletAddress}:${config.transport.isTestnet}`;
return await withLock(key, async ()=>{
// --- Generate nonce --------------------------------------
const nonce = await (config.nonceManager?.(walletAddress) ?? globalNonceManager.getNonce(key));
// --- Build signed payload --------------------------------
const { action, signature, extras } = await build(nonce);
// --- Send and validate -----------------------------------
const response = await config.transport.request("exchange", {
action,
signature,
nonce,
...extras
}, signal);
assertSuccessResponse(response);
return response;
});
}
//# sourceMappingURL=_shell.js.map