@orbinum/sdk 0.7.8 → 0.7.10

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.
package/dist/index.d.mts CHANGED
@@ -2073,6 +2073,13 @@ interface ClientProviderConfig {
2073
2073
  reconnectBaseMs?: number;
2074
2074
  /** Maximum reconnect delay cap in milliseconds. Default: `30_000`. */
2075
2075
  reconnectMaxMs?: number;
2076
+ /**
2077
+ * How long a connection must stay live before the reconnect backoff is reset
2078
+ * to base, in milliseconds. Prevents a flapping node (connect → drop →
2079
+ * connect) from resetting the backoff on every brief connect and hammering
2080
+ * the node every `reconnectBaseMs`. Default: `10_000`.
2081
+ */
2082
+ stableAfterMs?: number;
2076
2083
  }
2077
2084
  /**
2078
2085
  * Manages the lifecycle of an `OrbinumClient` with heartbeat monitoring,
@@ -2100,11 +2107,13 @@ declare class OrbinumClientProvider {
2100
2107
  private readonly heartbeatTimeoutMs;
2101
2108
  private readonly reconnectBaseMs;
2102
2109
  private readonly reconnectMaxMs;
2110
+ private readonly stableAfterMs;
2103
2111
  private _status;
2104
2112
  private _orbinumClient;
2105
2113
  private _connectingPromise;
2106
2114
  private _heartbeatTimer;
2107
2115
  private _reconnectTimer;
2116
+ private _stableTimer;
2108
2117
  private _reconnectAttempt;
2109
2118
  private _listeners;
2110
2119
  /** Creates a new provider with the given configuration. Does not connect automatically — call `connect()` to initiate. */
