@gvnrdao/dh-sdk 0.0.318 → 0.0.320
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/browser/dist/browser.js +1 -1
- package/dist/deployments.js +22 -12
- package/dist/deployments.mjs +22 -12
- package/dist/index.js +110 -40
- package/dist/index.mjs +110 -40
- package/dist/modules/diamond-hands-sdk.d.ts +16 -2
- package/dist/utils/server-session-store.d.ts +25 -7
- package/dist/utils/server-session.d.ts +27 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -412,7 +412,7 @@ var init_deployment_addresses = __esm({
|
|
|
412
412
|
LiquidationManagerModule: "0x74B28695352E7bf736D6c9F76ccb7B4439477De9",
|
|
413
413
|
CircuitBreakerModule: "0xF7b545d3a4Ee056D06909AB367E2F7bFFE3cB1BC",
|
|
414
414
|
AdminModule: "0x0023B71B586795eE5fa4E83E384345C1EC8Bb946",
|
|
415
|
-
PositionManagerViews: "
|
|
415
|
+
PositionManagerViews: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
|
|
416
416
|
PositionManager: "0x12A1836e56139ccaD8722B89519d84233efc224B",
|
|
417
417
|
OperationAuthorizationRegistry: "0xD4505645b724754f5170a2027804a4265e860d44",
|
|
418
418
|
ContractVersionRegistry: "0x5e18f77d01940dA5B1D986D373D9A6ad0767008d",
|
|
@@ -490,13 +490,13 @@ var init_deployment_addresses = __esm({
|
|
|
490
490
|
block: 25472957
|
|
491
491
|
},
|
|
492
492
|
PositionManager: {
|
|
493
|
-
previousImplementation: "
|
|
494
|
-
newImplementation: "
|
|
495
|
-
upgradedAt: "2026-
|
|
496
|
-
upgradedBy: "AdminModule
|
|
497
|
-
reason: "
|
|
498
|
-
executeTx: "
|
|
499
|
-
block:
|
|
493
|
+
previousImplementation: "0x600Dc0D1C2c0F94882B6Bc09172f8650047Ad5B1",
|
|
494
|
+
newImplementation: "0x2e7170d6Fb15A876dB726732e72e63109bcB916d",
|
|
495
|
+
upgradedAt: "2026-08-03T08:34:23.000Z",
|
|
496
|
+
upgradedBy: "AdminModule generic-op 0x69b79a906ed2 (3-of-3 signatures, 24h timelock; proposed by 0xEba7BfAeB35ee18408b424Ee0BB45AdDf776589f, executed in the release batch onchain-auth/.safe-batches/mainnet-release-execute-B.json, submitted by EOA 0x2002827d34A781883Ec4c83c36ECC140c3911F2B, tx 0xf1f8d5fc13f45d7a3f932bf1a2d6e29381fdd41cd31298ad785bf7688df07fe6, block 25673200)",
|
|
497
|
+
reason: "2026-08 agent-stack release, Execute B: agent-delegation digest rebind. makePayment/mintUCD/extendPosition now bind their EIP-712 digest to the STORED borrower rather than msg.sender, so a scoped AgentDelegationRegistry grant can submit; withdrawBTC still binds msg.sender and stays non-delegable. Also adds setViews(address), which the same batch used to repoint PM at the replacement PositionManagerViews. NOTE: VERSION reads 1.5.4 on BOTH sides of this upgrade \u2014 verify by implementation ADDRESS, never by VERSION(). NOTE: not the July audit rollout batch \u2014 reconcile-deployment-record.ts --write templates every row with that text; this hand-authored provenance is the accurate one, restore it if --write flattens it again.",
|
|
498
|
+
executeTx: "0xf1f8d5fc13f45d7a3f932bf1a2d6e29381fdd41cd31298ad785bf7688df07fe6",
|
|
499
|
+
block: 25673200
|
|
500
500
|
},
|
|
501
501
|
LoanOperationsManagerModule: {
|
|
502
502
|
previousImplementation: "0x56671D671e492Dae625413d463D47605Cf54edf6",
|
|
@@ -540,6 +540,16 @@ var init_deployment_addresses = __esm({
|
|
|
540
540
|
reason: "2026-08 agent-stack release: PositionDelegateRegistry VERSION 1.1.0 -> 2.0.0 via upgradeToAndCall + initializeV2(AdminModule, registrar 0x5D54E0BE\u2026, pauser 0xC205Ae99\u2026) \u2014 kill-switch, deny-only registrar, permanent delegate burn. NOTE: not the July audit rollout batch \u2014 reconcile-deployment-record.ts --write templates every row with that text; this hand-authored provenance is the accurate one, restore it if --write flattens it again.",
|
|
541
541
|
executeTx: "0xf0f237f6c4e958c37de556571908283c59c3fba6ebf9fa3cefb956f37e315a10",
|
|
542
542
|
block: 25669024
|
|
543
|
+
},
|
|
544
|
+
PositionManagerViews: {
|
|
545
|
+
previousImplementation: "0x9225647a30bbACA4Acc0491B786869036914242e",
|
|
546
|
+
newImplementation: "0xE68DC096A65Ecddbc6A9b5c6e5f878e2CE143Bfe",
|
|
547
|
+
proxy: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
|
|
548
|
+
upgradedAt: "2026-08-03T08:34:23.000Z",
|
|
549
|
+
upgradedBy: "REPLACED, not upgraded. Fresh ERC1967Proxy (atomically initialized) + AdminModule generic-op 0x848a97186f0d PositionManager.setViews(proxy) \u2014 3-of-3, 24h timelock, executed in onchain-auth/.safe-batches/mainnet-release-execute-B.json",
|
|
550
|
+
reason: "2026-08 agent-stack release. The mainnet PositionManagerViews at 0x9225647a was deployed as a BARE implementation (EIP-1967 slot 0x00), so upgradeToAndCall reverts UUPSUnauthorizedCallContext \u2014 it could never be upgraded. PositionManager.setViews (added in the same Execute B batch) removed the repoint blocker, so Views was replaced behind a new proxy rather than upgraded. This makes the Pashov F3 renewal debt-ceiling check REACHABLE for the first time: ExceedsMaxLoan (0x499e7985) is present in 0xE68DC096 and absent from 0x9225647a. Views holds no protocol state (8 wiring slots + roles + pause), which is what made replacement safe. The old contract is ABANDONED, not decommissioned \u2014 it stays live and callable as the rollback target for setViews. NOTE: VERSION reads 1.1.1 on both sides; verify by address.",
|
|
551
|
+
executeTx: "0xf1f8d5fc13f45d7a3f932bf1a2d6e29381fdd41cd31298ad785bf7688df07fe6",
|
|
552
|
+
block: 25673200
|
|
543
553
|
}
|
|
544
554
|
},
|
|
545
555
|
latestEnv: {
|
|
@@ -573,10 +583,10 @@ var init_deployment_addresses = __esm({
|
|
|
573
583
|
ADMIN_MODULE_IMPL: "0xb4C5C7E051A1e672F014B25CB5D55B225Aa0D512",
|
|
574
584
|
BTC_SPEND_AUTHORIZER: "0xfBbF108486fa07F1B06a811C5b66ed68DD9c508a",
|
|
575
585
|
BTC_SPEND_AUTHORIZER_IMPL: "0x40c9e8C46C65E0A57BB63da5368868A9E8Df81A5",
|
|
576
|
-
POSITION_MANAGER_VIEWS: "
|
|
577
|
-
POSITION_MANAGER_VIEWS_IMPL: "
|
|
586
|
+
POSITION_MANAGER_VIEWS: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
|
|
587
|
+
POSITION_MANAGER_VIEWS_IMPL: "0xE68DC096A65Ecddbc6A9b5c6e5f878e2CE143Bfe",
|
|
578
588
|
POSITION_MANAGER: "0x12A1836e56139ccaD8722B89519d84233efc224B",
|
|
579
|
-
POSITION_MANAGER_IMPL: "
|
|
589
|
+
POSITION_MANAGER_IMPL: "0x2e7170d6Fb15A876dB726732e72e63109bcB916d",
|
|
580
590
|
LOAN_OPERATIONS_MANAGER_MODULE: "0x2561974A40F1AEed1251d0A090A83cF8536FB9E9",
|
|
581
591
|
LOAN_OPERATIONS_MANAGER_MODULE_IMPL: "0x7d90aAB4466f59BA9aC9C7a9BF14dC53734336e7",
|
|
582
592
|
UPGRADE_VALIDATOR: "0xC46Ae71F22e3741A6CF46E399aE914C4868fEbed",
|
|
@@ -602,7 +612,7 @@ var init_deployment_addresses = __esm({
|
|
|
602
612
|
LiquidationManagerModule: "0x74B28695352E7bf736D6c9F76ccb7B4439477De9",
|
|
603
613
|
CircuitBreakerModule: "0xF7b545d3a4Ee056D06909AB367E2F7bFFE3cB1BC",
|
|
604
614
|
AdminModule: "0x0023B71B586795eE5fa4E83E384345C1EC8Bb946",
|
|
605
|
-
PositionManagerViews: "
|
|
615
|
+
PositionManagerViews: "0x8B57954eA338c6A6bfF1457f71080e25baFF3937",
|
|
606
616
|
PositionManager: "0x12A1836e56139ccaD8722B89519d84233efc224B",
|
|
607
617
|
OperationAuthorizationRegistry: "0xD4505645b724754f5170a2027804a4265e860d44",
|
|
608
618
|
ContractVersionRegistry: "0x5e18f77d01940dA5B1D986D373D9A6ad0767008d",
|
|
@@ -6521,6 +6531,7 @@ function sessionStoreKey(address, chainId, endpoint) {
|
|
|
6521
6531
|
return STORE_PREFIX + `${address.trim().toLowerCase()}:${chainId}:${endpoint.replace(/\/+$/, "")}`;
|
|
6522
6532
|
}
|
|
6523
6533
|
var PENDING_ENVELOPE_TTL_SECONDS = 8 * 60;
|
|
6534
|
+
var EOA_PENDING_ENVELOPE_TTL_SECONDS = 60;
|
|
6524
6535
|
function pendingEnvelopeKey(sessionKey) {
|
|
6525
6536
|
return sessionKey + ":pending";
|
|
6526
6537
|
}
|
|
@@ -6568,7 +6579,7 @@ var LocalStorageSessionStore = class {
|
|
|
6568
6579
|
} catch {
|
|
6569
6580
|
}
|
|
6570
6581
|
}
|
|
6571
|
-
loadPending(key) {
|
|
6582
|
+
loadPending(key, maxAgeSeconds = PENDING_ENVELOPE_TTL_SECONDS) {
|
|
6572
6583
|
let raw;
|
|
6573
6584
|
try {
|
|
6574
6585
|
raw = window.localStorage.getItem(pendingEnvelopeKey(key));
|
|
@@ -6585,7 +6596,7 @@ var LocalStorageSessionStore = class {
|
|
|
6585
6596
|
return null;
|
|
6586
6597
|
}
|
|
6587
6598
|
const nowSec = Math.floor(Date.now() / 1e3);
|
|
6588
|
-
if (!isPendingEnvelopeShape(parsed) || nowSec >= parsed.issuedAt +
|
|
6599
|
+
if (!isPendingEnvelopeShape(parsed) || nowSec >= parsed.issuedAt + maxAgeSeconds) {
|
|
6589
6600
|
this.clearPending(key);
|
|
6590
6601
|
return null;
|
|
6591
6602
|
}
|
|
@@ -6619,12 +6630,12 @@ var MemorySessionStore = class {
|
|
|
6619
6630
|
clear(key) {
|
|
6620
6631
|
this.entries.delete(key);
|
|
6621
6632
|
}
|
|
6622
|
-
loadPending(key) {
|
|
6633
|
+
loadPending(key, maxAgeSeconds = PENDING_ENVELOPE_TTL_SECONDS) {
|
|
6623
6634
|
const envelope = this.pending.get(key);
|
|
6624
6635
|
if (!envelope)
|
|
6625
6636
|
return null;
|
|
6626
6637
|
const nowSec = Math.floor(Date.now() / 1e3);
|
|
6627
|
-
if (nowSec >= envelope.issuedAt +
|
|
6638
|
+
if (nowSec >= envelope.issuedAt + maxAgeSeconds) {
|
|
6628
6639
|
this.pending.delete(key);
|
|
6629
6640
|
return null;
|
|
6630
6641
|
}
|
|
@@ -6658,15 +6669,23 @@ var REFRESH_LEEWAY_SECONDS = 30;
|
|
|
6658
6669
|
var LOGIN_RETRY_BASE_MS = 3e4;
|
|
6659
6670
|
var LOGIN_RETRY_MAX_MS = 5 * 6e4;
|
|
6660
6671
|
var ServerLoginError = class extends Error {
|
|
6661
|
-
constructor(message, status) {
|
|
6672
|
+
constructor(message, status, reason) {
|
|
6662
6673
|
super(message);
|
|
6663
6674
|
this.status = status;
|
|
6675
|
+
this.reason = reason;
|
|
6664
6676
|
this.name = "ServerLoginError";
|
|
6665
6677
|
}
|
|
6666
6678
|
};
|
|
6667
6679
|
function isLoginRejection(error) {
|
|
6668
6680
|
return error instanceof ServerLoginError && error.status >= 400 && error.status < 500 && error.status !== 429;
|
|
6669
6681
|
}
|
|
6682
|
+
var SPENT_ENVELOPE_REASONS = /* @__PURE__ */ new Set(["replayed_nonce", "expired_issuedAt"]);
|
|
6683
|
+
function isSpentEnvelope(error) {
|
|
6684
|
+
if (!isLoginRejection(error))
|
|
6685
|
+
return false;
|
|
6686
|
+
const { reason, status } = error;
|
|
6687
|
+
return reason ? SPENT_ENVELOPE_REASONS.has(reason) : status === 409;
|
|
6688
|
+
}
|
|
6670
6689
|
var ServerSession = class {
|
|
6671
6690
|
signer;
|
|
6672
6691
|
serviceEndpoint;
|
|
@@ -6697,6 +6716,12 @@ var ServerSession = class {
|
|
|
6697
6716
|
* `clear()` can drop the persisted token without an async address lookup.
|
|
6698
6717
|
*/
|
|
6699
6718
|
lastStoreKey = null;
|
|
6719
|
+
/**
|
|
6720
|
+
* Whether the signer is a smart-contract wallet, memoized after the first
|
|
6721
|
+
* `eth_getCode`. Decides which of the server's two first-use windows bounds
|
|
6722
|
+
* envelope reuse; a signer cannot change kind for the life of the session.
|
|
6723
|
+
*/
|
|
6724
|
+
contractSigner = null;
|
|
6700
6725
|
constructor(opts) {
|
|
6701
6726
|
assertSafeServiceEndpoint(opts.serviceEndpoint);
|
|
6702
6727
|
this.signer = opts.signer;
|
|
@@ -6895,6 +6920,34 @@ var ServerSession = class {
|
|
|
6895
6920
|
return null;
|
|
6896
6921
|
}
|
|
6897
6922
|
}
|
|
6923
|
+
/**
|
|
6924
|
+
* How long a pending envelope for THIS signer may be reused, in seconds.
|
|
6925
|
+
*
|
|
6926
|
+
* The server grants an EOA 120s to make an envelope's first use and a contract
|
|
6927
|
+
* wallet 600s, so one local TTL is necessarily wrong for one of them. Deployed
|
|
6928
|
+
* code has bytecode; an EOA does not — one `eth_getCode`, memoized, settles it.
|
|
6929
|
+
*
|
|
6930
|
+
* Reports the CONTRACT window when it cannot tell, which is the behavior that
|
|
6931
|
+
* shipped before the split. The asymmetry is intended: guessing "EOA" for a
|
|
6932
|
+
* Safe hands it a new message and orphans the owner signatures already
|
|
6933
|
+
* collected, while guessing "contract" for an EOA now costs one rejected
|
|
6934
|
+
* attempt, because a rejection clears the envelope.
|
|
6935
|
+
*/
|
|
6936
|
+
async pendingEnvelopeTtl() {
|
|
6937
|
+
if (this.contractSigner === null) {
|
|
6938
|
+
try {
|
|
6939
|
+
const provider = this.signer.provider;
|
|
6940
|
+
if (!provider)
|
|
6941
|
+
return PENDING_ENVELOPE_TTL_SECONDS;
|
|
6942
|
+
const address = await this.signer.getAddress();
|
|
6943
|
+
const code = await provider.getCode(address);
|
|
6944
|
+
this.contractSigner = typeof code === "string" && code !== "0x";
|
|
6945
|
+
} catch {
|
|
6946
|
+
return PENDING_ENVELOPE_TTL_SECONDS;
|
|
6947
|
+
}
|
|
6948
|
+
}
|
|
6949
|
+
return this.contractSigner ? PENDING_ENVELOPE_TTL_SECONDS : EOA_PENDING_ENVELOPE_TTL_SECONDS;
|
|
6950
|
+
}
|
|
6898
6951
|
async getOrRefresh() {
|
|
6899
6952
|
const nowSec = this.now();
|
|
6900
6953
|
if (this.cached && this.cached.expiresAt - REFRESH_LEEWAY_SECONDS > nowSec) {
|
|
@@ -6916,10 +6969,10 @@ var ServerSession = class {
|
|
|
6916
6969
|
}
|
|
6917
6970
|
this.onSignaturePrompt?.();
|
|
6918
6971
|
let session;
|
|
6972
|
+
const store = this.store;
|
|
6973
|
+
const storeKey = store ? this.lastStoreKey : null;
|
|
6919
6974
|
try {
|
|
6920
|
-
const
|
|
6921
|
-
const storeKey = store ? this.lastStoreKey : null;
|
|
6922
|
-
const reuse = storeKey ? store.loadPending?.(storeKey) ?? void 0 : void 0;
|
|
6975
|
+
const reuse = storeKey ? store.loadPending?.(storeKey, await this.pendingEnvelopeTtl()) ?? void 0 : void 0;
|
|
6923
6976
|
const payload = await buildSignedLoginPayload(
|
|
6924
6977
|
this.signer,
|
|
6925
6978
|
this.chainId,
|
|
@@ -6942,6 +6995,9 @@ var ServerSession = class {
|
|
|
6942
6995
|
this.onSignatureResolved?.(true);
|
|
6943
6996
|
} catch (error) {
|
|
6944
6997
|
this.onSignatureResolved?.(false);
|
|
6998
|
+
if (storeKey && isSpentEnvelope(error)) {
|
|
6999
|
+
store.clearPending?.(storeKey);
|
|
7000
|
+
}
|
|
6945
7001
|
const failures = (this.promptBackoff?.failures ?? 0) + 1;
|
|
6946
7002
|
this.promptBackoff = {
|
|
6947
7003
|
failures,
|
|
@@ -6970,9 +7026,17 @@ var ServerSession = class {
|
|
|
6970
7026
|
});
|
|
6971
7027
|
if (!res.ok) {
|
|
6972
7028
|
const detail = await res.text().catch(() => "");
|
|
7029
|
+
let reason;
|
|
7030
|
+
try {
|
|
7031
|
+
const parsed = JSON.parse(detail);
|
|
7032
|
+
if (typeof parsed?.reason === "string")
|
|
7033
|
+
reason = parsed.reason;
|
|
7034
|
+
} catch {
|
|
7035
|
+
}
|
|
6973
7036
|
throw new ServerLoginError(
|
|
6974
7037
|
`lit-ops-server login failed: HTTP ${res.status} ${detail.slice(0, 200)}`,
|
|
6975
|
-
res.status
|
|
7038
|
+
res.status,
|
|
7039
|
+
reason
|
|
6976
7040
|
);
|
|
6977
7041
|
}
|
|
6978
7042
|
const body = await res.json();
|
|
@@ -12627,7 +12691,7 @@ var DiamondHandsGraph = class {
|
|
|
12627
12691
|
async getPSMConfiguration() {
|
|
12628
12692
|
const query = `
|
|
12629
12693
|
query GetPSMConfiguration {
|
|
12630
|
-
psmConfiguration(id: "psm") {
|
|
12694
|
+
psmConfiguration: psmconfiguration(id: "psm") {
|
|
12631
12695
|
id
|
|
12632
12696
|
version
|
|
12633
12697
|
redeemEnabled
|
|
@@ -12749,7 +12813,7 @@ var DiamondHandsGraph = class {
|
|
|
12749
12813
|
const whereClause = whereConditions.length > 0 ? `where: { ${whereConditions.join(", ")} }` : "";
|
|
12750
12814
|
const query = `
|
|
12751
12815
|
query GetPSMTransactions($first: Int!, $skip: Int!) {
|
|
12752
|
-
psmTransactions(${whereClause}, first: $first, skip: $skip, orderBy: timestamp, orderDirection: desc) {
|
|
12816
|
+
psmTransactions: psmtransactions(${whereClause}, first: $first, skip: $skip, orderBy: timestamp, orderDirection: desc) {
|
|
12753
12817
|
id
|
|
12754
12818
|
type
|
|
12755
12819
|
user
|
|
@@ -12784,7 +12848,7 @@ var DiamondHandsGraph = class {
|
|
|
12784
12848
|
const whereClause = whereConditions.length > 0 ? `where: { ${whereConditions.join(", ")} }` : "";
|
|
12785
12849
|
const query = `
|
|
12786
12850
|
query GetPSMDailyMetrics($first: Int!) {
|
|
12787
|
-
psmDailyMetrics(${whereClause}, first: $first, orderBy: date, orderDirection: desc) {
|
|
12851
|
+
psmDailyMetrics: psmdailyMetrics(${whereClause}, first: $first, orderBy: date, orderDirection: desc) {
|
|
12788
12852
|
id
|
|
12789
12853
|
date
|
|
12790
12854
|
totalSwapVolume
|
|
@@ -13508,7 +13572,7 @@ var DiamondHandsGraph = class {
|
|
|
13508
13572
|
}` : ""}
|
|
13509
13573
|
|
|
13510
13574
|
${includeKind("psm") ? `
|
|
13511
|
-
psmTransactions(
|
|
13575
|
+
psmTransactions: psmtransactions(
|
|
13512
13576
|
${buildTimeWhereClause()}
|
|
13513
13577
|
first: $limit, orderBy: timestamp, orderDirection: $orderDirection
|
|
13514
13578
|
) {
|
|
@@ -24571,22 +24635,28 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24571
24635
|
* @throws if timeout is reached before subgraph catches up
|
|
24572
24636
|
*/
|
|
24573
24637
|
// ============================================================================
|
|
24574
|
-
// HIGH-LEVEL API - Agent Delegation (auto-renew)
|
|
24638
|
+
// HIGH-LEVEL API - Agent Delegation (auto-renew)
|
|
24575
24639
|
// ============================================================================
|
|
24576
|
-
/**
|
|
24577
|
-
|
|
24578
|
-
|
|
24579
|
-
|
|
24580
|
-
|
|
24581
|
-
|
|
24582
|
-
|
|
24583
|
-
|
|
24584
|
-
|
|
24585
|
-
|
|
24640
|
+
/**
|
|
24641
|
+
* Guard: resolve the AgentDelegationRegistry for the configured network.
|
|
24642
|
+
*
|
|
24643
|
+
* Deployment presence IS the availability test — there is deliberately no chainId
|
|
24644
|
+
* allow-list here. The registry is deployed per network (Sepolia 2026-07, mainnet
|
|
24645
|
+
* 2026-08 agent-stack release) and `getNetworkConfig` populates the address from the
|
|
24646
|
+
* generated deployment table, so a chain without a deployment resolves to `""` and
|
|
24647
|
+
* fails closed below. Adding a chain therefore needs no SDK code change — which is
|
|
24648
|
+
* exactly how the previous hardcoded `chainId !== 11155111` gate went stale and kept
|
|
24649
|
+
* the mainnet toggle dark after the registry shipped.
|
|
24650
|
+
*
|
|
24651
|
+
* Callers that need the availability answer WITHOUT throwing (e.g. to decide whether to
|
|
24652
|
+
* render a toggle at all) should ask the deployment table directly rather than calling this
|
|
24653
|
+
* and catching — `ALL_DEPLOYMENTS` is published on the `@gvnrdao/dh-sdk/deployments` subpath.
|
|
24654
|
+
*/
|
|
24655
|
+
agentDelegationRegistryOrThrow() {
|
|
24586
24656
|
const addr = this.config.contractAddresses?.agentDelegationRegistry;
|
|
24587
24657
|
if (!addr) {
|
|
24588
24658
|
throw new SDKError({
|
|
24589
|
-
message: "AgentDelegationRegistry
|
|
24659
|
+
message: "AgentDelegationRegistry is not available on this network \u2014 no deployment address is configured (contractAddresses.agentDelegationRegistry)",
|
|
24590
24660
|
category: "CONFIGURATION" /* CONFIGURATION */,
|
|
24591
24661
|
severity: "HIGH" /* HIGH */
|
|
24592
24662
|
});
|
|
@@ -24598,7 +24668,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24598
24668
|
* Pure view — no signer required.
|
|
24599
24669
|
*/
|
|
24600
24670
|
async getAutoRenewStatus(positionId, user) {
|
|
24601
|
-
const addr =
|
|
24671
|
+
const addr = this.agentDelegationRegistryOrThrow();
|
|
24602
24672
|
const registry = AgentDelegationRegistry__factory.connect(addr, this.getProviderOrThrow());
|
|
24603
24673
|
const pid = this.toBytes32(positionId);
|
|
24604
24674
|
const grant = await registry.getLoanGrant(pid);
|
|
@@ -24618,7 +24688,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24618
24688
|
* registers it, then records the position's renew grant. Borrower-signed.
|
|
24619
24689
|
*/
|
|
24620
24690
|
async enableAutoRenew(positionId, options) {
|
|
24621
|
-
const addr =
|
|
24691
|
+
const addr = this.agentDelegationRegistryOrThrow();
|
|
24622
24692
|
const pdrAddr = this.config.contractAddresses?.positionDelegateRegistry;
|
|
24623
24693
|
if (!pdrAddr) {
|
|
24624
24694
|
throw new SDKError({
|
|
@@ -24658,7 +24728,7 @@ Message: ${causeMessage}${quantumContext}${mintDebtDiagnostics}`
|
|
|
24658
24728
|
}
|
|
24659
24729
|
/** Disable auto-renew delegation for a position (clears the grant). Borrower-signed. */
|
|
24660
24730
|
async disableAutoRenew(positionId) {
|
|
24661
|
-
const addr =
|
|
24731
|
+
const addr = this.agentDelegationRegistryOrThrow();
|
|
24662
24732
|
const signer = this.getSignerOrThrow();
|
|
24663
24733
|
const user = await signer.getAddress();
|
|
24664
24734
|
const registry = AgentDelegationRegistry__factory.connect(addr, signer);
|
|
@@ -887,8 +887,22 @@ export declare class DiamondHandsSDK {
|
|
|
887
887
|
* @param options - Override timeout/interval for this call
|
|
888
888
|
* @throws if timeout is reached before subgraph catches up
|
|
889
889
|
*/
|
|
890
|
-
/**
|
|
891
|
-
|
|
890
|
+
/**
|
|
891
|
+
* Guard: resolve the AgentDelegationRegistry for the configured network.
|
|
892
|
+
*
|
|
893
|
+
* Deployment presence IS the availability test — there is deliberately no chainId
|
|
894
|
+
* allow-list here. The registry is deployed per network (Sepolia 2026-07, mainnet
|
|
895
|
+
* 2026-08 agent-stack release) and `getNetworkConfig` populates the address from the
|
|
896
|
+
* generated deployment table, so a chain without a deployment resolves to `""` and
|
|
897
|
+
* fails closed below. Adding a chain therefore needs no SDK code change — which is
|
|
898
|
+
* exactly how the previous hardcoded `chainId !== 11155111` gate went stale and kept
|
|
899
|
+
* the mainnet toggle dark after the registry shipped.
|
|
900
|
+
*
|
|
901
|
+
* Callers that need the availability answer WITHOUT throwing (e.g. to decide whether to
|
|
902
|
+
* render a toggle at all) should ask the deployment table directly rather than calling this
|
|
903
|
+
* and catching — `ALL_DEPLOYMENTS` is published on the `@gvnrdao/dh-sdk/deployments` subpath.
|
|
904
|
+
*/
|
|
905
|
+
private agentDelegationRegistryOrThrow;
|
|
892
906
|
/**
|
|
893
907
|
* Read a position's auto-renew delegation state (used to drive the Enable/Disable toggle).
|
|
894
908
|
* Pure view — no signer required.
|
|
@@ -44,8 +44,12 @@ export interface ServerSessionStore {
|
|
|
44
44
|
* so a custom store written before this existed still satisfies the interface;
|
|
45
45
|
* without it the session simply mints a fresh envelope each attempt, which is
|
|
46
46
|
* the pre-existing behavior and only costs a multi-owner Safe a restart.
|
|
47
|
+
*
|
|
48
|
+
* `maxAgeSeconds` is supplied by the caller, which knows the signer kind and
|
|
49
|
+
* therefore which of the server's two first-use windows applies. A store that
|
|
50
|
+
* ignores it keeps the old single-TTL behavior.
|
|
47
51
|
*/
|
|
48
|
-
loadPending?(key: string): PendingLoginEnvelope | null;
|
|
52
|
+
loadPending?(key: string, maxAgeSeconds?: number): PendingLoginEnvelope | null;
|
|
49
53
|
savePending?(key: string, envelope: PendingLoginEnvelope): void;
|
|
50
54
|
clearPending?(key: string): void;
|
|
51
55
|
}
|
|
@@ -69,12 +73,26 @@ export interface PendingLoginEnvelope {
|
|
|
69
73
|
nonce: string;
|
|
70
74
|
}
|
|
71
75
|
/**
|
|
72
|
-
* How long an unsigned envelope stays reusable. Must stay
|
|
73
|
-
* contract-wallet first-use skew
|
|
74
|
-
* beyond it the first use is
|
|
75
|
-
* instead of preventing a
|
|
76
|
+
* How long an unsigned envelope stays reusable FOR A CONTRACT WALLET. Must stay
|
|
77
|
+
* UNDER the server's contract-wallet first-use skew
|
|
78
|
+
* (`CONTRACT_ISSUED_AT_SKEW_SECONDS`, 10 min): beyond it the first use is
|
|
79
|
+
* rejected as stale, so reuse would guarantee failure instead of preventing a
|
|
80
|
+
* re-sign.
|
|
76
81
|
*/
|
|
77
82
|
export declare const PENDING_ENVELOPE_TTL_SECONDS: number;
|
|
83
|
+
/**
|
|
84
|
+
* The same, for an EOA — which the server gives only `ISSUED_AT_SKEW_SECONDS`
|
|
85
|
+
* (120s) to make its FIRST use.
|
|
86
|
+
*
|
|
87
|
+
* Between 120s and 8 minutes a reused EOA envelope is still "live" locally and
|
|
88
|
+
* certain to be refused by the server, so the contract-wallet TTL is not a safe
|
|
89
|
+
* over-estimate for a key-holding wallet — it is a window in which every retry
|
|
90
|
+
* re-signs a message that cannot be accepted. 60s leaves a full minute of the
|
|
91
|
+
* server's window for the prompt and the round trip, and an EOA gives up
|
|
92
|
+
* nothing by re-minting: it signs in one click, so it has no equivalent of the
|
|
93
|
+
* cross-session ceremony this reuse exists for.
|
|
94
|
+
*/
|
|
95
|
+
export declare const EOA_PENDING_ENVELOPE_TTL_SECONDS = 60;
|
|
78
96
|
/** Storage key for the pending envelope matching a session key. */
|
|
79
97
|
export declare function pendingEnvelopeKey(sessionKey: string): string;
|
|
80
98
|
export declare function isPendingEnvelopeShape(value: any): value is PendingLoginEnvelope;
|
|
@@ -82,7 +100,7 @@ export declare class LocalStorageSessionStore implements ServerSessionStore {
|
|
|
82
100
|
load(key: string): PersistedServerSession | null;
|
|
83
101
|
save(key: string, session: PersistedServerSession): void;
|
|
84
102
|
clear(key: string): void;
|
|
85
|
-
loadPending(key: string): PendingLoginEnvelope | null;
|
|
103
|
+
loadPending(key: string, maxAgeSeconds?: number): PendingLoginEnvelope | null;
|
|
86
104
|
savePending(key: string, envelope: PendingLoginEnvelope): void;
|
|
87
105
|
clearPending(key: string): void;
|
|
88
106
|
}
|
|
@@ -92,7 +110,7 @@ export declare class MemorySessionStore implements ServerSessionStore {
|
|
|
92
110
|
load(key: string): PersistedServerSession | null;
|
|
93
111
|
save(key: string, session: PersistedServerSession): void;
|
|
94
112
|
clear(key: string): void;
|
|
95
|
-
loadPending(key: string): PendingLoginEnvelope | null;
|
|
113
|
+
loadPending(key: string, maxAgeSeconds?: number): PendingLoginEnvelope | null;
|
|
96
114
|
savePending(key: string, envelope: PendingLoginEnvelope): void;
|
|
97
115
|
clearPending(key: string): void;
|
|
98
116
|
}
|
|
@@ -62,10 +62,15 @@ export interface ServerSessionOptions {
|
|
|
62
62
|
/** Override for tests. */
|
|
63
63
|
fetchImpl?: typeof fetch;
|
|
64
64
|
}
|
|
65
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Login failure carrying the HTTP status — and the server's machine-readable
|
|
67
|
+
* `reason` where it sent one — so callers can tell rejection from outage, and
|
|
68
|
+
* one kind of rejection from another.
|
|
69
|
+
*/
|
|
66
70
|
export declare class ServerLoginError extends Error {
|
|
67
71
|
readonly status: number;
|
|
68
|
-
|
|
72
|
+
readonly reason?: string | undefined;
|
|
73
|
+
constructor(message: string, status: number, reason?: string | undefined);
|
|
69
74
|
}
|
|
70
75
|
export declare class ServerSession {
|
|
71
76
|
private readonly signer;
|
|
@@ -97,6 +102,12 @@ export declare class ServerSession {
|
|
|
97
102
|
* `clear()` can drop the persisted token without an async address lookup.
|
|
98
103
|
*/
|
|
99
104
|
private lastStoreKey;
|
|
105
|
+
/**
|
|
106
|
+
* Whether the signer is a smart-contract wallet, memoized after the first
|
|
107
|
+
* `eth_getCode`. Decides which of the server's two first-use windows bounds
|
|
108
|
+
* envelope reuse; a signer cannot change kind for the life of the session.
|
|
109
|
+
*/
|
|
110
|
+
private contractSigner;
|
|
100
111
|
constructor(opts: ServerSessionOptions);
|
|
101
112
|
/**
|
|
102
113
|
* Returns a JWT good for at least `REFRESH_LEEWAY_SECONDS` more seconds.
|
|
@@ -160,6 +171,20 @@ export declare class ServerSession {
|
|
|
160
171
|
* and the store are skipped if a `clearPersisted()` landed meanwhile.
|
|
161
172
|
*/
|
|
162
173
|
private tryResolveSilently;
|
|
174
|
+
/**
|
|
175
|
+
* How long a pending envelope for THIS signer may be reused, in seconds.
|
|
176
|
+
*
|
|
177
|
+
* The server grants an EOA 120s to make an envelope's first use and a contract
|
|
178
|
+
* wallet 600s, so one local TTL is necessarily wrong for one of them. Deployed
|
|
179
|
+
* code has bytecode; an EOA does not — one `eth_getCode`, memoized, settles it.
|
|
180
|
+
*
|
|
181
|
+
* Reports the CONTRACT window when it cannot tell, which is the behavior that
|
|
182
|
+
* shipped before the split. The asymmetry is intended: guessing "EOA" for a
|
|
183
|
+
* Safe hands it a new message and orphans the owner signatures already
|
|
184
|
+
* collected, while guessing "contract" for an EOA now costs one rejected
|
|
185
|
+
* attempt, because a rejection clears the envelope.
|
|
186
|
+
*/
|
|
187
|
+
private pendingEnvelopeTtl;
|
|
163
188
|
private getOrRefresh;
|
|
164
189
|
private login;
|
|
165
190
|
/**
|
package/package.json
CHANGED