@gvnrdao/dh-sdk 0.0.303 → 0.0.305

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.mjs CHANGED
@@ -444,9 +444,13 @@ var init_deployment_addresses = __esm({
444
444
  reason: "Validator gas fix (#420): BitcoinAddressValidator packed-table lookups; VERSION 1.0.0 -> 1.0.1"
445
445
  },
446
446
  UCDController: {
447
+ previousImplementation: "0x16f94AcC78cE87bEeBCfF90552091B3EfC071E48",
447
448
  newImplementation: "0x28B8cAB89D89B3F83581FD2290de2Ce84535bd0A",
448
- upgradedBy: "Reconciled from chain \u2014 Upgraded event log unavailable; provenance omitted (never fabricated)",
449
- reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)"
449
+ upgradedAt: "2026-07-06T10:41:59.000Z",
450
+ upgradedBy: "AdminModule/Safe audit-batch upgradeToAndCall; executed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f in tx 0xf6609d3fa43b460d953c85d8d7265b59bf177723042db79a6a700571bad777b7 (block 25472962)",
451
+ reason: "Reconciled from chain \u2014 mainnet audit rollout batch (cross-ref onchain-auth/.safe-batches/mainnet-audit-execute.json)",
452
+ executeTx: "0xf6609d3fa43b460d953c85d8d7265b59bf177723042db79a6a700571bad777b7",
453
+ block: 25472962
450
454
  },