@@ -2145,9 +2154,20 @@ declare class OrbinumClientProvider {
2145
2154
  * Returns `true` if the node responds in time, `false` otherwise.
2146
2155
  */
2147
2156
  private probe;
2157
+ /**
2158
+ * After a successful connect, wait `stableAfterMs` before resetting the
2159
+ * backoff. If the connection survives that long it's considered stable and
2160
+ * the next drop starts from base delay again; if it drops sooner the backoff
2161
+ * keeps growing, so a flapping node backs off instead of hammering.
2162
+ */
2163
+ private startStableTimer;
2164
+ /** Clears the stability timer if active (on disconnect/teardown/reset). */
2165
+ private stopStableTimer;
2148
2166
  /**
2149
2167
  * Schedules the next connection attempt using exponential backoff
2150
- * (capped at `reconnectMaxMs`), then transitions to `'reconnecting'`.
2168
+ * (capped at `reconnectMaxMs`) with full jitter, then transitions to
2169
+ * `'reconnecting'`. Jitter (a random fraction of the delay) spreads out
2170
+ * reconnects so many clients don't retry in lockstep after a shared outage.
2151
2171
  */
2152
2172
  private scheduleReconnect;
2153
2173
  /** Clears any pending reconnect timer without triggering a new attempt. */
package/dist/index.d.ts CHANGED
@@ -2073,6 +2073,13 @@ interface ClientProviderConfig {
2073
2073
  reconnectBaseMs?: number;
2074
2074
  /** Maximum reconnect delay cap in milliseconds. Default: `30_000`. */
2075
2075
  reconnectMaxMs?: number;
2076
+ /**
2077
+ * How long a connection must stay live before the reconnect backoff is reset
2078
+ * to base, in milliseconds. Prevents a flapping node (connect → drop →
2079
+ * connect) from resetting the backoff on every brief connect and hammering
2080
+ * the node every `reconnectBaseMs`. Default: `10_000`.
2081
+ */
2082
+ stableAfterMs?: number;
2076
2083
  }
2077
2084
  /**
2078
2085
  * Manages the lifecycle of an `OrbinumClient` with heartbeat monitoring,
@@ -2100,11 +2107,13 @@ declare class OrbinumClientProvider {
2100
2107
  private readonly heartbeatTimeoutMs;
2101
2108
  private readonly reconnectBaseMs;
2102
2109
  private readonly reconnectMaxMs;
2110
+ private readonly stableAfterMs;
2103
2111
  private _status;
2104
2112
  private _orbinumClient;
2105
2113
  private _connectingPromise;
2106
2114
  private _heartbeatTimer;
2107
2115
  private _reconnectTimer;
2116
+ private _stableTimer;
2108
2117
  private _reconnectAttempt;
2109
2118
  private _listeners;
2110
2119
  /** Creates a new provider with the given configuration. Does not connect automatically — call `connect()` to initiate. */
@@ -2145,9 +2154,20 @@ declare class OrbinumClientProvider {
2145
2154
  * Returns `true` if the node responds in time, `false` otherwise.
2146
2155
  */
2147
2156
  private probe;
2157
+ /**
2158
+ * After a successful connect, wait `stableAfterMs` before resetting the
2159
+ * backoff. If the connection survives that long it's considered stable and
2160
+ * the next drop starts from base delay again; if it drops sooner the backoff
2161
+ * keeps growing, so a flapping node backs off instead of hammering.
2162
+ */
2163
+ private startStableTimer;
2164
+ /** Clears the stability timer if active (on disconnect/teardown/reset). */
2165
+ private stopStableTimer;
2148
2166
  /**
2149
2167
  * Schedules the next connection attempt using exponential backoff
2150
- * (capped at `reconnectMaxMs`), then transitions to `'reconnecting'`.
2168
+ * (capped at `reconnectMaxMs`) with full jitter, then transitions to
2169
+ * `'reconnecting'`. Jitter (a random fraction of the delay) spreads out
2170
+ * reconnects so many clients don't retry in lockstep after a shared outage.
2151
2171
  */
2152
2172
  private scheduleReconnect;
2153
2173
  /** Clears any pending reconnect timer without triggering a new attempt. */
package/dist/index.js CHANGED
@@ -1355,7 +1355,7 @@ var IndexerClient = class {
1355
1355
  async getAddressShieldedActivity(address, params) {
1356
1356
  const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1357
1357
  return this.get(
1358
- `/shielded/address/${encodeURIComponent(address.toLowerCase())}${qs}`
1358
+ `/shielded/address/${encodeURIComponent(address)}${qs}`
1359
1359
  );
1360
1360
  }
1361
1361
  // ─── Relayers ──────────────────────────────────────────────────────────────
@@ -3526,6 +3526,7 @@ var DEFAULT_HEARTBEAT_INTERVAL_MS = 5e3;
3526
3526
  var DEFAULT_HEARTBEAT_TIMEOUT_MS = 4e3;
3527
3527
  var DEFAULT_RECONNECT_BASE_MS = 3e3;
3528
3528
  var DEFAULT_RECONNECT_MAX_MS = 3e4;
3529
+ var DEFAULT_STABLE_AFTER_MS = 1e4;
3529
3530
  var OrbinumClientProvider = class {
3530
3531
  config;
3531
3532
  connectTimeoutMs;
@@ -3533,6 +3534,7 @@ var OrbinumClientProvider = class {
3533
3534
  heartbeatTimeoutMs;
3534
3535
  reconnectBaseMs;
3535
3536
  reconnectMaxMs;
3537
+ stableAfterMs;
3536
3538
  // ─── State ──────────────────────────────────────────────────────────────
3537
3539
  _status = "idle";
3538
3540
  _orbinumClient = null;
@@ -3540,6 +3542,7 @@ var OrbinumClientProvider = class {
3540
3542
  // ─── Timers ─────────────────────────────────────────────────────────────
3541
3543
  _heartbeatTimer = null;
3542
3544
  _reconnectTimer = null;
3545
+ _stableTimer = null;
3543
3546
  _reconnectAttempt = 0;
3544
3547
  // ─── Events ─────────────────────────────────────────────────────────────
3545
3548
  _listeners = /* @__PURE__ */ new Set();
@@ -3551,6 +3554,7 @@ var OrbinumClientProvider = class {
3551
3554
  this.heartbeatTimeoutMs = config.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS;
3552
3555
  this.reconnectBaseMs = config.reconnectBaseMs ?? DEFAULT_RECONNECT_BASE_MS;
3553
3556
  this.reconnectMaxMs = config.reconnectMaxMs ?? DEFAULT_RECONNECT_MAX_MS;
3557
+ this.stableAfterMs = config.stableAfterMs ?? DEFAULT_STABLE_AFTER_MS;
3554
3558
  }
3555
3559
  // ─── Status ─────────────────────────────────────────────────────────────
3556
3560
  /** Current connection status. Reflects the last state set by the provider internals. */
@@ -3637,9 +3641,9 @@ var OrbinumClientProvider = class {
3637
3641
  orphanClient = null;
3638
3642
  this._orbinumClient = client;
3639
3643
  this._connectingPromise = null;
3640
- this._reconnectAttempt = 0;
3641
3644
  this.setStatus("connected");
3642
3645
  this.startHeartbeat();
3646
+ this.startStableTimer();
3643
3647
  return client;
3644
3648
  } catch (err) {
3645
3649
  clearTimeout(timeoutId);
@@ -3696,17 +3700,41 @@ var OrbinumClientProvider = class {
3696
3700
  return false;
3697
3701
  }
3698
3702
  }
3703
+ // ─── Connection stability ───────────────────────────────────────────────
3704
+ /**
3705
+ * After a successful connect, wait `stableAfterMs` before resetting the
3706
+ * backoff. If the connection survives that long it's considered stable and
3707
+ * the next drop starts from base delay again; if it drops sooner the backoff
3708
+ * keeps growing, so a flapping node backs off instead of hammering.
3709
+ */
3710
+ startStableTimer() {
3711
+ this.stopStableTimer();
3712
+ this._stableTimer = setTimeout(() => {
3713
+ this._stableTimer = null;
3714
+ if (this._status === "connected") this._reconnectAttempt = 0;
3715
+ }, this.stableAfterMs);
3716
+ }
3717
+ /** Clears the stability timer if active (on disconnect/teardown/reset). */
3718
+ stopStableTimer() {
3719
+ if (this._stableTimer) {
3720
+ clearTimeout(this._stableTimer);
3721
+ this._stableTimer = null;
3722
+ }
3723
+ }
3699
3724
  // ─── Reconnection ───────────────────────────────────────────────────────
3700
3725
  /**
3701
3726
  * Schedules the next connection attempt using exponential backoff
3702
- * (capped at `reconnectMaxMs`), then transitions to `'reconnecting'`.
3727
+ * (capped at `reconnectMaxMs`) with full jitter, then transitions to
3728
+ * `'reconnecting'`. Jitter (a random fraction of the delay) spreads out
3729
+ * reconnects so many clients don't retry in lockstep after a shared outage.
3703
3730
  */
3704
3731
  scheduleReconnect() {
3705
3732
  if (this._reconnectTimer) clearTimeout(this._reconnectTimer);
3706
- const delay = Math.min(
3733
+ const capped = Math.min(
3707
3734
  this.reconnectBaseMs * 2 ** this._reconnectAttempt,
3708
3735
  this.reconnectMaxMs
3709
3736
  );
3737
+ const delay = capped / 2 + Math.random() * (capped / 2);
3710
3738
  this._reconnectAttempt++;
3711
3739
  this.setStatus("reconnecting");
3712
3740
  this._reconnectTimer = setTimeout(() => {
@@ -3725,6 +3753,7 @@ var OrbinumClientProvider = class {
3725
3753
  /** Stops the heartbeat, destroys the active client, and clears all in-progress promises. */
3726
3754
  teardownClient() {
3727
3755
  this.stopHeartbeat();
3756
+ this.stopStableTimer();
3728
3757
  try {
3729
3758
  this._orbinumClient?.destroy();
3730
3759
  } catch {
package/dist/index.mjs CHANGED
@@ -1228,7 +1228,7 @@ var IndexerClient = class {
1228
1228
  async getAddressShieldedActivity(address, params) {
1229
1229
  const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1230
1230
  return this.get(
1231
- `/shielded/address/${encodeURIComponent(address.toLowerCase())}${qs}`
1231
+ `/shielded/address/${encodeURIComponent(address)}${qs}`
1232
1232
  );
1233
1233
  }
1234
1234
  // ─── Relayers ──────────────────────────────────────────────────────────────
@@ -3399,6 +3399,7 @@ var DEFAULT_HEARTBEAT_INTERVAL_MS = 5e3;
3399
3399
  var DEFAULT_HEARTBEAT_TIMEOUT_MS = 4e3;
3400
3400
  var DEFAULT_RECONNECT_BASE_MS = 3e3;
3401
3401
  var DEFAULT_RECONNECT_MAX_MS = 3e4;
3402
+ var DEFAULT_STABLE_AFTER_MS = 1e4;
3402
3403
  var OrbinumClientProvider = class {
3403
3404
  config;
3404
3405
  connectTimeoutMs;
@@ -3406,6 +3407,7 @@ var OrbinumClientProvider = class {
3406
3407
  heartbeatTimeoutMs;
3407
3408
  reconnectBaseMs;
3408
3409
  reconnectMaxMs;
3410
+ stableAfterMs;
3409
3411
  // ─── State ──────────────────────────────────────────────────────────────
3410
3412
  _status = "idle";
3411
3413
  _orbinumClient = null;
@@ -3413,6 +3415,7 @@ var OrbinumClientProvider = class {
3413
3415
  // ─── Timers ─────────────────────────────────────────────────────────────
3414
3416
  _heartbeatTimer = null;
3415
3417
  _reconnectTimer = null;
3418
+ _stableTimer = null;
3416
3419
  _reconnectAttempt = 0;
3417
3420
  // ─── Events ─────────────────────────────────────────────────────────────
3418
3421
  _listeners = /* @__PURE__ */ new Set();
@@ -3424,6 +3427,7 @@ var OrbinumClientProvider = class {
3424
3427
  this.heartbeatTimeoutMs = config.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS;
3425
3428
  this.reconnectBaseMs = config.reconnectBaseMs ?? DEFAULT_RECONNECT_BASE_MS;
3426
3429
  this.reconnectMaxMs = config.reconnectMaxMs ?? DEFAULT_RECONNECT_MAX_MS;
3430
+ this.stableAfterMs = config.stableAfterMs ?? DEFAULT_STABLE_AFTER_MS;
3427
3431
  }
3428
3432
  // ─── Status ─────────────────────────────────────────────────────────────
3429
3433
  /** Current connection status. Reflects the last state set by the provider internals. */
@@ -3510,9 +3514,9 @@ var OrbinumClientProvider = class {
3510
3514
  orphanClient = null;
3511
3515
  this._orbinumClient = client;
3512
3516
  this._connectingPromise = null;
3513
- this._reconnectAttempt = 0;
3514
3517
  this.setStatus("connected");
3515
3518
  this.startHeartbeat();
3519
+ this.startStableTimer();
3516
3520
  return client;
3517
3521
  } catch (err) {
3518
3522
  clearTimeout(timeoutId);
@@ -3569,17 +3573,41 @@ var OrbinumClientProvider = class {
3569
3573
  return false;
3570
3574
  }
3571
3575
  }
3576
+ // ─── Connection stability ───────────────────────────────────────────────
3577
+ /**
3578
+ * After a successful connect, wait `stableAfterMs` before resetting the
3579
+ * backoff. If the connection survives that long it's considered stable and
3580
+ * the next drop starts from base delay again; if it drops sooner the backoff
3581
+ * keeps growing, so a flapping node backs off instead of hammering.
3582
+ */
3583
+ startStableTimer() {
3584
+ this.stopStableTimer();
3585
+ this._stableTimer = setTimeout(() => {
3586
+ this._stableTimer = null;
3587
+ if (this._status === "connected") this._reconnectAttempt = 0;
3588
+ }, this.stableAfterMs);
3589
+ }
3590
+ /** Clears the stability timer if active (on disconnect/teardown/reset). */
3591
+ stopStableTimer() {
3592
+ if (this._stableTimer) {
3593
+ clearTimeout(this._stableTimer);
3594
+ this._stableTimer = null;
3595
+ }
3596
+ }
3572
3597
  // ─── Reconnection ───────────────────────────────────────────────────────
3573
3598
  /**
3574
3599
  * Schedules the next connection attempt using exponential backoff
3575
- * (capped at `reconnectMaxMs`), then transitions to `'reconnecting'`.
3600
+ * (capped at `reconnectMaxMs`) with full jitter, then transitions to
3601
+ * `'reconnecting'`. Jitter (a random fraction of the delay) spreads out
3602
+ * reconnects so many clients don't retry in lockstep after a shared outage.
3576
3603
  */
3577
3604
  scheduleReconnect() {
3578
3605
  if (this._reconnectTimer) clearTimeout(this._reconnectTimer);
3579
- const delay = Math.min(
3606
+ const capped = Math.min(
3580
3607
  this.reconnectBaseMs * 2 ** this._reconnectAttempt,
3581
3608
  this.reconnectMaxMs
3582
3609
  );
3610
+ const delay = capped / 2 + Math.random() * (capped / 2);
3583
3611
  this._reconnectAttempt++;
3584
3612
  this.setStatus("reconnecting");
3585
3613
  this._reconnectTimer = setTimeout(() => {
@@ -3598,6 +3626,7 @@ var OrbinumClientProvider = class {
3598
3626
  /** Stops the heartbeat, destroys the active client, and clears all in-progress promises. */
3599
3627
  teardownClient() {
3600
3628
  this.stopHeartbeat();
3629
+ this.stopStableTimer();
3601
3630
  try {
3602
3631
  this._orbinumClient?.destroy();
3603
3632
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orbinum/sdk",
3
- "version": "0.7.8",
3
+ "version": "0.7.10",
4
4
  "description": "Official TypeScript SDK for Orbinum.",
5
5
  "author": "Orbinum",
6
6
  "license": "MIT",