@0xmonaco/core 1.0.83 → 1.0.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,7 +25,7 @@
25
25
  * );
26
26
  * ```
27
27
  */
28
- import type { AuthAPI, AuthState, ChallengeResponse, SessionCredentials, SessionRefreshResponse } from "@0xmonaco/types";
28
+ import type { AuthAPI, AuthState, ChallengeResponse, InviteCodeList, InviteCodeRequestSummary, SessionCredentials, SessionRefreshResponse } from "@0xmonaco/types";
29
29
  import type { Chain, WalletClient } from "viem";
30
30
  import { BaseAPI } from "../base";
31
31
  export declare class AuthAPIImpl extends BaseAPI implements AuthAPI {
@@ -69,7 +69,7 @@ export declare class AuthAPIImpl extends BaseAPI implements AuthAPI {
69
69
  * console.log(`User ID: ${authResult.user.id}`);
70
70
  * ```
71
71
  */
72
- authenticate(clientId: string, referralCode?: string): Promise<AuthState>;
72
+ authenticate(clientId: string, referralCode?: string, inviteCode?: string): Promise<AuthState>;
73
73
  /**
74
74
  * Signs a challenge message using the wallet client.
75
75
  *
@@ -149,7 +149,11 @@ export declare class AuthAPIImpl extends BaseAPI implements AuthAPI {
149
149
  * console.log(`Session public key: ${authResult.sessionPublicKey}`);
150
150
  * ```
151
151
  */
152
- verifySignature(address: string, signature: string, nonce: string, clientId: string, session: SessionCredentials, referralCode?: string): Promise<AuthState>;
152
+ verifySignature(address: string, signature: string, nonce: string, clientId: string, session: SessionCredentials, referralCode?: string, inviteCode?: string): Promise<AuthState>;
153
+ /** Mint one code: one initial allowance plus one per 250,000 USDC of Mainnet volume. */
154
+ requestInviteCodes(): Promise<InviteCodeRequestSummary>;
155
+ /** Read the allowance and minted codes. Read-only: never consumes a slot. */
156
+ listInviteCodes(): Promise<InviteCodeList>;
153
157
  /**
154
158
  * Refreshes the current session's expiry.
155
159
  *
@@ -75,7 +75,7 @@ export class AuthAPIImpl extends BaseAPI {
75
75
  * console.log(`User ID: ${authResult.user.id}`);
76
76
  * ```
77
77
  */