451
455
  PositionManagerCoreModule: {
452
456
  previousImplementation: "0x6C8b0FB93F8d0239254aefaC24d4264cA2F8AAeB",
@@ -1293,7 +1297,7 @@ var require_pkg_src = __commonJS({
1293
1297
  description: "Production Pkp Validator",
1294
1298
  version: "1.0.0",
1295
1299
  deployed: true,
1296
- deployedAt: 1783106284785,
1300
+ deployedAt: 1784569687492,
1297
1301
  size: 4140,
1298
1302
  hash: "4c0d65bf1f33cdac22a78fd8c4764319cc3fe00650e0fe7fa8a6090d9a318a7b",
1299
1303
  validatorWalletAddress: "0x82db9f515957aa380b596c6ea2bd30cef181f236",
@@ -1370,17 +1374,17 @@ var require_pkg_src = __commonJS({
1370
1374
  }
1371
1375
  },
1372
1376
  btcWithdrawal: {
1373
- cid: "QmYG1o9qMBZsEMDE9DNsJMzQmvxfj6jTu9V37WwuJZAtC2",
1377
+ cid: "QmexvpfHPacjsVcqNHHLyJhSnnAPLgbWmWd9N3NDLDvYds",
1374
1378
  authorizedCidHex: cidToHex(
1375
- "QmYG1o9qMBZsEMDE9DNsJMzQmvxfj6jTu9V37WwuJZAtC2"
1379
+ "QmexvpfHPacjsVcqNHHLyJhSnnAPLgbWmWd9N3NDLDvYds"
1376
1380
  ),
1377
1381
  name: "Btc Withdrawal",
1378
1382
  description: "Production Btc Withdrawal",
1379
- version: "1.2.1",
1383
+ version: "1.2.3",
1380
1384
  deployed: true,
1381
- deployedAt: 1784316549409,
1382
- size: 90692,
1383
- hash: "ca7276763142fe1fc812b70f6319973000faf338a91c531f898f8f6406035c64",
1385
+ deployedAt: 1784585746901,
1386
+ size: 92027,
1387
+ hash: "7b4f4eab1f0c08b8b5b1c9cdb1064dd403ec13f57765919f62dec67fb8ba3c69",
1384
1388
  validatorWalletAddress: "0x82DB9F515957aA380B596C6eA2Bd30CEF181f236",
1385
1389
  pkp: {
1386
1390
  publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
@@ -3752,12 +3756,23 @@ ${auth.clientId}`;
3752
3756
  if (!data.vout || !Array.isArray(data.vout)) {
3753
3757
  return null;
3754
3758
  }
3755
- return data.vout.map((output, index) => ({
3756
- index,
3757
- scriptpubkey: output.scriptpubkey,
3758
- scriptpubkey_address: output.scriptpubkey_address,
3759
- value: output.value ?? 0
3760
- }));
3759
+ return data.vout.map((output, index) => {
3760
+ if (output.value === void 0) {
3761
+ throw new Error(
3762
+ `getTransactionOutputs(${txid}): output ${index} is missing its value \u2014 malformed provider response, refusing to return outputs that cannot be value-verified`
3763
+ );
3764
+ }
3765
+ assertSaneSatoshis(
3766
+ output.value,
3767
+ `getTransactionOutputs(${txid}) output ${index}`
3768
+ );
3769
+ return {
3770
+ index,
3771
+ scriptpubkey: output.scriptpubkey,
3772
+ scriptpubkey_address: output.scriptpubkey_address,
3773
+ value: output.value
3774
+ };
3775
+ });
3761
3776
  } catch (error) {
3762
3777
  clearTimeout(timeoutId);
3763
3778
  if (isAbortError(error)) {
@@ -6526,6 +6541,14 @@ var ServerSession = class {
6526
6541
  fetchImpl;
6527
6542
  cached = null;
6528
6543
  inFlight = null;
6544
+ /**
6545
+ * Bumped by `clearPersisted()` (logout / disconnect). An in-flight
6546
+ * `getOrRefresh()` captures this at start and refuses to write its freshly
6547
+ * minted token back to `this.cached`/the store if the value changed
6548
+ * meanwhile — so a refresh racing a sign-out can't silently "un-clear" the
6549
+ * credential it was told to drop.
6550
+ */
6551
+ generation = 0;
6529
6552
  /**
6530
6553
  * Store key for the current signer, memoized on first use so the sync
6531
6554
  * `clear()` can drop the persisted token without an async address lookup.
@@ -6541,8 +6564,22 @@ var ServerSession = class {
6541
6564
  this.now = opts.now ?? (() => Math.floor(Date.now() / 1e3));
6542
6565
  this.fetchImpl = opts.fetchImpl ?? ((...a) => fetch(...a));
6543
6566
  }
6544
- /** Returns a JWT good for at least `REFRESH_LEEWAY_SECONDS` more seconds. */
6545
- async getValidToken() {
6567
+ /**
6568
+ * Returns a JWT good for at least `REFRESH_LEEWAY_SECONDS` more seconds.
6569
+ * Pass `{ silent: true }` to forbid a fresh wallet signature: it resolves ONLY
6570
+ * from a live cached token or the persisted re-mint envelope, never prompting
6571
+ * and never joining a prompt-capable in-flight refresh (used by `logout()`,
6572
+ * which must never pop the wallet during sign-out). Rejects when only a fresh
6573
+ * signature could produce a token.
6574
+ */
6575
+ async getValidToken(opts) {
6576
+ if (opts?.silent) {
6577
+ const session2 = await this.tryResolveSilently(this.generation);
6578
+ if (!session2) {
6579
+ throw new Error("ServerSession: no existing session to refresh");
6580
+ }
6581
+ return session2.token;
6582
+ }
6546
6583
  const session = await this.getOrRefresh();
6547
6584
  return session.token;
6548
6585
  }
@@ -6575,20 +6612,24 @@ var ServerSession = class {
6575
6612
  * from storage).
6576
6613
  */
6577
6614
  async clearPersisted() {
6615
+ this.generation += 1;
6578
6616
  this.cached = null;
6579
6617
  this.inFlight = null;
6580
6618
  if (!this.store)
6581
6619
  return;
6582
- if (this.lastStoreKey) {
6583
- this.store.clear(this.lastStoreKey);
6584
- return;
6585
- }
6586
6620
  try {
6587
- const address = (await this.signer.getAddress()).toLowerCase();
6588
- this.store.clear(
6589
- sessionStoreKey(address, this.chainId, this.serviceEndpoint)
6590
- );
6621
+ if (this.lastStoreKey) {
6622
+ this.store.clear(this.lastStoreKey);
6623
+ } else {
6624
+ const address = (await this.signer.getAddress()).toLowerCase();
6625
+ this.store.clear(
6626
+ sessionStoreKey(address, this.chainId, this.serviceEndpoint)
6627
+ );
6628
+ }
6591
6629
  } catch {
6630
+ } finally {
6631
+ this.generation += 1;
6632
+ this.cached = null;
6592
6633
  }
6593
6634
  }
6594
6635
  /**
@@ -6598,7 +6639,8 @@ var ServerSession = class {
6598
6639
  * of server response so the client stops presenting the token.
6599
6640
  */
6600
6641
  async logout() {
6601
- const token = this.cached?.token ?? await this.getValidToken().catch(() => null);
6642
+ const cached = this.cached;
6643
+ const token = cached && cached.expiresAt > this.now() ? cached.token : await this.getValidToken({ silent: true }).catch(() => null);
6602
6644
  await this.clearPersisted();
6603
6645
  if (!token)
6604
6646
  return;
@@ -6613,6 +6655,50 @@ var ServerSession = class {
6613
6655
  );
6614
6656
  }
6615
6657
  }
6658
+ /**
6659
+ * Resolve a session WITHOUT ever prompting for a wallet signature: a live
6660
+ * cached token, else the persisted JWT (adopted if still fresh, otherwise
6661
+ * silently re-minted from the envelope). Returns `null` only when a fresh
6662
+ * wallet signature would be required (dead/absent envelope). Never touches
6663
+ * `this.inFlight`, so a silent caller (logout) can resolve independently
6664
+ * instead of being dragged into a prompt-capable refresh already in flight.
6665
+ *
6666
+ * `gen` is the caller's clear-generation snapshot: writes to `this.cached`
6667
+ * and the store are skipped if a `clearPersisted()` landed meanwhile.
6668
+ */
6669
+ async tryResolveSilently(gen) {
6670
+ const nowSec = this.now();
6671
+ if (this.cached && this.cached.expiresAt - REFRESH_LEEWAY_SECONDS > nowSec) {
6672
+ return this.cached;
6673
+ }
6674
+ const persisted = await this.loadPersisted();
6675
+ if (!persisted)
6676
+ return null;
6677
+ if (persisted.token && typeof persisted.tokenExpiresAt === "number" && persisted.tokenExpiresAt - REFRESH_LEEWAY_SECONDS > this.now()) {
6678
+ const adopted = {
6679
+ token: persisted.token,
6680
+ expiresAt: persisted.tokenExpiresAt
6681
+ };
6682
+ if (gen === this.generation)
6683
+ this.cached = adopted;
6684
+ return adopted;
6685
+ }
6686
+ try {
6687
+ const session = await this.login(persisted.payload);
6688
+ if (gen === this.generation) {
6689
+ this.persist(persisted.payload, session);
6690
+ this.cached = session;
6691
+ }
6692
+ return session;
6693
+ } catch (error) {
6694
+ if (!isLoginRejection(error))
6695
+ throw error;
6696
+ if (gen === this.generation && this.store && this.lastStoreKey) {
6697
+ this.store.clear(this.lastStoreKey);
6698
+ }
6699
+ return null;
6700
+ }
6701
+ }
6616
6702
  async getOrRefresh() {
6617
6703
  const nowSec = this.now();
6618
6704
  if (this.cached && this.cached.expiresAt - REFRESH_LEEWAY_SECONDS > nowSec) {
@@ -6620,30 +6706,13 @@ var ServerSession = class {
6620
6706
  }
6621
6707
  if (this.inFlight)
6622
6708
  return this.inFlight;
6709
+ const gen = this.generation;
6710
+ const notCleared = () => gen === this.generation;
6623
6711
  this.inFlight = (async () => {
6624
6712
  try {
6625
- const persisted = await this.loadPersisted();
6626
- if (persisted) {
6627
- if (persisted.token && typeof persisted.tokenExpiresAt === "number" && persisted.tokenExpiresAt - REFRESH_LEEWAY_SECONDS > this.now()) {
6628
- this.cached = {
6629
- token: persisted.token,
6630
- expiresAt: persisted.tokenExpiresAt
6631
- };
6632
- return this.cached;
6633
- }
6634
- try {
6635
- const session2 = await this.login(persisted.payload);
6636
- this.persist(persisted.payload, session2);
6637
- this.cached = session2;
6638
- return session2;
6639
- } catch (error) {
6640
- if (!isLoginRejection(error))
6641
- throw error;
6642
- if (this.store && this.lastStoreKey) {
6643
- this.store.clear(this.lastStoreKey);
6644
- }
6645
- }
6646
- }
6713
+ const existing = await this.tryResolveSilently(gen);
6714
+ if (existing)
6715
+ return existing;
6647
6716
  this.onSignaturePrompt?.();
6648
6717
  const payload = await buildSignedLoginPayload(
6649
6718
  this.signer,
@@ -6651,11 +6720,14 @@ var ServerSession = class {
6651
6720
  this.serviceEndpoint
6652
6721
  );
6653
6722
  const session = await this.login(payload);
6654
- this.persist(payload, session);
6655
- this.cached = session;
6723
+ if (notCleared()) {
6724
+ this.persist(payload, session);
6725
+ this.cached = session;
6726
+ }
6656
6727
  return session;
6657
6728
  } finally {
6658
- this.inFlight = null;
6729
+ if (notCleared())
6730
+ this.inFlight = null;
6659
6731
  }
6660
6732
  })();
6661
6733
  return this.inFlight;
@@ -16032,13 +16104,25 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
16032
16104
  return this.serverSession.getAuthHeader();
16033
16105
  }
16034
16106
  /**
16035
- * Remove the persisted lit-ops-server session (the 24h re-mint envelope and
16036
- * its JWT) for the current auth signer. Call on wallet disconnect or
16037
- * explicit sign-out so the credential does not outlive the wallet
16038
- * connection. No-op in standalone mode.
16107
+ * Sign out of the lit-ops-server session for the current auth signer. Call on
16108
+ * wallet disconnect or explicit sign-out so the credential does not outlive
16109
+ * the wallet connection. No-op in standalone mode.
16110
+ *
16111
+ * Attempts a server-side revocation first (`ServerSession.logout()` — which
16112
+ * tombstones the envelope's 24h re-mint window and invalidates the JWT), then
16113
+ * always removes the local credential. If the revocation call fails (offline,
16114
+ * server down, wallet already disconnected) we still clear locally so the
16115
+ * session cannot silently re-mint after sign-out; `logout()` is best-effort
16116
+ * and never prompts the wallet.
16039
16117
  */
16040
16118
  async clearServerSession() {
16041
- await this.serverSession?.clearPersisted();
16119
+ if (!this.serverSession)
16120
+ return;
16121
+ try {
16122
+ await this.serverSession.logout();
16123
+ } catch {
16124
+ await this.serverSession.clearPersisted();
16125
+ }
16042
16126
  }
16043
16127
  /**
16044
16128
  * Audit H-9: invalidate the LoanQuery cache so subsequent reads return
@@ -20613,7 +20697,9 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
20613
20697
  gasUsed: receipt.gasUsed?.toString() || "unknown",
20614
20698
  utxoTxid: validationResponse.utxoTxid,
20615
20699
  utxoVout: validationResponse.utxoVout,
20616
- utxoSatoshis: validationResponse.utxoSatoshis
20700
+ utxoSatoshis: validationResponse.utxoSatoshis,
20701
+ // Phase B: full consensus-validated spend set (absent on older actions).
20702
+ confirmedUtxos: validationResponse.confirmedUtxos
20617
20703
  };
20618
20704
  } catch (error) {
20619
20705
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -20643,6 +20729,42 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
20643
20729
  };
20644
20730
  }
20645
20731
  }
20732
+ /**
20733
+ * TEMPORARY (multi-UTXO withdrawal fix, Phase A): fetch the vault's confirmed
20734
+ * UTXO set from lit-ops-server (`GET /api/lit/vault-utxos`) so the caller can
20735
+ * assemble and sign the FULL input set for a multi-UTXO consolidation
20736
+ * withdrawal. Phase 1 only returns ONE representative UTXO, so a vault whose
20737
+ * balance is spread across several UTXOs otherwise fails the Phase-2 signer
20738
+ * with "Insufficient UTXO value ... across 1 input(s)".
20739
+ *
20740
+ * Returns `[]` on any failure (non-service mode, network error, bad shape) so
20741
+ * callers transparently fall back to the single authorized UTXO. Superseded
20742
+ * by the btc-withdrawal Lit Action returning its own confirmedUTXOs (Phase B).
20743
+ */
20744
+ async fetchConfirmedVaultUtxos(positionId) {
20745
+ if (this.config.mode !== "service" || !this.config.serviceEndpoint)
20746
+ return [];
20747
+ try {
20748
+ const pid = positionId.startsWith("0x") ? positionId : `0x${positionId}`;
20749
+ const resp = await fetch(
20750
+ `${this.config.serviceEndpoint}/api/lit/vault-utxos?positionId=${encodeURIComponent(pid)}`,
20751
+ { method: "GET", headers: { ...await this.getAuthHeader() } }
20752
+ );
20753
+ if (!resp.ok)
20754
+ return [];
20755
+ const json = await resp.json();
20756
+ if (!json.success || !Array.isArray(json.data?.utxos))
20757
+ return [];
20758
+ return json.data.utxos.map((u) => ({
20759
+ txid: String(u.txid),
20760
+ vout: Number(u.vout),
20761
+ value: Number(u.value),
20762
+ confirmations: Number(u.confirmations ?? 0)
20763
+ }));
20764
+ } catch {
20765
+ return [];
20766
+ }
20767
+ }
20646
20768
  /**
20647
20769
  * Execute Bitcoin withdrawal (Phase 2)
20648
20770
  *
@@ -21259,13 +21381,49 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
21259
21381
  if (this.config.debug) {
21260
21382
  log.info("\u{1F50D} Found vault UTXO for execution", { utxoIdentifier });
21261
21383
  }
21384
+ let executionUtxos;
21385
+ const gatheredUtxos = authResult.confirmedUtxos && authResult.confirmedUtxos.length > 0 ? authResult.confirmedUtxos.map((u) => ({
21386
+ txid: u.txid,
21387
+ vout: Number(u.vout),
21388
+ value: Number(u.value),
21389
+ confirmations: 0
21390
+ })) : await this.fetchConfirmedVaultUtxos(positionId);
21391
+ if (gatheredUtxos.length > 0) {
21392
+ const normTxid = (t) => String(t).toLowerCase().replace(/^0x/, "");
21393
+ const byOutpoint = /* @__PURE__ */ new Map();
21394
+ for (const u of gatheredUtxos) {
21395
+ const txid = normTxid(u.txid);
21396
+ byOutpoint.set(`${txid}:${u.vout}`, {
21397
+ txid,
21398
+ vout: Number(u.vout),
21399
+ value: Number(u.value)
21400
+ });
21401
+ }
21402
+ const repKey = `${normTxid(authResult.utxoTxid)}:${authResult.utxoVout}`;
21403
+ if (!byOutpoint.has(repKey)) {
21404
+ byOutpoint.set(repKey, {
21405
+ txid: normTxid(authResult.utxoTxid),
21406
+ vout: Number(authResult.utxoVout),
21407
+ value: Number(authResult.utxoSatoshis)
21408
+ });
21409
+ }
21410
+ if (byOutpoint.size > 1) {
21411
+ executionUtxos = Array.from(byOutpoint.values());
21412
+ if (this.config.debug) {
21413
+ log.info("\u{1F9E9} Multi-UTXO withdrawal: signing full input set", {
21414
+ inputs: executionUtxos.length
21415
+ });
21416
+ }
21417
+ }
21418
+ }
21262
21419
  const executionResult = await this.executeBTCWithdrawal({
21263
21420
  positionId,
21264
21421
  utxoIdentifier,
21265
21422
  utxoSatoshis: Number(authResult.utxoSatoshis),
21266
21423
  networkFee,
21267
21424
  destination: withdrawalAddress,
21268
- targetAmount: withdrawalAmount
21425
+ targetAmount: withdrawalAmount,
21426
+ ...executionUtxos ? { utxos: executionUtxos } : {}
21269
21427
  });
21270
21428
  if (this.config.debug) {
21271
21429
  log.info("\u2705 Phase 2 complete: Bitcoin transaction executed", {
@@ -233,6 +233,16 @@ export interface BTCWithdrawalResult {
233
233
  utxoVout?: number;
234
234
  /** Full satoshi value of the authorized UTXO; needed by Phase 2 broadcast. */
235
235
  utxoSatoshis?: string;
236
+ /**
237
+ * Phase B: the FULL consensus-validated confirmed UTXO set the Lit Action
238
+ * spends, so a multi-UTXO consolidation withdrawal can sign the whole set
239
+ * without the temporary /vault-utxos endpoint. Absent on older Lit Actions.
240
+ */
241
+ confirmedUtxos?: Array<{
242
+ txid: string;
243
+ vout: number;
244
+ value: string;
245
+ }>;
236
246
  error?: string;
237
247
  }
238
248
  /**
@@ -112,10 +112,16 @@ export declare class DiamondHandsSDK {
112
112
  */
113
113
  private getAuthHeader;
114
114
  /**
115
- * Remove the persisted lit-ops-server session (the 24h re-mint envelope and
116
- * its JWT) for the current auth signer. Call on wallet disconnect or
117
- * explicit sign-out so the credential does not outlive the wallet
118
- * connection. No-op in standalone mode.
115
+ * Sign out of the lit-ops-server session for the current auth signer. Call on
116
+ * wallet disconnect or explicit sign-out so the credential does not outlive
117
+ * the wallet connection. No-op in standalone mode.
118
+ *
119
+ * Attempts a server-side revocation first (`ServerSession.logout()` — which
120
+ * tombstones the envelope's 24h re-mint window and invalidates the JWT), then
121
+ * always removes the local credential. If the revocation call fails (offline,
122
+ * server down, wallet already disconnected) we still clear locally so the
123
+ * session cannot silently re-mint after sign-out; `logout()` is best-effort
124
+ * and never prompts the wallet.
119
125
  */
120
126
  clearServerSession(): Promise<void>;
121
127
  /**
@@ -442,6 +448,24 @@ export declare class DiamondHandsSDK {
442
448
  * @returns Withdrawal result with transaction details
443
449
  */
444
450
  withdrawBTC(positionId: string, withdrawalAddress: string, withdrawalAmount: number): Promise<BTCWithdrawalResult>;
451
+ /**
452
+ * TEMPORARY (multi-UTXO withdrawal fix, Phase A): fetch the vault's confirmed
453
+ * UTXO set from lit-ops-server (`GET /api/lit/vault-utxos`) so the caller can
454
+ * assemble and sign the FULL input set for a multi-UTXO consolidation
455
+ * withdrawal. Phase 1 only returns ONE representative UTXO, so a vault whose
456
+ * balance is spread across several UTXOs otherwise fails the Phase-2 signer
457
+ * with "Insufficient UTXO value ... across 1 input(s)".
458
+ *
459
+ * Returns `[]` on any failure (non-service mode, network error, bad shape) so
460
+ * callers transparently fall back to the single authorized UTXO. Superseded
461
+ * by the btc-withdrawal Lit Action returning its own confirmedUTXOs (Phase B).
462
+ */
463
+ fetchConfirmedVaultUtxos(positionId: string): Promise<Array<{
464
+ txid: string;
465
+ vout: number;
466
+ value: number;
467
+ confirmations: number;
468
+ }>>;
445
469
  /**
446
470
  * Execute Bitcoin withdrawal (Phase 2)
447
471
  *
@@ -60,14 +60,31 @@ export declare class ServerSession {
60
60
  private readonly fetchImpl;
61
61
  private cached;
62
62
  private inFlight;
63
+ /**
64
+ * Bumped by `clearPersisted()` (logout / disconnect). An in-flight
65
+ * `getOrRefresh()` captures this at start and refuses to write its freshly
66
+ * minted token back to `this.cached`/the store if the value changed
67
+ * meanwhile — so a refresh racing a sign-out can't silently "un-clear" the
68
+ * credential it was told to drop.
69
+ */
70
+ private generation;
63
71
  /**
64
72
  * Store key for the current signer, memoized on first use so the sync
65
73
  * `clear()` can drop the persisted token without an async address lookup.
66
74
  */
67
75
  private lastStoreKey;
68
76
  constructor(opts: ServerSessionOptions);
69
- /** Returns a JWT good for at least `REFRESH_LEEWAY_SECONDS` more seconds. */
70
- getValidToken(): Promise<string>;
77
+ /**
78
+ * Returns a JWT good for at least `REFRESH_LEEWAY_SECONDS` more seconds.
79
+ * Pass `{ silent: true }` to forbid a fresh wallet signature: it resolves ONLY
80
+ * from a live cached token or the persisted re-mint envelope, never prompting
81
+ * and never joining a prompt-capable in-flight refresh (used by `logout()`,
82
+ * which must never pop the wallet during sign-out). Rejects when only a fresh
83
+ * signature could produce a token.
84
+ */
85
+ getValidToken(opts?: {
86
+ silent?: boolean;
87
+ }): Promise<string>;
71
88
  /** Convenience for fetch: spread directly into `headers`. */
72
89
  getAuthHeader(): Promise<Record<string, string>>;
73
90
  /**
@@ -89,6 +106,18 @@ export declare class ServerSession {
89
106
  * of server response so the client stops presenting the token.
90
107
  */
91
108
  logout(): Promise<void>;
109
+ /**
110
+ * Resolve a session WITHOUT ever prompting for a wallet signature: a live
111
+ * cached token, else the persisted JWT (adopted if still fresh, otherwise
112
+ * silently re-minted from the envelope). Returns `null` only when a fresh
113
+ * wallet signature would be required (dead/absent envelope). Never touches
114
+ * `this.inFlight`, so a silent caller (logout) can resolve independently
115
+ * instead of being dragged into a prompt-capable refresh already in flight.
116
+ *
117
+ * `gen` is the caller's clear-generation snapshot: writes to `this.cached`
118
+ * and the store are skipped if a `clearPersisted()` landed meanwhile.
119
+ */
120
+ private tryResolveSilently;
92
121
  private getOrRefresh;
93
122
  private login;
94
123
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gvnrdao/dh-sdk",
3
- "version": "0.0.303",
3
+ "version": "0.0.305",
4
4
  "description": "TypeScript SDK for Diamond Hands Protocol - Bitcoin-backed lending with LIT Protocol PKPs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -82,8 +82,8 @@
82
82
  },
83
83
  "sideEffects": false,
84
84
  "dependencies": {
85
- "@gvnrdao/dh-lit-actions": "^0.0.314",
86
- "@gvnrdao/dh-lit-ops": "^0.0.304",
85
+ "@gvnrdao/dh-lit-actions": "^0.0.315",
86
+ "@gvnrdao/dh-lit-ops": "^0.0.305",
87
87
  "@noble/hashes": "^1.5.0",
88
88
  "axios": "^1.17.0",
89
89
  "bech32": "^2.0.0",