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

nktkas / hyperliquid / 19514753888

19 Nov 2025 08:02PM UTC coverage: 94.811% (+0.1%) from 94.685%
19514753888

push

github

nktkas
ci: remove environment for test job

364 of 583 branches covered (62.44%)

Branch coverage included in aggregate %.

12208 of 12677 relevant lines covered (96.3%)

964.38 hits per line

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

96.04
/src/api/exchange/convertToMultiSigUser.ts
1
import * as v from "valibot";
357✔
2

3
// ============================================================
4
// API Schemas
5
// ============================================================
6

7
import { Address, Hex, UnsignedInteger } from "../_base.ts";
357✔
8
import { ErrorResponse, Signature, SuccessResponse } from "./_base/mod.ts";
357✔
9

10
/** Signers configuration for {@linkcode ConvertToMultiSigUserRequest}. */
11
const ConvertToMultiSigUserRequestSigners = /* @__PURE__ */ (() => {
357✔
12
  return v.pipe(
605✔
13
    v.union([
605✔
14
      v.object({
605✔
15
        /** List of authorized user addresses. */
16
        authorizedUsers: v.pipe(
605✔
17
          v.array(Address),
605✔
18
          v.description("List of authorized user addresses."),
605✔
19
        ),
20
        /** Minimum number of signatures required. */
21
        threshold: v.pipe(
605✔
22
          UnsignedInteger,
605✔
23
          v.description("Minimum number of signatures required."),
605✔
24
        ),
25
      }),
605✔
26
      /** Convert a multi-signature account to a single-signature account. */
27
      v.pipe(
605✔
28
        v.null(),
605✔
29
        v.description("Convert a multi-signature account to a single-signature account."),
605✔
30
      ),
31
    ]),
605✔
32
    v.description("Signers configuration for `ConvertToMultiSigUserRequest`"),
605✔
33
  );
34
})();
357✔
35

36
/**
37
 * Convert a single-signature account to a multi-signature account or vice versa.
38
 * @see https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/multi-sig
39
 */
40
export const ConvertToMultiSigUserRequest = /* @__PURE__ */ (() => {
357✔
41
  return v.pipe(
605✔
42
    v.object({
605✔
43
      /** Action to perform. */
44
      action: v.pipe(
605✔
45
        v.object({
605✔
46
          /** Type of action. */
47
          type: v.pipe(
605✔
48
            v.literal("convertToMultiSigUser"),
605✔
49
            v.description("Type of action."),
605✔
50
          ),
51
          /** Chain ID used for signing. */
52
          signatureChainId: v.pipe(
605✔
53
            Hex,
605✔
54
            v.description("Chain ID used for signing."),
605✔
55
          ),
56
          /** HyperLiquid network. */
57
          hyperliquidChain: v.pipe(
605✔
58
            v.union([v.literal("Mainnet"), v.literal("Testnet")]),
2,420✔
59
            v.description("HyperLiquid network."),
605✔
60
          ),
61
          /**
62
           * Signers configuration.
63
           *
64
           * Must be {@linkcode ConvertToMultiSigUserRequestSigners} converted to a string via `JSON.stringify(...)`.
65
           */
66
          signers: v.pipe(
605✔
67
            v.union([
605✔
68
              v.pipe(
605✔
69
                v.string(),
605✔
70
                v.parseJson(),
605✔
71
                ConvertToMultiSigUserRequestSigners,
605✔
72
                v.stringifyJson(),
605✔
73
              ),
74
              v.pipe(
605✔
75
                ConvertToMultiSigUserRequestSigners,
605✔
76
                v.stringifyJson(),
605✔
77
              ),
78
            ]),
605✔
79
            v.description(
605✔
80
              "Signers configuration." +
605✔
81
                "\n\nMust be `ConvertToMultiSigUserRequestSigners` converted to a string via `JSON.stringify(...)`.",
605✔
82
            ),
83
          ),
84
          /** Unique request identifier (current timestamp in ms). */
85
          nonce: v.pipe(
605✔
86
            UnsignedInteger,
605✔
87
            v.description("Unique request identifier (current timestamp in ms)."),
605✔
88
          ),
89
        }),
605✔
90
        v.description("Action to perform."),
605✔
91
      ),
92
      /** Unique request identifier (current timestamp in ms). */
93
      nonce: v.pipe(
605✔
94
        UnsignedInteger,
605✔
95
        v.description("Unique request identifier (current timestamp in ms)."),
605✔
96
      ),
97
      /** Cryptographic signature. */
98
      signature: v.pipe(
605✔
99
        Signature,
605✔
100
        v.description("Cryptographic signature."),
605✔
101
      ),
102
    }),
605✔
103
    v.description("Convert a single-signature account to a multi-signature account or vice versa."),
605✔
104
  );
105
})();
357✔
106
export type ConvertToMultiSigUserRequest = v.InferOutput<typeof ConvertToMultiSigUserRequest>;
107

108
/**
109
 * Successful response without specific data or error response.
110
 * @see https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/multi-sig
111
 */