78
- async authenticate(clientId, referralCode) {
78
+ async authenticate(clientId, referralCode, inviteCode) {
79
79
  if (!this.walletClient) {
80
80
  throw new InvalidConfigError("Wallet client not set. Connect a wallet first.", "walletClient");
81
81
  }
@@ -95,7 +95,7 @@ export class AuthAPIImpl extends BaseAPI {
95
95
  // 3. Sign the challenge message with the wallet
96
96
  const signature = await this.signChallenge(challenge.message);
97
97
  // 4. Verify signature, registering the session public key (and optional referral)
98
- return await this.verifySignature(account.address, signature, challenge.nonce, clientId, session, referralCode);
98
+ return await this.verifySignature(account.address, signature, challenge.nonce, clientId, session, referralCode, inviteCode);
99
99
  }
100
100
  /**
101
101
  * Signs a challenge message using the wallet client.
@@ -204,7 +204,7 @@ export class AuthAPIImpl extends BaseAPI {
204
204
  * console.log(`Session public key: ${authResult.sessionPublicKey}`);
205
205
  * ```
206
206
  */
207
- async verifySignature(address, signature, nonce, clientId, session, referralCode) {
207
+ async verifySignature(address, signature, nonce, clientId, session, referralCode, inviteCode) {
208
208
  const responseBody = await this.makePublicRequest("/api/v1/auth/verify", {
209
209
  method: "POST",
210
210
  body: JSON.stringify({
@@ -215,6 +215,7 @@ export class AuthAPIImpl extends BaseAPI {
215
215
  chainId: this.chain.id,
216
216
  sessionPublicKey: session.publicKey,
217
217
  ...(referralCode ? { referralCode } : {}),
218
+ ...(inviteCode ? { inviteCode } : {}),
218
219
  }),
219
220
  });
220
221
  return {
@@ -234,6 +235,19 @@ export class AuthAPIImpl extends BaseAPI {
234
235
  ...(responseBody.referralApplied !== undefined ? { referralApplied: responseBody.referralApplied } : {}),
235
236
  };
236
237
  }
238
+ /** Mint one code: one initial allowance plus one per 250,000 USDC of Mainnet volume. */
239
+ async requestInviteCodes() {
240
+ return await this.makeAuthenticatedRequest("/api/v1/invite-codes/requests", {
241
+ method: "POST",
242
+ body: JSON.stringify({}),
243
+ });
244
+ }
245
+ /** Read the allowance and minted codes. Read-only: never consumes a slot. */
246
+ async listInviteCodes() {
247
+ return await this.makeAuthenticatedRequest("/api/v1/invite-codes", {
248
+ method: "GET",
249
+ });
250
+ }
237
251
  /**
238
252
  * Refreshes the current session's expiry.
239
253
  *
@@ -40,6 +40,19 @@ function readOptionalString(source, field) {
40
40
  }
41
41
  return value;
42
42
  }
43
+ /**
44
+ * Read an optional decimal-string field: absent (or `null`) is `undefined`,
45
+ * and a present value must be a non-empty string. An empty string is
46
+ * rejected rather than surfaced, because a client converting it with
47
+ * `Number("")` would read it as zero.
48
+ */
49
+ function readOptionalDecimalString(source, field) {
50
+ const value = readOptionalString(source, field);
51
+ if (value === "") {
52
+ throw new Error(`Invalid WebSocket event: ${field} must not be empty`);
53
+ }
54
+ return value;
55
+ }
43
56
  /**
44
57
  * Read a field the server serializes as an explicit `null` when unset.
45
58
  *
@@ -377,6 +390,11 @@ function parseAccountEventData(raw) {
377
390
  freeCollateral: readString(data, "freeCollateral"),
378
391
  marginRatio: readString(data, "marginRatio"),
379
392
  maintenanceRequirement: readString(data, "maintenanceRequirement"),
393
+ // Optional so a frame from an older server parses; a present value must
394
+ // still be a non-empty decimal string, or the frame is rejected.
395
+ initialMarginRequired: readOptionalDecimalString(data, "initialMarginRequired"),
396
+ withdrawableCollateral: readOptionalDecimalString(data, "withdrawableCollateral"),
397
+ realizedPnl: readOptionalDecimalString(data, "realizedPnl"),
380
398
  updatedAt: readString(data, "updatedAt"),
381
399
  };
382
400
  }
@@ -800,8 +818,10 @@ function parseBalanceSnapshotItem(raw) {
800
818
  *
801
819
  * The optional fields are read as nullable, not optional: they are Rust
802
820
  * `Option`s serialized without `skip_serializing_if`, so the key is always
803
- * present carrying `null`. `clientOrderId` is the one field the server omits
804
- * outright, so it is the one read as optional.
821
+ * present carrying `null`. The fields the server omits outright
822
+ * (`clientOrderId`, `selfTradePreventionMode`, `parentOrderId`, `postOnly`,
823
+ * `expirationDate`, `triggerPrice`, `positionSide`, `version` and `origin`) are
824
+ * read as optional and spread in only when present.
805
825
  */
806
826
  function parseOrderSnapshotItem(raw) {
807
827
  if (!isRecord(raw)) {
@@ -819,6 +839,7 @@ function parseOrderSnapshotItem(raw) {
819
839
  const triggerPrice = readOptionalString(item, "triggerPrice");
820
840
  const positionSide = readOptionalString(item, "positionSide");
821
841
  const version = readOptionalNumber(item, "version");
842
+ const origin = readOptionalString(item, "origin");
822
843
  return {
823
844
  orderId: readString(item, "orderId"),
824
845
  userId: readString(item, "userId"),
@@ -866,6 +887,10 @@ function parseOrderSnapshotItem(raw) {
866
887
  // than becoming `version: undefined` — a resync compares this value, and
867
888
  // absent means unknown, never zero (0XM-2440).
868
889
  ...(version === undefined ? {} : { version }),
890
+ // Read as a plain string, like the value fields above: an unrecognized
891
+ // origin passes through rather than dropping the row, and absent stays
892
+ // absent.
893
+ ...(origin === undefined ? {} : { origin }),
869
894
  };
870
895
  }
871
896
  /**
@@ -1248,6 +1273,9 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1248
1273
  if (msg.code === "AUTH_FAILED") {
1249
1274
  lastAuthError = { code: msg.code, message: msg.message, session: pendingAuthSessions.shift() };
1250
1275
  }
1276
+ else if (msg.code === "ACCOUNT_DEACTIVATED") {
1277
+ lastAuthError = { code: msg.code, message: msg.message, session: pendingAuthSessions.shift() ?? confirmedSession };
1278
+ }
1251
1279
  else if (msg.code === "SESSION_INVALID") {
1252
1280
  lastAuthError = { code: msg.code, message: msg.message, session: confirmedSession ?? pendingAuthSessions[0] };
1253
1281
  }
@@ -1430,7 +1458,10 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1430
1458
  const skewRetry = autoReconnect && authError?.code === "AUTH_FAILED" && SKEW_REJECTION.test(authError.message) && skewAuthRetries < MAX_SKEW_AUTH_RETRIES;
1431
1459
  if (skewRetry)
1432
1460
  skewAuthRetries++;
1433
- const authLoss = !skewRetry && authError !== null && authError.session !== undefined && (authError.code === "AUTH_FAILED" || event.code === 1008);
1461
+ const authLoss = !skewRetry &&
1462
+ authError !== null &&
1463
+ authError.session !== undefined &&
1464
+ (authError.code === "AUTH_FAILED" || authError.code === "ACCOUNT_DEACTIVATED" || event.code === 1008);
1434
1465
  const terminalAuthLoss = authLoss && session === authError.session;
1435
1466
  if (terminalAuthLoss) {
1436
1467
  session = undefined;
@@ -1910,7 +1941,8 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1910
1941
  /**
1911
1942
  * Subscribe to the authenticated user's account-level margin health updates
1912
1943
  * (equity, collateral, free collateral, margin ratio, maintenance
1913
- * requirement). Requires authentication - the user is identified from the
1944
+ * requirement, initial margin required, withdrawable collateral, realized
1945
+ * PnL). Requires authentication - the user is identified from the
1914
1946
  * signed session-key handshake. Detected broadcast lag closes the connection
1915
1947
  * with 1013; reconnect and reconcile missed state. Each frame is a terminal-state snapshot
1916
1948
  * per margin account, not an additive delta.
@@ -34,6 +34,8 @@ export declare const COVERED: {
34
34
  list_twap_order_slices: string;
35
35
  close_position: string;
36
36
  create_challenge: string;
37
+ request_invite_codes: string;
38
+ list_invite_codes: string;
37
39
  create_delegated_session: string;
38
40
  create_order: string;
39
41
  create_sub_account_limit: string;
package/dist/coverage.js CHANGED
@@ -34,6 +34,8 @@ export const COVERED = {
34
34
  list_twap_order_slices: "listTwapOrderSlices",
35
35
  close_position: "closePosition",
36
36
  create_challenge: "createChallenge",
37
+ request_invite_codes: "auth.requestInviteCodes",
38
+ list_invite_codes: "auth.listInviteCodes",
37
39
  create_delegated_session: "createDelegatedSession",
38
40
  create_order: "placeLimitOrder / placeMarketOrder",
39
41
  create_sub_account_limit: "subAccounts.createLimit",
@@ -303,6 +303,12 @@ export declare class APIError extends MonacoCoreError {
303
303
  requestId?: string;
304
304
  retryAfter?: number;
305
305
  });
306
+ /**
307
+ * The server's stable error code from the response envelope's `code` field
308
+ * (e.g. `INVITE_CODE_REQUIRED`, `POST_ONLY_WOULD_CROSS`), when it sent one.
309
+ * Branch on this rather than on the message text.
310
+ */
311
+ get serverCode(): string | undefined;
306
312
  /**
307
313
  * Override toJSON to include API-specific fields with sanitization
308
314
  *
@@ -563,6 +563,19 @@ export class APIError extends MonacoCoreError {
563
563
  this.requestId = options?.requestId;
564
564
  this.retryAfter = options?.retryAfter;
565
565
  }
566
+ /**
567
+ * The server's stable error code from the response envelope's `code` field
568
+ * (e.g. `INVITE_CODE_REQUIRED`, `POST_ONLY_WOULD_CROSS`), when it sent one.
569
+ * Branch on this rather than on the message text.
570
+ */
571
+ get serverCode() {
572
+ const body = this.responseBody;
573
+ if (body && typeof body === "object" && "code" in body) {
574
+ const code = body.code;
575
+ return typeof code === "string" ? code : undefined;
576
+ }
577
+ return undefined;
578
+ }
566
579
  /**
567
580
  * Override toJSON to include API-specific fields with sanitization
568
581
  *
package/dist/sdk.d.ts CHANGED
@@ -62,6 +62,7 @@ export declare class MonacoSDKImpl implements MonacoSDK {
62
62
  * @param clientId - The client ID for authentication
63
63
  * @param options - Optional configuration
64
64
  * @param options.connectWebSocket - Auto-connect WebSocket after login (default: false)
65
+ * @param options.inviteCode - Optional case-sensitive Mainnet invite code
65
66
  *
66
67
  * @example
67
68
  * ```typescript
@@ -79,6 +80,7 @@ export declare class MonacoSDKImpl implements MonacoSDK {
79
80
  */
80
81
  login(clientId: string, options?: {
81
82
  connectWebSocket?: boolean;
83
+ inviteCode?: string;
82
84
  }): Promise<AuthState>;
83
85
  /**
84
86
  * Create and adopt an owner-scoped delegated session.
package/dist/sdk.js CHANGED
@@ -213,6 +213,7 @@ export class MonacoSDKImpl {
213
213
  * @param clientId - The client ID for authentication
214
214
  * @param options - Optional configuration
215
215
  * @param options.connectWebSocket - Auto-connect WebSocket after login (default: false)
216
+ * @param options.inviteCode - Optional case-sensitive Mainnet invite code
216
217
  *
217
218
  * @example
218
219
  * ```typescript
@@ -229,7 +230,7 @@ export class MonacoSDKImpl {
229
230
  * ```
230
231
  */
231
232
  async login(clientId, options) {
232
- this.authState = await this.auth.authenticate(clientId);
233
+ this.authState = await this.auth.authenticate(clientId, undefined, options?.inviteCode);
233
234
  this.propagateSession(this.sessionFromAuthState(this.authState));
234
235
  // Auto-connect WebSocket if requested
235
236
  if (options?.connectWebSocket) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xmonaco/core",
3
- "version": "1.0.83",
3
+ "version": "1.0.85",
4
4
  "type": "module",
5
5
  "homepage": "https://docs.0xmonaco.com/sdk/typescript",
6
6
  "main": "./dist/index.js",
@@ -19,8 +19,8 @@
19
19
  "viem": "^2.45.2"
20
20
  },
21
21
  "dependencies": {
22
- "@0xmonaco/contracts": "1.0.83",
23
- "@0xmonaco/types": "1.0.83",
22
+ "@0xmonaco/contracts": "1.0.85",
23
+ "@0xmonaco/types": "1.0.85",
24
24
  "@noble/curves": "^1.9.1",
25
25
  "@noble/hashes": "^2.4.0",
26
26
  "http-status-codes": "^2.3.0"