@bounded-sh/core 0.0.102 → 0.0.104

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.
Files changed (33) hide show
  1. package/dist/client/realtime-store.d.ts +2 -0
  2. package/dist/client/reconnect-backoff.d.ts +16 -0
  3. package/dist/client/socket-heartbeat.d.ts +47 -0
  4. package/dist/client/solana-operations.d.ts +15 -0
  5. package/dist/client/subscription-v2.d.ts +6 -0
  6. package/dist/{index-BEGeDFQI.js → index-62gjQH30.js} +220 -26
  7. package/dist/index-62gjQH30.js.map +1 -0
  8. package/dist/{index-CMT0saxy.mjs → index-CLst0IiM.mjs} +220 -26
  9. package/dist/index-CLst0IiM.mjs.map +1 -0
  10. package/dist/index.js +1 -1
  11. package/dist/index.mjs +1 -1
  12. package/dist/{realtime-store-DrtEj-bE.js → realtime-store-9SCt1RPf.js} +2 -2
  13. package/dist/realtime-store-9SCt1RPf.js.map +1 -0
  14. package/dist/{realtime-store-DqAAqfo9.mjs → realtime-store-C9AgPg7U.mjs} +2 -2
  15. package/dist/realtime-store-C9AgPg7U.mjs.map +1 -0
  16. package/dist/{solana-message-CJTnYiJu.js → solana-message-Bf2q_JO1.js} +2 -2
  17. package/dist/{solana-message-CJTnYiJu.js.map → solana-message-Bf2q_JO1.js.map} +1 -1
  18. package/dist/{solana-message-C_717vAx.mjs → solana-message-Deru1tF1.mjs} +2 -2
  19. package/dist/{solana-message-C_717vAx.mjs.map → solana-message-Deru1tF1.mjs.map} +1 -1
  20. package/dist/{solana-operations-DGNA2nGZ.mjs → solana-operations-Cm19J14R.mjs} +34 -5
  21. package/dist/{solana-operations-DGNA2nGZ.mjs.map → solana-operations-Cm19J14R.mjs.map} +1 -1
  22. package/dist/{solana-operations-CU0YbiMu.js → solana-operations-eTiLgak2.js} +34 -3
  23. package/dist/{solana-operations-CU0YbiMu.js.map → solana-operations-eTiLgak2.js.map} +1 -1
  24. package/dist/{solana-v1-operations-yQII8r1s.js → solana-v1-operations-CnmiKiyj.js} +3 -3
  25. package/dist/{solana-v1-operations-yQII8r1s.js.map → solana-v1-operations-CnmiKiyj.js.map} +1 -1
  26. package/dist/{solana-v1-operations-Bpd4TASG.mjs → solana-v1-operations-Dxs4XM_F.mjs} +3 -3
  27. package/dist/{solana-v1-operations-Bpd4TASG.mjs.map → solana-v1-operations-Dxs4XM_F.mjs.map} +1 -1
  28. package/dist/types.d.ts +16 -1
  29. package/package.json +2 -2
  30. package/dist/index-BEGeDFQI.js.map +0 -1
  31. package/dist/index-CMT0saxy.mjs.map +0 -1
  32. package/dist/realtime-store-DqAAqfo9.mjs.map +0 -1
  33. package/dist/realtime-store-DrtEj-bE.js.map +0 -1
