@0xmonaco/core 1.0.94 → 1.0.97

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.
@@ -1109,6 +1109,13 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1109
1109
  // with nothing confirmed and re-requests what is wanted.
1110
1110
  const confirmedChannels = new Set();
1111
1111
  let pendingRequests = [];
1112
+ // First subscribers of the current tick on the open socket, in call order,
1113
+ // not yet sent. The server reads one command at a time, so a Subscribe per
1114
+ // channel would hold each later channel's first frame behind the earlier
1115
+ // ones' snapshot reads; they go out together as one Subscribe instead. A
1116
+ // request enters `pendingRequests` only when its frame is sent.
1117
+ let queuedSubscribes = [];
1118
+ let subscribeFlushScheduled = false;
1112
1119
  // Wanted channels the server rejected with AUTH_REQUIRED on this socket,
1113
1120
  // re-requested once when the connection next authenticates.
1114
1121
  const authRejectedChannels = new Set();
@@ -1283,13 +1290,50 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1283
1290
  pendingRequests.push({ kind: "unsubscribe", channels });
1284
1291
  send({ type: "Unsubscribe", channels });
1285
1292
  };
1293
+ /** Send the channels queued this tick as one Subscribe. */
1294
+ const flushQueuedSubscribes = () => {
1295
+ const channels = queuedSubscribes;
1296
+ queuedSubscribes = [];
1297
+ sendSubscribe(channels);
1298
+ };
1299
+ /**
1300
+ * Queue a first subscriber's Subscribe for the end of the current tick.
1301
+ * Only on an open socket: otherwise the next open's resubscribe sends it.
1302
+ */
1303
+ const queueSubscribe = (channel) => {
1304
+ if (ws?.readyState !== WebSocket.OPEN)
1305
+ return;
1306
+ queuedSubscribes.push(channel);
1307
+ if (subscribeFlushScheduled)
1308
+ return;
1309
+ subscribeFlushScheduled = true;
1310
+ queueMicrotask(() => {
1311
+ subscribeFlushScheduled = false;
1312
+ flushQueuedSubscribes();
1313
+ });
1314
+ };
1315
+ /**
1316
+ * Drop a channel released before its queued Subscribe went out. Returns
1317
+ * whether it was queued: the server was never asked for it, so there is
1318
+ * nothing to unsubscribe.
1319
+ */
1320
+ const unqueueSubscribe = (channel) => {
1321
+ const index = queuedSubscribes.indexOf(channel);
1322
+ if (index === -1)
1323
+ return false;
1324
+ queuedSubscribes.splice(index, 1);
1325
+ return true;
1326
+ };
1286
1327
  /** Forget everything the server confirmed or was asked on the old socket. */
1287
1328
  const resetSubscriptionAcks = () => {
1288
1329
  confirmedChannels.clear();
1289
1330
  pendingRequests = [];
1331
+ queuedSubscribes = [];
1290
1332
  authRejectedChannels.clear();
1291
1333
  };
1292
- const isRequested = (kind, channel) => pendingRequests.some((request) => request.kind === kind && request.channels.includes(channel));
1334
+ // A queued Subscribe counts as requested: it goes out this tick.
1335
+ const isRequested = (kind, channel) => (kind === "subscribe" && queuedSubscribes.includes(channel)) ||
1336
+ pendingRequests.some((request) => request.kind === kind && request.channels.includes(channel));
1293
1337
  const getSubscriptionState = (channel) => {
1294
1338
  if (handlers.has(channel)) {
1295
1339
  if (isRequested("subscribe", channel))
@@ -1687,7 +1731,7 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1687
1731
  }
1688
1732
  // Only send Subscribe message on first subscriber for this channel
1689
1733
  if (isFirstSubscriber) {
1690
- sendSubscribe([channel]);
1734
+ queueSubscribe(channel);
1691
1735
  }
1692
1736
  // Return unsubscribe function
1693
1737
  return () => {
@@ -1704,7 +1748,9 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1704
1748
  // Only send Unsubscribe on last subscriber for this channel
1705
1749
  if (channelHandlers.size === 0) {
1706
1750
  handlers.delete(channel);
1707
- sendUnsubscribe([channel]);
1751
+ if (!unqueueSubscribe(channel)) {
1752
+ sendUnsubscribe([channel]);
1753
+ }
1708
1754
  }
1709
1755
  }
1710
1756
  };
@@ -1,5 +1,5 @@
1
1
  /** Monaco's RFC 9421 Ed25519 profile; key registration remains wallet-authorized. */
2
- import { ed25519 } from "@noble/curves/ed25519";
2
+ import { ed25519 } from "@noble/curves/ed25519.js";
3
3
  import { sha256 } from "@noble/hashes/sha2.js";
4
4
  import { bytesToHex, utf8ToBytes } from "@noble/hashes/utils.js";
5
5
  function base64(bytes) {
@@ -7,7 +7,7 @@
7
7
  * private key. The server verifies the signature against the stored public
8
8
  * key — it never sees the private key, so it cannot mint requests as the user.
9
9
  */
10
- import { ed25519 } from "@noble/curves/ed25519";
10
+ import { ed25519 } from "@noble/curves/ed25519.js";
11
11
  import { sha256 } from "@noble/hashes/sha2.js";
12
12
  import { bytesToHex, hexToBytes, utf8ToBytes } from "@noble/hashes/utils.js";
13
13
  /**
@@ -21,7 +21,7 @@ export function generateSessionKeypair() {
21
21
  if (typeof globalThis.crypto?.getRandomValues !== "function") {
22
22
  throw new Error("Secure randomness (crypto.getRandomValues) is unavailable; cannot generate a session keypair.");
23
23
  }
24
- const privateKey = ed25519.utils.randomPrivateKey();
24
+ const privateKey = ed25519.utils.randomSecretKey();
25
25
  const publicKey = ed25519.getPublicKey(privateKey);
26
26
  return { publicKey, privateKey };
27
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xmonaco/core",
3
- "version": "1.0.94",
3
+ "version": "1.0.97",
4
4
  "type": "module",
5
5
  "homepage": "https://docs.0xmonaco.com/sdk/typescript",
6
6
  "main": "./dist/index.js",
@@ -19,15 +19,15 @@
19
19
  "viem": "^2.45.2"
20
20
  },
21
21
  "dependencies": {
22
- "@0xmonaco/contracts": "1.0.94",
23
- "@0xmonaco/types": "1.0.94",
24
- "@noble/curves": "^1.9.1",
22
+ "@0xmonaco/contracts": "1.0.97",
23
+ "@0xmonaco/types": "1.0.97",
24
+ "@noble/curves": "^2.4.0",
25
25
  "@noble/hashes": "^2.4.0",
26
26
  "http-status-codes": "^2.3.0"
27
27
  },
28
28
  "devDependencies": {
29
- "dotenv": "^17.1.0",
30
- "ws": "^8.18.3"
29
+ "dotenv": "^18.0.8",
30
+ "ws": "^8.22.0"
31
31
  },
32
32
  "exports": {
33
33
  ".": {