112
export const ConvertToMultiSigUserResponse = /* @__PURE__ */ (() => {
357✔
113
  return v.pipe(
605✔
114
    v.union([SuccessResponse, ErrorResponse]),
2,420✔
115
    v.description("Successful response without specific data or error response."),
605✔
116
  );
117
})();
357✔
118
export type ConvertToMultiSigUserResponse = v.InferOutput<typeof ConvertToMultiSigUserResponse>;
119

120
// ============================================================
121
// Execution Logic
122
// ============================================================
123

124
import { type DeepImmutable, parser } from "../_base.ts";
357✔
125
import {
357✔
126
  type ExchangeRequestConfig,
127
  type ExcludeErrorResponse,
128
  executeUserSignedAction,
357✔
129
  type ExtractRequestAction,
130
  type ExtractRequestOptions,
131
  getSignatureChainId,
357✔
132
  type MultiSignRequestConfig,
133
} from "./_base/mod.ts";
357✔
134

135
/** Action parameters for the {@linkcode convertToMultiSigUser} function. */
136
export type ConvertToMultiSigUserParameters = ExtractRequestAction<v.InferInput<typeof ConvertToMultiSigUserRequest>>;
137

138
/** Request options for the {@linkcode convertToMultiSigUser} function. */
139
export type ConvertToMultiSigUserOptions = ExtractRequestOptions<v.InferInput<typeof ConvertToMultiSigUserRequest>>;
140

141
/** Successful variant of {@linkcode ConvertToMultiSigUserResponse} without errors. */
142
export type ConvertToMultiSigUserSuccessResponse = ExcludeErrorResponse<ConvertToMultiSigUserResponse>;
143

144
/** EIP-712 types for the {@linkcode convertToMultiSigUser} function. */
145
export const ConvertToMultiSigUserTypes = {
357✔
146
  "HyperliquidTransaction:ConvertToMultiSigUser": [
357✔
147
    { name: "hyperliquidChain", type: "string" },
1,428✔
148
    { name: "signers", type: "string" },
1,428✔
149
    { name: "nonce", type: "uint64" },
1,428✔
150
  ],
151
};
357✔
152

153
/**
154
 * Convert a single-signature account to a multi-signature account or vice versa.
155
 * @param config - General configuration for Exchange API requests.
156
 * @param params - Parameters specific to the API request.
157
 * @param opts - Request execution options.
158
 * @returns Successful response without specific data.
159
 *
160
 * @throws {ApiRequestError} When the API returns an unsuccessful response.
161
 * @throws {TransportError} When the transport layer throws an error.
162
 *
163
 * @see https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/multi-sig
164
 * @example
165
 * ```ts
166
 * import { HttpTransport } from "@nktkas/hyperliquid";
167
 * import { convertToMultiSigUser } from "@nktkas/hyperliquid/api/exchange";
168
 * import { privateKeyToAccount } from "viem/accounts";
169
 *
170
 * const wallet = privateKeyToAccount("0x..."); // viem or ethers
171
 * const transport = new HttpTransport(); // or `WebSocketTransport`
172
 *
173
 * // Convert to multi-sig user
174
 * await convertToMultiSigUser(
175
 *   { transport, wallet },
176
 *   {
177
 *     signers: {
178
 *       authorizedUsers: ["0x...", "0x...", "0x..."],
179
 *       threshold: 2,
180
 *     },
181
 *   },
182
 * );
183
 *
184
 * // Convert to single-sig user
185
 * await convertToMultiSigUser(
186
 *   { transport, wallet },
187
 *   { signers: null },
188
 * );
189
 * ```
190
 */
191
export async function convertToMultiSigUser(
357✔
192
  config: ExchangeRequestConfig | MultiSignRequestConfig,
357✔
193
  params: DeepImmutable<ConvertToMultiSigUserParameters>,
357✔
194
  opts?: ConvertToMultiSigUserOptions,
357✔
195
): Promise<ConvertToMultiSigUserSuccessResponse> {
196
  const request = parser(ConvertToMultiSigUserRequest)({
401✔
197
    action: {
401✔
198
      type: "convertToMultiSigUser",
401✔
199
      hyperliquidChain: config.transport.isTestnet ? "Testnet" : "Mainnet",
×
200
      signatureChainId: await getSignatureChainId(config),
401✔
201
      nonce: 0, // Placeholder; actual nonce generated in `executeUserSignedAction` to prevent race conditions
401✔
202
      ...params,
401✔
203
    },
401✔
204
    nonce: 0, // Placeholder; actual nonce generated in `executeUserSignedAction` to prevent race conditions
401✔
205
    signature: { // Placeholder; actual signature generated in `executeUserSignedAction`
401✔
206
      r: "0x0000000000000000000000000000000000000000000000000000000000000000",
401✔
207
      s: "0x0000000000000000000000000000000000000000000000000000000000000000",
401✔
208
      v: 27,
401✔
209
    },
401✔
210
  });
401✔
211
  return await executeUserSignedAction(config, request, ConvertToMultiSigUserTypes, opts?.signal);
×
212
}
401✔
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