@@ -33,6 +33,8 @@ export declare class RealtimeStore {
33
33
  private reconnectTimer;
34
34
  private reconnectDelay;
35
35
  private maxReconnectDelay;
36
+ /** When the current socket finished connecting; decides whether a close resets the backoff. */
37
+ private connectedAtMs;
36
38
  private idbFlushTimer;
37
39
  private idbDirtyKeys;
38
40
  private closed;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Reconnect backoff for RealtimeStore's WebSocket.
3
+ *
4
+ * A server that sheds load closes many sockets at once (1013). Without jitter
5
+ * every client comes back at the same instant; without growth on quick closes a
6
+ * socket that is accepted and then immediately dropped retries at the floor
7
+ * forever. So: a connection that stayed up for STABLE_CONNECTION_MS resets the
8
+ * delay, a shorter one doubles it, and every scheduled wait is jittered.
9
+ */
10
+ export declare const RECONNECT_BASE_DELAY_MS = 1000;
11
+ export declare const RECONNECT_MAX_DELAY_MS = 30000;
12
+ export declare const STABLE_CONNECTION_MS = 10000;
13
+ /** Delay to use after a close, given how long the closed connection had been up (null: never connected). */
14
+ export declare function reconnectDelayAfterClose(currentDelayMs: number, connectedForMs: number | null, maxDelayMs?: number): number;
15
+ /** The wait actually scheduled: the delay scaled by a random factor in [0.5, 1.5). */
16
+ export declare function jitteredReconnectDelayMs(delayMs: number, random?: () => number): number;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Idle heartbeat for the realtime WebSocket connection (subscription-v2.ts).
3
+ *
4
+ * A socket whose server has stopped delivering frames looks exactly like a
5
+ * quiet one: the browser reports it open and nothing arrives. The client only
6
+ * learns the difference by asking. Once nothing has been received for
7
+ * HEARTBEAT_IDLE_MS the heartbeat asks the connection to send a ping; if
8
+ * nothing at all arrives within HEARTBEAT_TIMEOUT_MS after that, the socket is
9
+ * declared dead and the connection is reconnected. Any inbound frame counts as
10
+ * proof of life, so a busy socket is never pinged and a pong is just another
11
+ * frame. The connection may decline to ping (it already has a request in
12
+ * flight with its own timeout); the idle wait then simply starts over.
13
+ *
14
+ * The timeout sits above both budgets a pong can wait behind: the connection's
15
+ * own 30 s request budget (the server handles one frame per socket at a time)
16
+ * and the object's 30 s CPU slice, which another socket's handler can hold
17
+ * while every pong waits. A healthy socket must never be declared dead
18
+ * within either.
19
+ *
20
+ * Pure: timers come from the clock passed in, so tests can drive it.
21
+ */
22
+ export declare const HEARTBEAT_IDLE_MS = 25000;
23
+ export declare const HEARTBEAT_TIMEOUT_MS = 45000;
24
+ export interface HeartbeatClock {
25
+ setTimeout(callback: () => void, ms: number): unknown;
26
+ clearTimeout(handle: unknown): void;
27
+ }
28
+ export declare class SocketHeartbeat {
29
+ /** Send a ping now; return false to skip this round (the idle wait restarts). */
30
+ private readonly sendPing;
31
+ private readonly onDead;
32
+ private readonly clock;
33
+ private readonly idleMs;
34
+ private readonly timeoutMs;
35
+ private idleTimer;
36
+ private timeoutTimer;
37
+ private stopped;
38
+ constructor(
39
+ /** Send a ping now; return false to skip this round (the idle wait restarts). */
40
+ sendPing: () => boolean, onDead: () => void, clock?: HeartbeatClock, idleMs?: number, timeoutMs?: number);
41
+ start(): void;
42
+ /** An inbound frame arrived: the socket is alive, so the idle wait starts over. */
43
+ noteActivity(): void;
44
+ stop(): void;
45
+ private armIdle;
46
+ private clearTimers;
47
+ }
@@ -121,6 +121,21 @@ export declare function validateServerTransactionSemantics(input: {
121
121
  instructions: ServerTransactionInstructionView[];
122
122
  PublicKeyCtor: PublicKeyClass;
123
123
  }): void;
124
+ /**
125
+ * Poofnet lane of the onchain 202. Poofnet has no chain, so there is nothing to
126
+ * submit and no blockhash to refresh: the worker issued an unsendable message
127
+ * (off-curve fee payer) that only proves this wallet approved this write. It is
128
+ * validated exactly like a mainnet transaction before the wallet sees it, signed
129
+ * by the same provider method, and returned for the worker to verify and commit.
130
+ */
131
+ /**
132
+ * The fee payer of every poofnet approval message (realtime's
133
+ * POOFNET_VOID_FEE_PAYER): an off-curve address with no private key, so a message
134
+ * it pays for can never land on any cluster. Pinned here so a 202 from anything
135
+ * else can never get a live, broadcastable transaction signed.
136
+ */
137
+ export declare const POOFNET_VOID_FEE_PAYER = "CAXES7Tt3KGsSw4A5knQXKKUJZWsrguu6PC7SDBL4oq2";
138
+ export declare function signPoofnetTransaction(serializedTransaction: string, authProvider: AuthProvider, options: SetOptions | undefined, expectedIntent: ExpectedWriteIntent): Promise<string>;
124
139
  export declare function handlePreBuiltTransaction(tx: {
125
140
  serializedTransaction: string;
126
141
  blockhash: string;
@@ -28,6 +28,12 @@ export declare const SHARD_CAP = 45;
28
28
  * target, far beyond any legitimate UI.
29
29
  */
30
30
  export declare const MAX_SHARDS_PER_KEY = 8;
31
+ /**
32
+ * Every idle client on a stalled object hits its dead timer at about the same
33
+ * moment, so the replacement waits out the wrapper's own first-attempt delay
34
+ * with the same jitter, instead of every client reopening in one instant.
35
+ */
36
+ export declare const HEARTBEAT_RECONNECT_DELAY_MAX_MS: number;
31
37
  /**
32
38
  * Subscribe to data at a path using WebSocket v2.
33
39
  * Returns an unsubscribe function.
@@ -4190,7 +4190,7 @@ class ServerSessionManager {
4190
4190
  const sessionConfig = (_a = this.sessionConfig) !== null && _a !== void 0 ? _a : undefined;
4191
4191
  /* fetch nonce from auth API (bound to the snapshotted app+issuer) */
4192
4192
  const nonce = await genAuthNonce(sessionConfig);
4193
- const { genSolanaMessage } = await Promise.resolve().then(function () { return require('./solana-message-CJTnYiJu.js'); });
4193
+ const { genSolanaMessage } = await Promise.resolve().then(function () { return require('./solana-message-Bf2q_JO1.js'); });
4194
4194
  const message = await genSolanaMessage(address, nonce, sessionConfig === null || sessionConfig === void 0 ? void 0 : sessionConfig.appId);
4195
4195
  /* sign the message */
4196
4196
  const sigBytes = nacl.sign.detached(new TextEncoder().encode(message), kp.secretKey);
@@ -5231,6 +5231,83 @@ async function resolveClientTransactionVersions(authProvider) {
5231
5231
  return typeof authProvider.signTransactionV1 === 'function' ? ['legacy', 0, 1] : ['legacy', 0];
5232
5232
  }
5233
5233
 
5234
+ /**
5235
+ * Idle heartbeat for the realtime WebSocket connection (subscription-v2.ts).
5236
+ *
5237
+ * A socket whose server has stopped delivering frames looks exactly like a
5238
+ * quiet one: the browser reports it open and nothing arrives. The client only
5239
+ * learns the difference by asking. Once nothing has been received for
5240
+ * HEARTBEAT_IDLE_MS the heartbeat asks the connection to send a ping; if
5241
+ * nothing at all arrives within HEARTBEAT_TIMEOUT_MS after that, the socket is
5242
+ * declared dead and the connection is reconnected. Any inbound frame counts as
5243
+ * proof of life, so a busy socket is never pinged and a pong is just another
5244
+ * frame. The connection may decline to ping (it already has a request in
5245
+ * flight with its own timeout); the idle wait then simply starts over.
5246
+ *
5247
+ * The timeout sits above both budgets a pong can wait behind: the connection's
5248
+ * own 30 s request budget (the server handles one frame per socket at a time)
5249
+ * and the object's 30 s CPU slice, which another socket's handler can hold
5250
+ * while every pong waits. A healthy socket must never be declared dead
5251
+ * within either.
5252
+ *
5253
+ * Pure: timers come from the clock passed in, so tests can drive it.
5254
+ */
5255
+ const HEARTBEAT_IDLE_MS = 25000;
5256
+ const HEARTBEAT_TIMEOUT_MS = 45000;
5257
+ class SocketHeartbeat {
5258
+ constructor(
5259
+ /** Send a ping now; return false to skip this round (the idle wait restarts). */
5260
+ sendPing, onDead, clock = globalThis, idleMs = HEARTBEAT_IDLE_MS, timeoutMs = HEARTBEAT_TIMEOUT_MS) {
5261
+ this.sendPing = sendPing;
5262
+ this.onDead = onDead;
5263
+ this.clock = clock;
5264
+ this.idleMs = idleMs;
5265
+ this.timeoutMs = timeoutMs;
5266
+ this.idleTimer = null;
5267
+ this.timeoutTimer = null;
5268
+ this.stopped = false;
5269
+ }
5270
+ start() {
5271
+ if (this.stopped)
5272
+ return;
5273
+ this.armIdle();
5274
+ }
5275
+ /** An inbound frame arrived: the socket is alive, so the idle wait starts over. */
5276
+ noteActivity() {
5277
+ if (this.stopped)
5278
+ return;
5279
+ this.clearTimers();
5280
+ this.armIdle();
5281
+ }
5282
+ stop() {
5283
+ this.stopped = true;
5284
+ this.clearTimers();
5285
+ }
5286
+ armIdle() {
5287
+ this.idleTimer = this.clock.setTimeout(() => {
5288
+ this.idleTimer = null;
5289
+ if (!this.sendPing()) {
5290
+ this.armIdle();
5291
+ return;
5292
+ }
5293
+ this.timeoutTimer = this.clock.setTimeout(() => {
5294
+ this.timeoutTimer = null;
5295
+ this.onDead();
5296
+ }, this.timeoutMs);
5297
+ }, this.idleMs);
5298
+ }
5299
+ clearTimers() {
5300
+ if (this.idleTimer !== null) {
5301
+ this.clock.clearTimeout(this.idleTimer);
5302
+ this.idleTimer = null;
5303
+ }
5304
+ if (this.timeoutTimer !== null) {
5305
+ this.clock.clearTimeout(this.timeoutTimer);
5306
+ this.timeoutTimer = null;
5307
+ }
5308
+ }
5309
+ }
5310
+
5234
5311
  /**
5235
5312
  * WebSocket v2 Subscription Manager
5236
5313
  *
@@ -5325,6 +5402,81 @@ const WS_CONFIG = {
5325
5402
  // Give handshakes more time before considering the attempt failed.
5326
5403
  connectionTimeout: 10000,
5327
5404
  };
5405
+ /** Client-chosen close code for a socket the heartbeat declared dead (4000-4999 are application codes). */
5406
+ const HEARTBEAT_CLOSE_CODE = 4000;
5407
+ function heartbeatReconnectDelayMs() {
5408
+ return BASE_MIN_RECONNECT_DELAY_MS + Math.floor(Math.random() * MIN_RECONNECT_DELAY_JITTER_MS);
5409
+ }
5410
+ /**
5411
+ * Start the idle heartbeat for the native socket that just opened on `ws`.
5412
+ * A ping goes out after HEARTBEAT_IDLE_MS of silence, and a socket that
5413
+ * answers nothing for HEARTBEAT_TIMEOUT_MS more is reconnected through the
5414
+ * wrapper after a jittered delay, the same path an auth change takes. A
5415
+ * server that has stopped dispatching frames leaves the socket open and
5416
+ * silent, so nothing else on the client would ever notice.
5417
+ */
5418
+ function startHeartbeat(connection, ws) {
5419
+ stopHeartbeat(connection);
5420
+ const heartbeat = new SocketHeartbeat(() => {
5421
+ // An outbound wait already has its own timeout, and the server
5422
+ // answers one frame per socket at a time, so a ping behind it would
5423
+ // only measure that wait. Let the idle wait start over instead.
5424
+ if (hasOutboundWait(connection))
5425
+ return false;
5426
+ // The wrapper drops a send on a socket that is not open, and a send
5427
+ // that throws is a socket that cannot carry a ping either way; the
5428
+ // dead timer then reports it.
5429
+ try {
5430
+ ws.send(JSON.stringify({ type: 'ping' }));
5431
+ }
5432
+ catch (error) {
5433
+ console.warn('[WS v2] Heartbeat ping could not be sent:', error);
5434
+ }
5435
+ return true;
5436
+ }, () => {
5437
+ // Only the socket this heartbeat was started for. A replaced or
5438
+ // torn-down connection must never be resurrected by a late timer.
5439
+ if (connection.heartbeat !== heartbeat || connection.ws !== ws)
5440
+ return;
5441
+ console.warn('[WS v2] No frames within the heartbeat window; reconnecting');
5442
+ // The heartbeat stays installed through the delay: a frame that
5443
+ // arrives meanwhile cancels the replacement (see the message
5444
+ // listener) and starts a fresh idle window on the same socket.
5445
+ connection.heartbeatReconnectTimer = setTimeout(() => {
5446
+ connection.heartbeatReconnectTimer = null;
5447
+ if (connection.heartbeat !== heartbeat || connection.ws !== ws)
5448
+ return;
5449
+ connection.heartbeat = null;
5450
+ try {
5451
+ ws.reconnect(HEARTBEAT_CLOSE_CODE, 'Heartbeat timeout');
5452
+ }
5453
+ catch (error) {
5454
+ console.error('[WS v2] Error reconnecting after heartbeat timeout:', error);
5455
+ }
5456
+ }, heartbeatReconnectDelayMs());
5457
+ });
5458
+ connection.heartbeat = heartbeat;
5459
+ heartbeat.start();
5460
+ }
5461
+ function stopHeartbeat(connection) {
5462
+ var _a;
5463
+ (_a = connection.heartbeat) === null || _a === void 0 ? void 0 : _a.stop();
5464
+ connection.heartbeat = null;
5465
+ if (connection.heartbeatReconnectTimer) {
5466
+ clearTimeout(connection.heartbeatReconnectTimer);
5467
+ connection.heartbeatReconnectTimer = null;
5468
+ }
5469
+ }
5470
+ /** A frame of ours the server has not answered yet: a request, a subscription confirmation, or a snapshot refresh. */
5471
+ function hasOutboundWait(connection) {
5472
+ if (connection.pendingRequests.size > 0 || connection.pendingSubscriptions.size > 0)
5473
+ return true;
5474
+ for (const subscription of connection.subscriptions.values()) {
5475
+ if (subscription.refresh)
5476
+ return true;
5477
+ }
5478
+ return false;
5479
+ }
5328
5480
  const WS_V2_PATH = '/ws/v2';
5329
5481
  let browserReconnectHooksAttached = false;
5330
5482
  let lastBrowserTriggeredReconnectAt = 0;
@@ -5793,6 +5945,7 @@ function closeConnectionNow(connection) {
5793
5945
  clearInterval(connection.tokenRefreshTimer);
5794
5946
  connection.tokenRefreshTimer = null;
5795
5947
  }
5948
+ stopHeartbeat(connection);
5796
5949
  const ws = connection.ws;
5797
5950
  connection.ws = null;
5798
5951
  connection.isConnecting = false;
@@ -6077,6 +6230,8 @@ async function getOrCreateConnectionOnce(appId, isServer, routePath, authTokenPr
6077
6230
  authTokenValue: null,
6078
6231
  authPrincipal: null,
6079
6232
  socketGeneration: 0,
6233
+ heartbeat: null,
6234
+ heartbeatReconnectTimer: null,
6080
6235
  tokenRefreshTimer: null,
6081
6236
  idleCloseTimer: null,
6082
6237
  consecutiveAuthFailures: 0,
@@ -6151,6 +6306,7 @@ async function getOrCreateConnectionOnce(appId, isServer, routePath, authTokenPr
6151
6306
  connection.socketGeneration += 1;
6152
6307
  connection.isConnecting = false;
6153
6308
  connection.isConnected = true;
6309
+ startHeartbeat(connection, ws);
6154
6310
  // NOTE: Do NOT reset consecutiveAuthFailures here. It is reset when a
6155
6311
  // fresh auth token is actually obtained or on an explicit auth change.
6156
6312
  // Schedule periodic token freshness checks. An anonymous (read-only
@@ -6185,6 +6341,13 @@ async function getOrCreateConnectionOnce(appId, isServer, routePath, authTokenPr
6185
6341
  });
6186
6342
  // Handle incoming messages
6187
6343
  ws.addEventListener('message', (event) => {
6344
+ var _a;
6345
+ if (connection.heartbeatReconnectTimer) {
6346
+ // A frame inside the replacement delay: the socket is alive after all.
6347
+ clearTimeout(connection.heartbeatReconnectTimer);
6348
+ connection.heartbeatReconnectTimer = null;
6349
+ }
6350
+ (_a = connection.heartbeat) === null || _a === void 0 ? void 0 : _a.noteActivity();
6188
6351
  try {
6189
6352
  const message = JSON.parse(event.data);
6190
6353
  handleServerMessage(connection, message);
@@ -6206,6 +6369,7 @@ async function getOrCreateConnectionOnce(appId, isServer, routePath, authTokenPr
6206
6369
  });
6207
6370
  // Handle close
6208
6371
  ws.addEventListener('close', () => {
6372
+ stopHeartbeat(connection);
6209
6373
  connection.isConnected = false;
6210
6374
  connection.isAuthenticating = false;
6211
6375
  const disconnectError = new Error('WebSocket disconnected');
@@ -7185,6 +7349,7 @@ async function closeAllSubscriptionsV2() {
7185
7349
  connection.tokenRefreshTimer = null;
7186
7350
  }
7187
7351
  if (connection.ws) {
7352
+ stopHeartbeat(connection);
7188
7353
  const ws = connection.ws;
7189
7354
  connection.ws = null;
7190
7355
  connection.isConnected = false;
@@ -7304,7 +7469,7 @@ async function doReconnectWithNewAuth() {
7304
7469
  console.warn('[WS v2] Failed to clear HTTP read cache on auth change:', error);
7305
7470
  }
7306
7471
  try {
7307
- const { reconnectRealtimeStoreWithNewAuth } = await Promise.resolve().then(function () { return require('./realtime-store-DrtEj-bE.js'); });
7472
+ const { reconnectRealtimeStoreWithNewAuth } = await Promise.resolve().then(function () { return require('./realtime-store-9SCt1RPf.js'); });
7308
7473
  await reconnectRealtimeStoreWithNewAuth();
7309
7474
  }
7310
7475
  catch (error) {
@@ -8647,7 +8812,7 @@ async function set(path, document, options) {
8647
8812
  * state appears only under `observation`/`mirrorSync` once actually observed.
8648
8813
  */
8649
8814
  async function setMany(many, options) {
8650
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
8815
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
8651
8816
  // Returns the data that was set, or undefined if the document was already set.
8652
8817
  try {
8653
8818
  // A server WalletClient threads its immutable config snapshot; the default
@@ -8752,13 +8917,35 @@ async function setMany(many, options) {
8752
8917
  throw new Error('The write response carried no execution-chain tag, so this receipt could not state where the write ran. ' +
8753
8918
  'Nothing was signed or submitted.');
8754
8919
  }
8920
+ if (workerChain === 'realtime_offchain') {
8921
+ // Poofnet: the wallet signs the worker's unsendable approval message and
8922
+ // the worker verifies and commits it. Nothing is submitted to any chain.
8923
+ if (typeof curTx.serializedTransaction !== 'string' || typeof curTx.poofnetIntentId !== 'string') {
8924
+ throw new Error('Unsupported 202 transaction shape: a poofnet write needs serializedTransaction and poofnetIntentId');
8925
+ }
8926
+ const { signPoofnetTransaction, buildExpectedWriteIntent } = await Promise.resolve().then(function () { return require('./solana-operations-eTiLgak2.js'); });
8927
+ const signedTransaction = await signPoofnetTransaction(curTx.serializedTransaction, authProvider, options, buildExpectedWriteIntent(documents));
8928
+ // Signing-only, exactly as on a real chain: signed and NOT committed.
8929
+ if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false) {
8930
+ return {
8931
+ status: 'signed', appId, requestedDocuments: buildRequestedDocuments(documents),
8932
+ chain: 'realtime_offchain', transactionId: null, signedTransaction,
8933
+ poofnetIntentId: curTx.poofnetIntentId,
8934
+ };
8935
+ }
8936
+ const commitResponse = await makeApiRequest('PUT', 'items/signed', { intentId: curTx.poofnetIntentId, signedTransaction }, options === null || options === void 0 ? void 0 : options._overrides);
8937
+ if (commitResponse.status !== 200) {
8938
+ throw new Error(`Poofnet signed write was not committed (status ${commitResponse.status})`);
8939
+ }
8940
+ return directCommitResult(commitResponse, documents);
8941
+ }
8755
8942
  if (curTx.serializedTransaction) {
8756
8943
  if (!SOLANA_CHAIN_TAGS.has(workerChain)) {
8757
8944
  throw new Error(`The write response reported execution chain "${workerChain}" for a Solana transaction. ` +
8758
8945
  'Nothing was signed or submitted.');
8759
8946
  }
8760
8947
  const solanaChain = workerChain;
8761
- const { handlePreBuiltTransaction, buildExpectedWriteIntent } = await Promise.resolve().then(function () { return require('./solana-operations-CU0YbiMu.js'); });
8948
+ const { handlePreBuiltTransaction, buildExpectedWriteIntent } = await Promise.resolve().then(function () { return require('./solana-operations-eTiLgak2.js'); });
8762
8949
  // OA-0001: derive the expected intent from OUR OWN request (the one
8763
8950
  // ground truth a tampered builder response cannot change) so the
8764
8951
  // validator can reject any transaction whose operation semantics
@@ -8801,26 +8988,7 @@ async function setMany(many, options) {
8801
8988
  }
8802
8989
  }
8803
8990
  else if (setResponse.status === 200) {
8804
- // Direct commit: the worker applied the batch itself. The receipt is
8805
- // batch-level — `transactionId` comes from the worker's own receipt and is
8806
- // NEVER lifted out of a result document (a delete returns the PREVIOUS
8807
- // document, so its stale `_transaction_hash` would misreport the delete).
8808
- const body = (setResponse.data && typeof setResponse.data === 'object' && !Array.isArray(setResponse.data))
8809
- ? setResponse.data
8810
- : null;
8811
- const receipt = ((body === null || body === void 0 ? void 0 : body.receipt) && typeof body.receipt === 'object' && !Array.isArray(body.receipt))
8812
- ? body.receipt
8813
- : null;
8814
- const rawTransactionId = receipt === null || receipt === void 0 ? void 0 : receipt.transactionId;
8815
- return {
8816
- status: 'committed',
8817
- requestedDocuments: buildRequestedDocuments(documents),
8818
- observation: observationFromDirectCommit(documents.map(d => d.destinationPath), receipt === null || receipt === void 0 ? void 0 : receipt.observation),
8819
- // A worker predating the batch receipt reports no lane. Say so rather
8820
- // than inventing one — and never discard a committed write's receipt.
8821
- chain: ((_l = readWorkerChainTag(receipt)) !== null && _l !== void 0 ? _l : 'unknown'),
8822
- transactionId: typeof rawTransactionId === 'string' && rawTransactionId.length > 0 ? rawTransactionId : null,
8823
- };
8991
+ return directCommitResult(setResponse, documents);
8824
8992
  }
8825
8993
  else {
8826
8994
  throw new Error(`Failed to set document: ${setResponse}`);
@@ -8830,6 +8998,32 @@ async function setMany(many, options) {
8830
8998
  throw error;
8831
8999
  }
8832
9000
  }
9001
+ /**
9002
+ * Direct commit: the worker applied the batch itself (an offchain write, or a
9003
+ * poofnet onchain write after its signature verified). The receipt is batch-level
9004
+ * - `transactionId` comes from the worker's own receipt and is NEVER lifted out
9005
+ * of a result document (a delete returns the PREVIOUS document, so its stale
9006
+ * `_transaction_hash` would misreport the delete).
9007
+ */
9008
+ function directCommitResult(response, documents) {
9009
+ var _a;
9010
+ const body = (response.data && typeof response.data === 'object' && !Array.isArray(response.data))
9011
+ ? response.data
9012
+ : null;
9013
+ const receipt = ((body === null || body === void 0 ? void 0 : body.receipt) && typeof body.receipt === 'object' && !Array.isArray(body.receipt))
9014
+ ? body.receipt
9015
+ : null;
9016
+ const rawTransactionId = receipt === null || receipt === void 0 ? void 0 : receipt.transactionId;
9017
+ return {
9018
+ status: 'committed',
9019
+ requestedDocuments: buildRequestedDocuments(documents),
9020
+ observation: observationFromDirectCommit(documents.map(d => d.destinationPath), receipt === null || receipt === void 0 ? void 0 : receipt.observation),
9021
+ // A worker predating the batch receipt reports no lane. Say so rather
9022
+ // than inventing one - and never discard a committed write's receipt.
9023
+ chain: ((_a = readWorkerChainTag(receipt)) !== null && _a !== void 0 ? _a : 'unknown'),
9024
+ transactionId: typeof rawTransactionId === 'string' && rawTransactionId.length > 0 ? rawTransactionId : null,
9025
+ };
9026
+ }
8833
9027
  /**
8834
9028
  * Extract the document/collection path from a cache key. Keys are
8835
9029
  * `<appId:principal>|<path>:<...>` (H1 principal-scoped) — strip the principal
@@ -10533,7 +10727,7 @@ function toMillis(seconds) {
10533
10727
 
10534
10728
  /** SIWS message creation is async already, so its onchain module can be lazy. */
10535
10729
  async function genSolanaMessage(address, nonce) {
10536
- const implementation = await Promise.resolve().then(function () { return require('./solana-message-CJTnYiJu.js'); });
10730
+ const implementation = await Promise.resolve().then(function () { return require('./solana-message-Bf2q_JO1.js'); });
10537
10731
  return implementation.genSolanaMessage(address, nonce);
10538
10732
  }
10539
10733
 
@@ -11180,4 +11374,4 @@ exports.toMillis = toMillis;
11180
11374
  exports.toSeconds = toSeconds;
11181
11375
  exports.waitForSetResult = waitForSetResult;
11182
11376
  exports.withEffects = withEffects;
11183
- //# sourceMappingURL=index-BEGeDFQI.js.map
11377
+ //# sourceMappingURL=index-62gjQH30.js.map