@nktkas/hyperliquid
Version:
Hyperliquid API SDK for all major JS runtimes, written in TypeScript.
121 lines (120 loc) • 3.91 kB
JavaScript
/**
* User-signed ([EIP-712](https://eips.ethereum.org/EIPS/eip-712)) signing for fund and account actions.
* @module
*/ import { signTypedData } from "./_abstractWallet.js";
import { trimSignature } from "./_multiSig.js";
/**
* Signs a user-signed action.
*
* @param args The wallet, action, and EIP-712 types.
* @return The ECDSA signature.
*
* @throws {AbstractWalletError} If signing fails.
*
* @example
* ```ts
* import { signUserSignedAction } from "@nktkas/hyperliquid/signing";
* import { ApproveAgentTypes } from "@nktkas/hyperliquid/api/exchange";
* import { privateKeyToAccount } from "npm:viem/accounts";
*
* const wallet = privateKeyToAccount("0x..."); // `viem` or `ethers` or any `AbstractWallet`
*
* const types = ApproveAgentTypes; // or custom EIP-712 types matching the action
* const action = {
* type: "approveAgent",
* signatureChainId: "0x66eee" as const,
* hyperliquidChain: "Mainnet",
* agentAddress: "0x...",
* agentName: "Agent",
* nonce: Date.now(),
* };
*
* const signature = await signUserSignedAction({ wallet, action, types });
* ```
*
* @example
* \- Full cycle of signing and sending a user-signed action to the Hyperliquid API
* ```ts
* import { signUserSignedAction } from "@nktkas/hyperliquid/signing";
* import { ApproveAgentTypes } from "@nktkas/hyperliquid/api/exchange";
* import { privateKeyToAccount } from "npm:viem/accounts";
*
* const wallet = privateKeyToAccount("0x..."); // `viem` or `ethers` or any `AbstractWallet`
*
* const types = ApproveAgentTypes; // or custom EIP-712 types matching the action
* const action = {
* type: "approveAgent",
* signatureChainId: "0x66eee" as const,
* hyperliquidChain: "Mainnet",
* agentAddress: "0x...",
* agentName: "Agent",
* nonce: Date.now(),
* };
*
* const signature = await signUserSignedAction({ wallet, action, types });
*
* // Send the signed action to the Hyperliquid API
* const response = await fetch("https://api.hyperliquid.xyz/exchange", {
* method: "POST",
* headers: { "Content-Type": "application/json" },
* body: JSON.stringify({ action, signature, nonce: action.nonce }),
* });
* const body = await response.json();
* ```
*/ export async function signUserSignedAction(args) {
const { wallet, action, types } = args;
return await signTypedData({
wallet,
domain: {
name: "HyperliquidSignTransaction",
version: "1",
chainId: parseInt(action.signatureChainId),
verifyingContract: "0x0000000000000000000000000000000000000000"
},
types,
primaryType: Object.keys(types)[0],
message: action
});
}
/**
* Signs an inner per-signer contribution to a multi-sig user-signed action.
*
* Signs the action with `payloadMultiSigUser` and `outerSigner` fields injected
* (using a type extended after its first field); the returned signature is
* trimmed for inclusion in the multi-sig wrapper.
*
* @param args The signer, action, types, and signing parameters.
* @return The trimmed ECDSA signature.
*
* @throws {AbstractWalletError} If signing fails.
*/ export async function signUserSignedInner(args) {
// Inject fields for multi-sig
const primaryType = Object.keys(args.types)[0];
const primaryTypeFields = args.types[primaryType];
const extendedTypes = {
...args.types,
[primaryType]: [
primaryTypeFields[0],
{
name: "payloadMultiSigUser",
type: "address"
},
{
name: "outerSigner",
type: "address"
},
...primaryTypeFields.slice(1)
]
};
const signature = await signUserSignedAction({
wallet: args.signer,
action: {
payloadMultiSigUser: args.multiSigUser.toLowerCase(),
outerSigner: args.outerSigner.toLowerCase(),
...args.action
},
types: extendedTypes
});
return trimSignature(signature);
}
//# sourceMappingURL=_userSigned.js.map