• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nktkas / hyperliquid / 16583192762

29 Jul 2025 12:09AM UTC coverage: 90.806% (-4.9%) from 95.69%
16583192762

push

github

nktkas
chore: fix deno check

366 of 500 branches covered (73.2%)

Branch coverage included in aggregate %.

2903 of 3100 relevant lines covered (93.65%)

434.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.67
/src/clients/multiSign.ts
1
import type { IRequestTransport } from "../transports/base.ts";
2
import type {
3
    CancelSuccessResponse,
4
    CreateSubAccountResponse,
5
    CreateVaultResponse,
6
    Hex,
7
    OrderSuccessResponse,
8
    SuccessResponse,
9
    TwapCancelSuccessResponse,
10
    TwapOrderSuccessResponse,
11
} from "../types/mod.ts";
12
import { ExchangeClient, type ExchangeClientParameters } from "./exchange.ts";
114✔
13
import {
114✔
14
    type AbstractWallet,
15
    type actionSorter,
16
    getWalletAddress,
114✔
17
    signL1Action,
114✔
18
    signUserSignedAction,
114✔
19
    userSignedActionEip712Types,
114✔
20
} from "../signing/mod.ts";
114✔
21

22
/** Parameters for the {@linkcode MultiSignClient} constructor. */
23
export interface MultiSignClientParameters<
24
    T extends IRequestTransport = IRequestTransport,
25
    S extends readonly AbstractWallet[] = AbstractWallet[],
26
> extends Omit<ExchangeClientParameters<T, S[0]>, "wallet"> {
27
    /** The multi-signature account address. */
28
    multiSignAddress: Hex;
29
    /** Array of wallets used for multi-signature operations. The first wallet acts as the leader. */
30
    signers: S;
31
}
32

33
/**
34
 * Multi-signature exchange client for interacting with the Hyperliquid API.
35
 * @typeParam T The transport used to connect to the Hyperliquid API.
36
 * @typeParam S Array of wallets where the first wallet acts as the leader.
37
 */
38
export class MultiSignClient<
114✔
39
    T extends IRequestTransport = IRequestTransport,
40
    S extends readonly AbstractWallet[] = AbstractWallet[],
41
> extends ExchangeClient<T, S[0]> implements MultiSignClientParameters<T, S> {
114✔
42
    multiSignAddress: Hex;
114✔
43
    signers: S;
114✔
44

45
    /**
46
     * @multisign Is the first wallet from {@linkcode signers}. Changing the property also changes the first element in the {@linkcode signers} array.
47
     */
48
    declare wallet: S[0];
49

50
    /**
51
     * Initialises a new multi-signature client instance.
52
     * @param args - The parameters for the multi-signature client.
53
     *
54
     * @example
55
     * ```ts
56
     * import * as hl from "@nktkas/hyperliquid";
57
     *
58
     * const multiSignAddress = "0x...";
59
     * const signers = [
60
     *   "0x...", // private key; or any other wallet libraries
61
     * ] as const;
62
     *
63
     * const transport = new hl.HttpTransport();
64
     * const multiSignClient = new hl.MultiSignClient({ transport, multiSignAddress, signers });
65
     * ```
66
     */
67
    constructor(args: MultiSignClientParameters<T, S>) {
114✔
68
        super({ ...args, wallet: args.signers[0] });
612✔
69
        this.multiSignAddress = args.multiSignAddress;
153✔
70
        this.signers = args.signers;
153✔
71

72
        Object.defineProperty(this, "wallet", {
153✔
73
            get() {
153✔
74
                return this.signers[0];
445✔
75
            },
153✔
76
            set(value) {
×
77
                this.signers[0] = value;
×
78
            },
×
79
            enumerable: true,
153✔
80
            configurable: true,
153✔
81
        });
153✔
82
    }
153✔
83

84
    protected override async _executeL1Action<
114✔
85
        T extends
86
            | SuccessResponse
87
            | CancelSuccessResponse
88
            | CreateSubAccountResponse
89
            | CreateVaultResponse
90
            | OrderSuccessResponse
91
            | TwapOrderSuccessResponse
92
            | TwapCancelSuccessResponse,
93
    >(
94
        request: {
114✔
95
            action: Parameters<
96
                typeof actionSorter[
97
                    Exclude<keyof typeof actionSorter, keyof typeof userSignedActionEip712Types>
98
                ]
99
            >[0];
100
            vaultAddress?: Hex;
101
            expiresAfter: number | undefined;
102
        },
114✔
103
        signal?: AbortSignal,
114✔
104
    ): Promise<T> {
114✔
105
        const { action, vaultAddress, expiresAfter } = request;
182✔
106

107
        // Sign an L1 action
108
        const nonce = await this.nonceManager();
182✔
109
        const outerSigner = await getWalletAddress(this.signers[0]);
182✔
110
        const signatures = await Promise.all(this.signers.map(async (signer) => {
182✔
111
            return await signL1Action({
250✔
112
                wallet: signer,
250✔
113
                action: [this.multiSignAddress.toLowerCase(), outerSigner.toLowerCase(), action],
1,250✔
114
                nonce,
250✔
115
                isTestnet: this.isTestnet,
250✔
116
                vaultAddress,
250✔
117
                expiresAfter,
250✔
118
            });
250✔
119
        }));
182✔
120

121
        // Send a request via multi-sign action
122
        return await super.multiSig(
182✔
123
            {
182✔
124
                signatures,
182✔
125
                payload: {
182✔
126
                    multiSigUser: this.multiSignAddress,
182✔
127
                    outerSigner,
182✔
128
                    action,
182✔
129
                },
182✔
130
                nonce,
182✔
131
            },
182✔
132
            { signal, vaultAddress, expiresAfter },
910✔
133
        );
134
    }
182✔
135

136
    protected override async _executeUserSignedAction<
114✔
137
        T extends
138
            | SuccessResponse
139
            | CancelSuccessResponse
140
            | CreateSubAccountResponse
141
            | CreateVaultResponse
142
            | OrderSuccessResponse
143
            | TwapOrderSuccessResponse
144
            | TwapCancelSuccessResponse,
145
    >(
146
        request: {
114✔
147
            action: Parameters<
148
                typeof actionSorter[
149
                    Exclude<Extract<keyof typeof actionSorter, keyof typeof userSignedActionEip712Types>, "multiSig">
150
                ]
151
            >[0];
152
        },
114✔
153
        signal?: AbortSignal,
114✔
154
    ): Promise<T> {
114✔
155
        const { action } = request;
165✔
156

157
        // Sign a user-signed action
158
        const nonce = "nonce" in action ? action.nonce : action.time;
165✔
159
        const outerSigner = await getWalletAddress(this.signers[0]);
165✔
160
        const signatures = await Promise.all(this.signers.map(async (signer) => {
165✔
161
            return await signUserSignedAction({
216✔
162
                wallet: signer,
216✔
163
                action: {
216✔
164
                    payloadMultiSigUser: this.multiSignAddress,
216✔
165
                    outerSigner,
216✔
166
                    ...action,
216✔
167
                },
216✔
168
                types: userSignedActionEip712Types[action.type],
216✔
169
            });
216✔
170
        }));
165✔
171

172
        // Send a request via multi-sign action
173
        return await super.multiSig(
165✔
174
            {
165✔
175
                signatures,
165✔
176
                payload: {
165✔
177
                    multiSigUser: this.multiSignAddress,
165✔
178
                    outerSigner,
165✔
179
                    action,
165✔
180
                },
165✔
181
                nonce,
165✔
182
            },
165✔
183
            { signal },
495✔
184
        );
185
    }
165✔
186
}
114✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc