@gvnrdao/dh-sdk 0.0.309 → 0.0.312
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/index.d.ts +2 -0
- package/dist/index.js +172 -5
- package/dist/index.mjs +168 -5
- package/dist/interfaces/chunks/config.i.d.ts +21 -0
- package/dist/modules/diamond-hands-sdk.d.ts +23 -0
- package/dist/utils/eip712-login.d.ts +13 -1
- package/dist/utils/server-session-store.d.ts +44 -0
- package/dist/utils/server-session.d.ts +37 -0
- package/package.json +1 -1
|
@@ -39,18 +39,62 @@ export interface ServerSessionStore {
|
|
|
39
39
|
load(key: string): PersistedServerSession | null;
|
|
40
40
|
save(key: string, session: PersistedServerSession): void;
|
|
41
41
|
clear(key: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Optional pending-envelope persistence (see `PendingLoginEnvelope`). Optional
|
|
44
|
+
* so a custom store written before this existed still satisfies the interface;
|
|
45
|
+
* without it the session simply mints a fresh envelope each attempt, which is
|
|
46
|
+
* the pre-existing behavior and only costs a multi-owner Safe a restart.
|
|
47
|
+
*/
|
|
48
|
+
loadPending?(key: string): PendingLoginEnvelope | null;
|
|
49
|
+
savePending?(key: string, envelope: PendingLoginEnvelope): void;
|
|
50
|
+
clearPending?(key: string): void;
|
|
42
51
|
}
|
|
43
52
|
export declare function sessionStoreKey(address: string, chainId: number, endpoint: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* The UNSIGNED envelope of a login already collecting signatures.
|
|
55
|
+
*
|
|
56
|
+
* A multi-owner Safe signs across sessions — owner 1 now, owner 2 later — and
|
|
57
|
+
* identifies the pending message solely by its EIP-712 hash. Every field is
|
|
58
|
+
* hashed, so minting a fresh `nonce`/`issuedAt` for the next attempt yields a
|
|
59
|
+
* DIFFERENT hash, which Safe presents as a new message needing its FIRST
|
|
60
|
+
* signature. Whatever owner 1 signed is orphaned, and a 2-of-N Safe can never
|
|
61
|
+
* reach threshold: every retry resets the count to zero.
|
|
62
|
+
*
|
|
63
|
+
* Reusing the envelope makes the re-request hash identically, so Safe shows the
|
|
64
|
+
* same pending message and the next owner ADDS to it. Invisible for an EOA,
|
|
65
|
+
* which signs immediately and spends the envelope.
|
|
66
|
+
*/
|
|
67
|
+
export interface PendingLoginEnvelope {
|
|
68
|
+
issuedAt: number;
|
|
69
|
+
nonce: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* How long an unsigned envelope stays reusable. Must stay UNDER the server's
|
|
73
|
+
* contract-wallet first-use skew (`CONTRACT_ISSUED_AT_SKEW_SECONDS`, 10 min):
|
|
74
|
+
* beyond it the first use is rejected as stale, so reuse would guarantee failure
|
|
75
|
+
* instead of preventing a re-sign.
|
|
76
|
+
*/
|
|
77
|
+
export declare const PENDING_ENVELOPE_TTL_SECONDS: number;
|
|
78
|
+
/** Storage key for the pending envelope matching a session key. */
|
|
79
|
+
export declare function pendingEnvelopeKey(sessionKey: string): string;
|
|
80
|
+
export declare function isPendingEnvelopeShape(value: any): value is PendingLoginEnvelope;
|
|
44
81
|
export declare class LocalStorageSessionStore implements ServerSessionStore {
|
|
45
82
|
load(key: string): PersistedServerSession | null;
|
|
46
83
|
save(key: string, session: PersistedServerSession): void;
|
|
47
84
|
clear(key: string): void;
|
|
85
|
+
loadPending(key: string): PendingLoginEnvelope | null;
|
|
86
|
+
savePending(key: string, envelope: PendingLoginEnvelope): void;
|
|
87
|
+
clearPending(key: string): void;
|
|
48
88
|
}
|
|
49
89
|
export declare class MemorySessionStore implements ServerSessionStore {
|
|
50
90
|
private readonly entries;
|
|
91
|
+
private readonly pending;
|
|
51
92
|
load(key: string): PersistedServerSession | null;
|
|
52
93
|
save(key: string, session: PersistedServerSession): void;
|
|
53
94
|
clear(key: string): void;
|
|
95
|
+
loadPending(key: string): PendingLoginEnvelope | null;
|
|
96
|
+
savePending(key: string, envelope: PendingLoginEnvelope): void;
|
|
97
|
+
clearPending(key: string): void;
|
|
54
98
|
}
|
|
55
99
|
/** `localStorage` when usable (browser, not blocked), else per-instance memory. */
|
|
56
100
|
export declare function createDefaultSessionStore(): ServerSessionStore;
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* `~/.diamond-hands/session.json` for cross-invocation reuse.
|
|
23
23
|
*/
|
|
24
24
|
import type { Signer } from "ethers";
|
|
25
|
+
import { type DhServerLoginPayload } from "./eip712-login";
|
|
25
26
|
import { type ServerSessionStore } from "./server-session-store";
|
|
26
27
|
export interface ServerSessionOptions {
|
|
27
28
|
signer: Signer;
|
|
@@ -34,12 +35,28 @@ export interface ServerSessionOptions {
|
|
|
34
35
|
sessionStore?: ServerSessionStore;
|
|
35
36
|
/** Set false to disable persistence entirely (fresh signature per instance + expiry). */
|
|
36
37
|
persistSession?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Audit M-8 audience to bind the login to. Defaults to `serviceEndpoint`.
|
|
40
|
+
*
|
|
41
|
+
* A caller that shares ONE signature across several services (the browser
|
|
42
|
+
* frontend, which authenticates both lit-ops-server and the api from a single
|
|
43
|
+
* wallet prompt) cannot bind to a single endpoint, so it passes the app audience
|
|
44
|
+
* instead — and every server it talks to must accept that value. Node callers
|
|
45
|
+
* (CLI, MCP, cr-monitor) omit it and keep the endpoint binding unchanged.
|
|
46
|
+
*/
|
|
47
|
+
loginAudience?: string;
|
|
37
48
|
/**
|
|
38
49
|
* Fires immediately before a wallet signature is requested — i.e. only when
|
|
39
50
|
* neither the cached JWT nor the persisted envelope could renew the session,
|
|
40
51
|
* never on the silent paths. Lets UIs show a "check your wallet" prompt.
|
|
41
52
|
*/
|
|
42
53
|
onSignaturePrompt?: () => void;
|
|
54
|
+
/**
|
|
55
|
+
* Fires once the prompted signature has concluded, with whether a session was
|
|
56
|
+
* established. Without it `onSignaturePrompt` has no ending, so a UI showing
|
|
57
|
+
* "check your wallet" can never take it down.
|
|
58
|
+
*/
|
|
59
|
+
onSignatureResolved?: (ok: boolean) => void;
|
|
43
60
|
/** Override for tests. */
|
|
44
61
|
now?: () => number;
|
|
45
62
|
/** Override for tests. */
|
|
@@ -53,9 +70,11 @@ export declare class ServerLoginError extends Error {
|
|
|
53
70
|
export declare class ServerSession {
|
|
54
71
|
private readonly signer;
|
|
55
72
|
private readonly serviceEndpoint;
|
|
73
|
+
private readonly loginAudience;
|
|
56
74
|
private readonly chainId;
|
|
57
75
|
private readonly store;
|
|
58
76
|
private readonly onSignaturePrompt?;
|
|
77
|
+
private readonly onSignatureResolved?;
|
|
59
78
|
private readonly now;
|
|
60
79
|
private readonly fetchImpl;
|
|
61
80
|
private cached;
|
|
@@ -111,6 +130,24 @@ export declare class ServerSession {
|
|
|
111
130
|
* of server response so the client stops presenting the token.
|
|
112
131
|
*/
|
|
113
132
|
logout(): Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* Adopt a login envelope signed ELSEWHERE and exchange it for a session now.
|
|
135
|
+
*
|
|
136
|
+
* The browser frontend collects one wallet signature and spends it at both the
|
|
137
|
+
* api and this service, so the envelope is minted outside the SDK. Without this
|
|
138
|
+
* seam the SDK would mint its own — a second wallet prompt, which for a
|
|
139
|
+
* multi-sig Safe is another full propose-and-confirm ceremony across owners.
|
|
140
|
+
*
|
|
141
|
+
* Must be called PROMPTLY after signing. Each server pins the nonce on FIRST
|
|
142
|
+
* use and requires that first use to be fresh (±120s EOA, ±600s contract
|
|
143
|
+
* wallet); the stores are independent, so a late hand-off is rejected as
|
|
144
|
+
* `stale_first_use` even though the other service already accepted it. After a
|
|
145
|
+
* successful first use, silent re-mint covers the next 24h.
|
|
146
|
+
*
|
|
147
|
+
* No-ops the prompt path entirely: on success the session is cached and
|
|
148
|
+
* persisted exactly as a self-minted login would be.
|
|
149
|
+
*/
|
|
150
|
+
adoptLoginPayload(payload: DhServerLoginPayload): Promise<void>;
|
|
114
151
|
/**
|
|
115
152
|
* Resolve a session WITHOUT ever prompting for a wallet signature: a live
|
|
116
153
|
* cached token, else the persisted JWT (adopted if still fresh, otherwise
|
package/package.json
CHANGED