@bounded-sh/core 0.0.47 → 0.0.49

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 (23) hide show
  1. package/dist/client/config.d.ts +10 -5
  2. package/dist/client/token-subscription.d.ts +22 -0
  3. package/dist/{index-Bq2Zug5X.mjs → index-CXyMnWgK.mjs} +138 -52
  4. package/dist/index-CXyMnWgK.mjs.map +1 -0
  5. package/dist/{index-Kn7IIh5d.js → index-D6xrWKP7.js} +138 -52
  6. package/dist/index-D6xrWKP7.js.map +1 -0
  7. package/dist/index.js +1 -1
  8. package/dist/index.mjs +1 -1
  9. package/dist/{realtime-store-XKFKDJRA.mjs → realtime-store-Djb_Dm-M.mjs} +2 -2
  10. package/dist/{realtime-store-XKFKDJRA.mjs.map → realtime-store-Djb_Dm-M.mjs.map} +1 -1
  11. package/dist/{realtime-store-DssTn6Nr.js → realtime-store-HkfnxBu3.js} +2 -2
  12. package/dist/{realtime-store-DssTn6Nr.js.map → realtime-store-HkfnxBu3.js.map} +1 -1
  13. package/dist/{solana-message-DSkrhvy8.js → solana-message-CTUg0Tqd.js} +2 -2
  14. package/dist/{solana-message-DSkrhvy8.js.map → solana-message-CTUg0Tqd.js.map} +1 -1
  15. package/dist/{solana-message-Svo0_paO.mjs → solana-message-l5OZo1j2.mjs} +2 -2
  16. package/dist/{solana-message-Svo0_paO.mjs.map → solana-message-l5OZo1j2.mjs.map} +1 -1
  17. package/dist/{solana-operations-C_aie1aF.js → solana-operations-CSh2uF_0.js} +2 -2
  18. package/dist/{solana-operations-C_aie1aF.js.map → solana-operations-CSh2uF_0.js.map} +1 -1
  19. package/dist/{solana-operations-4MGSdS1U.mjs → solana-operations-TSE5Tbgo.mjs} +2 -2
  20. package/dist/{solana-operations-4MGSdS1U.mjs.map → solana-operations-TSE5Tbgo.mjs.map} +1 -1
  21. package/package.json +1 -1
  22. package/dist/index-Bq2Zug5X.mjs.map +0 -1
  23. package/dist/index-Kn7IIh5d.js.map +0 -1
@@ -17,6 +17,7 @@ let clientConfig = {
17
17
  authApiUrl: 'https://wallet-auth.bounded.sh',
18
18
  humanAuthApiUrl: 'https://auth.bounded.sh',
19
19
  functionsUrl: 'https://functions.bounded.sh',
20
+ devApiUrl: 'https://dev-api.bounded.sh',
20
21
  appId: '',
21
22
  // No hidden modal fallback: browser clients start hosted Bounded Auth with
22
23
  // loginWithRedirect/loginWithPopup. For crypto/onchain wallet login use
@@ -41,6 +42,7 @@ const BOUNDED_NETWORKS = {
41
42
  authApiUrl: 'https://wallet-auth-staging.bounded.sh',
42
43
  humanAuthApiUrl: 'https://auth-staging.bounded.sh',
43
44
  functionsUrl: 'https://functions-staging.bounded.sh',
45
+ devApiUrl: 'https://dev-api-staging.bounded.sh',
44
46
  },
45
47
  'bounded-production': {
46
48
  // All on bounded.sh custom domains. authApiUrl = WALLET/SIWS issuer
@@ -51,6 +53,7 @@ const BOUNDED_NETWORKS = {
51
53
  authApiUrl: 'https://wallet-auth.bounded.sh',
52
54
  humanAuthApiUrl: 'https://auth.bounded.sh',
53
55
  functionsUrl: 'https://functions.bounded.sh',
56
+ devApiUrl: 'https://dev-api.bounded.sh',
54
57
  },
55
58
  };
56
59
  // `network: 'bounded'` is an alias for the current GA target.
@@ -3407,7 +3410,7 @@ class ServerSessionManager {
3407
3410
  const address = kp.publicKey.toBase58();
3408
3411
  /* fetch nonce from auth API */
3409
3412
  const nonce = await genAuthNonce();
3410
- const { genSolanaMessage } = await Promise.resolve().then(function () { return require('./solana-message-DSkrhvy8.js'); });
3413
+ const { genSolanaMessage } = await Promise.resolve().then(function () { return require('./solana-message-CTUg0Tqd.js'); });
3411
3414
  const message = await genSolanaMessage(address, nonce);
3412
3415
  /* sign the message */
3413
3416
  const sigBytes = nacl.sign.detached(new TextEncoder().encode(message), kp.secretKey);
@@ -5444,11 +5447,11 @@ async function setMany(many, options) {
5444
5447
  transactionResult = await handleEvmTransaction(curTx.evmTransaction, authProvider, options);
5445
5448
  }
5446
5449
  else if (curTx.serializedTransaction) {
5447
- const { handlePreBuiltTransaction } = await Promise.resolve().then(function () { return require('./solana-operations-C_aie1aF.js'); });
5450
+ const { handlePreBuiltTransaction } = await Promise.resolve().then(function () { return require('./solana-operations-CSh2uF_0.js'); });
5448
5451
  transactionResult = await handlePreBuiltTransaction(curTx, authProvider, options, expectedWritePaths);
5449
5452
  }
5450
5453
  else {
5451
- const { handleSolanaTransaction } = await Promise.resolve().then(function () { return require('./solana-operations-C_aie1aF.js'); });
5454
+ const { handleSolanaTransaction } = await Promise.resolve().then(function () { return require('./solana-operations-CSh2uF_0.js'); });
5452
5455
  transactionResult = await handleSolanaTransaction(curTx, authProvider, options, expectedWritePaths);
5453
5456
  }
5454
5457
  // Sync items after all transactions are confirmed
@@ -6106,7 +6109,10 @@ function roomKeyFromRoutePath(routePath) {
6106
6109
  function replaySubscriptions(connection) {
6107
6110
  for (const sub of connection.subscriptions.values()) {
6108
6111
  sub.lastData = undefined;
6109
- sendSubscribe(connection, sub);
6112
+ if (!connection.pendingSubscriptions.has(sub.subscriptionId)) {
6113
+ registerDetachedReplayConfirmation(connection, sub);
6114
+ }
6115
+ sendSubscribeWithConfirmation(connection, sub);
6110
6116
  }
6111
6117
  }
6112
6118
  /**
@@ -6146,6 +6152,9 @@ function closeConnectionNow(connection) {
6146
6152
  connection.isConnected = false;
6147
6153
  connection.isAuthenticating = false;
6148
6154
  const closeError = new Error('WebSocket connection closed');
6155
+ for (const subscriptionId of Array.from(connection.pendingSubscriptions.keys())) {
6156
+ rejectPendingSubscriptionConfirmation(connection, subscriptionId, closeError);
6157
+ }
6149
6158
  for (const subscription of connection.subscriptions.values()) {
6150
6159
  rejectSubscriptionRefresh(subscription, closeError);
6151
6160
  }
@@ -6791,6 +6800,75 @@ function armSubscriptionConfirmationTimeout(connection, subscription, pending) {
6791
6800
  rejectPendingSubscriptionConfirmation(connection, subscription.subscriptionId, new Error('Subscription timeout'));
6792
6801
  }, SUBSCRIPTION_CONFIRM_TIMEOUT_MS);
6793
6802
  }
6803
+ /**
6804
+ * Bind an existing confirmation promise to the exact socket session that is
6805
+ * about to carry its subscribe frame. Cold-start registrations create the
6806
+ * promise before the socket opens; replay uses this helper to move the timeout
6807
+ * from the connection wait onto the authenticated socket without allocating a
6808
+ * second promise or leaving the original timer behind.
6809
+ */
6810
+ function sendSubscribeWithConfirmation(connection, subscription) {
6811
+ const pending = connection.pendingSubscriptions.get(subscription.subscriptionId);
6812
+ const socket = connection.ws;
6813
+ if (pending && socket && socket.readyState === WS_READY_STATE_OPEN) {
6814
+ if (pending.timer) {
6815
+ clearTimeout(pending.timer);
6816
+ pending.timer = null;
6817
+ }
6818
+ pending.socket = socket;
6819
+ pending.socketGeneration = connection.socketGeneration;
6820
+ pending.authTokenValue = connection.authTokenValue;
6821
+ pending.authPrincipal = connection.authPrincipal;
6822
+ // Arm before send: browser/test transports may synchronously dispatch
6823
+ // the subscribed/data/error response from send().
6824
+ armSubscriptionConfirmationTimeout(connection, subscription, pending);
6825
+ }
6826
+ sendSubscribe(connection, subscription);
6827
+ }
6828
+ /**
6829
+ * A reconnect replay has no caller awaiting subscribeV2 anymore, but it still
6830
+ * needs the same bounded confirmation/retry guarantee. Attach the rejection
6831
+ * handler immediately so this recovery record can never become an unhandled
6832
+ * promise. Structured server errors are delivered by handleServerMessage;
6833
+ * terminal local timeouts are surfaced here exactly once to active callbacks.
6834
+ */
6835
+ function registerDetachedReplayConfirmation(connection, subscription) {
6836
+ const socket = connection.ws;
6837
+ if (!socket || connection.pendingSubscriptions.has(subscription.subscriptionId))
6838
+ return;
6839
+ let resolve;
6840
+ let reject;
6841
+ const promise = new Promise((resolvePromise, rejectPromise) => {
6842
+ resolve = resolvePromise;
6843
+ reject = rejectPromise;
6844
+ });
6845
+ const pending = {
6846
+ resolve,
6847
+ reject,
6848
+ timer: null,
6849
+ retrySent: false,
6850
+ socket,
6851
+ socketGeneration: connection.socketGeneration,
6852
+ authTokenValue: connection.authTokenValue,
6853
+ authPrincipal: connection.authPrincipal,
6854
+ };
6855
+ connection.pendingSubscriptions.set(subscription.subscriptionId, pending);
6856
+ void promise.catch((error) => {
6857
+ if (error.__boundedDeliveredToOnError)
6858
+ return;
6859
+ if (connection.subscriptions.get(subscription.subscriptionId) !== subscription)
6860
+ return;
6861
+ // Ordinary socket/auth-change close paths will replay again and did not
6862
+ // historically poison every established callback. Only a healthy socket
6863
+ // exhausting its bounded confirmation retry is a new terminal condition.
6864
+ if (error.message === 'Subscription timeout') {
6865
+ const delivered = notifyErrorCallbacks(subscription, error);
6866
+ if (!delivered) {
6867
+ console.warn('[WS v2] Replayed subscription confirmation timed out:', subscription.path);
6868
+ }
6869
+ }
6870
+ });
6871
+ }
6794
6872
  function resolveSubscriptionRefresh(subscription) {
6795
6873
  const refresh = subscription.refresh;
6796
6874
  if (!refresh)
@@ -7063,53 +7141,57 @@ async function subscribeV2(path, subscriptionOptions, roomRoutePath) {
7063
7141
  throw error;
7064
7142
  }
7065
7143
  releaseConnection();
7066
- // Send subscribe message if connected
7144
+ // Register the confirmation before any possible synchronous send/ACK. This
7145
+ // includes the first subscription on a cold socket: replaySubscriptions()
7146
+ // will bind this same pending record to the authenticated socket and send it.
7147
+ const subscriptionPromise = new Promise((resolve, reject) => {
7148
+ const socket = connection.ws;
7149
+ if (!socket) {
7150
+ reject(new Error('WebSocket disconnected'));
7151
+ return;
7152
+ }
7153
+ const pending = {
7154
+ resolve,
7155
+ reject,
7156
+ timer: null,
7157
+ retrySent: false,
7158
+ socket,
7159
+ socketGeneration: connection.socketGeneration,
7160
+ authTokenValue: connection.authTokenValue,
7161
+ authPrincipal: connection.authPrincipal,
7162
+ };
7163
+ connection.pendingSubscriptions.set(subscriptionId, pending);
7164
+ // Bound a cold connection/auth wait as well. Once the socket becomes
7165
+ // ready, sendSubscribeWithConfirmation() replaces this timer with a
7166
+ // fresh per-socket confirmation window.
7167
+ armSubscriptionConfirmationTimeout(connection, subscription, pending);
7168
+ });
7067
7169
  if (connection.isConnected && !connection.isAuthenticating) {
7068
- // Create a promise to wait for subscription confirmation
7069
- const subscriptionPromise = new Promise((resolve, reject) => {
7070
- const socket = connection.ws;
7071
- if (!socket) {
7072
- reject(new Error('WebSocket disconnected'));
7073
- return;
7074
- }
7075
- const pending = {
7076
- resolve,
7077
- reject,
7078
- timer: null,
7079
- retrySent: false,
7080
- socket,
7081
- socketGeneration: connection.socketGeneration,
7082
- authTokenValue: connection.authTokenValue,
7083
- authPrincipal: connection.authPrincipal,
7084
- };
7085
- connection.pendingSubscriptions.set(subscriptionId, pending);
7086
- armSubscriptionConfirmationTimeout(connection, subscription, pending);
7087
- });
7088
- sendSubscribe(connection, subscription);
7089
- try {
7090
- await subscriptionPromise;
7170
+ sendSubscribeWithConfirmation(connection, subscription);
7171
+ }
7172
+ try {
7173
+ await subscriptionPromise;
7174
+ }
7175
+ catch (error) {
7176
+ const err = error instanceof Error ? error : new Error(String(error));
7177
+ let deliveredLocally = false;
7178
+ if (!err.__boundedDeliveredToOnError) {
7179
+ // A local confirmation timeout belongs to the caller that
7180
+ // originated it. Joined callbacks may already have a viable
7181
+ // same-id refresh and must not be poisoned by that old attempt.
7182
+ deliveredLocally = notifyErrorCallback(subscriptionOptions, err);
7183
+ }
7184
+ if (!subscriptionOptions.onError) {
7185
+ rejectPendingSubscriptionConfirmation(connection, subscriptionId, err);
7186
+ // This registration may have acquired joined callbacks while
7187
+ // its confirmation was pending. Remove only the originating
7188
+ // callback; deleting the whole logical subscription would
7189
+ // orphan those remounted consumers and their refresh flight.
7190
+ await removeCallbackFromSubscription(connection, subscriptionId, subscriptionOptions);
7191
+ throw err;
7091
7192
  }
7092
- catch (error) {
7093
- const err = error instanceof Error ? error : new Error(String(error));
7094
- let deliveredLocally = false;
7095
- if (!err.__boundedDeliveredToOnError) {
7096
- // A local confirmation timeout belongs to the caller that
7097
- // originated it. Joined callbacks may already have a viable
7098
- // same-id refresh and must not be poisoned by that old attempt.
7099
- deliveredLocally = notifyErrorCallback(subscriptionOptions, err);
7100
- }
7101
- if (!subscriptionOptions.onError) {
7102
- connection.pendingSubscriptions.delete(subscriptionId);
7103
- // This registration may have acquired joined callbacks while
7104
- // its confirmation was pending. Remove only the originating
7105
- // callback; deleting the whole logical subscription would
7106
- // orphan those remounted consumers and their refresh flight.
7107
- await removeCallbackFromSubscription(connection, subscriptionId, subscriptionOptions);
7108
- throw err;
7109
- }
7110
- if (!err.__boundedDeliveredToOnError && !deliveredLocally) {
7111
- console.warn('[WS v2] Subscription confirmation failed, keeping for reconnect recovery:', error);
7112
- }
7193
+ if (!err.__boundedDeliveredToOnError && !deliveredLocally) {
7194
+ console.warn('[WS v2] Subscription confirmation failed, keeping for reconnect recovery:', error);
7113
7195
  }
7114
7196
  }
7115
7197
  // Return unsubscribe function
@@ -7132,6 +7214,7 @@ async function removeCallbackFromSubscription(connection, subscriptionId, callba
7132
7214
  }
7133
7215
  // No more callbacks, unsubscribe from server
7134
7216
  connection.subscriptions.delete(subscriptionId);
7217
+ rejectPendingSubscriptionConfirmation(connection, subscriptionId, new Error('Subscription unsubscribed'));
7135
7218
  if (connection.isConnected && !connection.isAuthenticating) {
7136
7219
  // Create a promise to wait for unsubscription confirmation
7137
7220
  const unsubscribePromise = new Promise((resolve, reject) => {
@@ -7159,6 +7242,9 @@ async function closeAllSubscriptionsV2() {
7159
7242
  for (const [appId, connection] of connections) {
7160
7243
  cancelIdleConnectionClose(connection);
7161
7244
  const closeError = new Error('Subscriptions closed');
7245
+ for (const subscriptionId of Array.from(connection.pendingSubscriptions.keys())) {
7246
+ rejectPendingSubscriptionConfirmation(connection, subscriptionId, closeError);
7247
+ }
7162
7248
  for (const subscription of connection.subscriptions.values()) {
7163
7249
  rejectSubscriptionRefresh(subscription, closeError);
7164
7250
  }
@@ -7280,7 +7366,7 @@ async function doReconnectWithNewAuth() {
7280
7366
  console.warn('[WS v2] Failed to clear HTTP read cache on auth change:', error);
7281
7367
  }
7282
7368
  try {
7283
- const { reconnectRealtimeStoreWithNewAuth } = await Promise.resolve().then(function () { return require('./realtime-store-DssTn6Nr.js'); });
7369
+ const { reconnectRealtimeStoreWithNewAuth } = await Promise.resolve().then(function () { return require('./realtime-store-HkfnxBu3.js'); });
7284
7370
  await reconnectRealtimeStoreWithNewAuth();
7285
7371
  }
7286
7372
  catch (error) {
@@ -7625,7 +7711,7 @@ async function buildSetDocumentsTransaction(connection, idl, programProvider, pa
7625
7711
  }
7626
7712
  /** SIWS message creation is async already, so its onchain module can be lazy. */
7627
7713
  async function genSolanaMessage(address, nonce) {
7628
- const implementation = await Promise.resolve().then(function () { return require('./solana-message-DSkrhvy8.js'); });
7714
+ const implementation = await Promise.resolve().then(function () { return require('./solana-message-CTUg0Tqd.js'); });
7629
7715
  return implementation.genSolanaMessage(address, nonce);
7630
7716
  }
7631
7717
  const BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
@@ -8228,4 +8314,4 @@ exports.toLowerEvmAddress = toLowerEvmAddress;
8228
8314
  exports.toMillis = toMillis;
8229
8315
  exports.toSeconds = toSeconds;
8230
8316
  exports.withEffects = withEffects;
8231
- //# sourceMappingURL=index-Kn7IIh5d.js.map
8317
+ //# sourceMappingURL=index-D6xrWKP7.js.map