@droplinked_inc/wallet-connection 0.1.1

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.
@@ -0,0 +1,74 @@
1
+ /** EIP-1193 request method signature. */
2
+ export interface Eip1193RequestArgs {
3
+ readonly method: string;
4
+ readonly params?: readonly unknown[] | object;
5
+ }
6
+ export interface Eip1193Provider {
7
+ request(args: Eip1193RequestArgs): Promise<unknown>;
8
+ readonly isMetaMask?: boolean;
9
+ readonly isCoinbaseWallet?: boolean;
10
+ /** MetaMask's multi-wallet bridge (deprecated but still in the wild). */
11
+ readonly providers?: readonly Eip1193Provider[];
12
+ }
13
+ /**
14
+ * Resolves the EIP-1193 provider from the host environment. Returns
15
+ * undefined when not in a browser or when no injection is present —
16
+ * callers should throw a typed error in that case.
17
+ */
18
+ export declare function getInjectedProvider(): Eip1193Provider | undefined;
19
+ export declare function requireInjectedProvider(): Eip1193Provider;
20
+ /**
21
+ * Canonical rdns identifiers for the wallets this package supports.
22
+ * Match against these — never against `info.name`, which any extension
23
+ * can set.
24
+ */
25
+ export declare const WALLET_RDNS: {
26
+ readonly metamask: "io.metamask";
27
+ readonly coinbase: "com.coinbase.wallet";
28
+ readonly phantom: "app.phantom";
29
+ };
30
+ export type WalletRdns = (typeof WALLET_RDNS)[keyof typeof WALLET_RDNS];
31
+ export interface Eip6963ProviderInfo {
32
+ readonly uuid: string;
33
+ readonly name: string;
34
+ readonly icon: string;
35
+ /** Reverse-DNS identifier — the only spoofing-resistant wallet ID. */
36
+ readonly rdns: string;
37
+ }
38
+ export interface Eip6963ProviderDetail {
39
+ readonly info: Eip6963ProviderInfo;
40
+ readonly provider: Eip1193Provider;
41
+ }
42
+ /**
43
+ * Synchronously collect EIP-6963 provider announcements. Dispatches
44
+ * `eip6963:requestProvider` and listens for `eip6963:announceProvider`
45
+ * responses. Announcements are deduplicated by `info.uuid`.
46
+ *
47
+ * NOTE: EIP-6963 announcements are synchronous; wallets respond to the
48
+ * request event before the dispatch returns. Async polling is not
49
+ * required.
50
+ */
51
+ export declare function discoverEip6963Providers(): ReadonlyMap<string, Eip6963ProviderDetail>;
52
+ /** Find the first announced provider whose `info.rdns` matches `rdns`. */
53
+ export declare function findProviderByRdns(rdns: WalletRdns | string): Eip6963ProviderDetail | undefined;
54
+ /**
55
+ * MetaMask-specific selection.
56
+ *
57
+ * Strict (EIP-6963) path: match on `info.rdns === 'io.metamask'`.
58
+ * Legacy fallback: when no EIP-6963 announcement is heard, fall back to
59
+ * `window.ethereum.isMetaMask` / `ethereum.providers[i].isMetaMask`.
60
+ * The legacy path is strictly weaker — an extension that injects
61
+ * `window.ethereum = { isMetaMask: true, request: drainerRequest }`
62
+ * before MetaMask loads will be matched there. Document this to
63
+ * consumers in JSDoc + THREAT_MODEL.md.
64
+ */
65
+ export declare function selectMetaMaskProvider(): Eip1193Provider;
66
+ export declare function selectCoinbaseProvider(): Eip1193Provider;
67
+ export declare function getAccounts(provider: Eip1193Provider): Promise<string[]>;
68
+ export declare function requestAccounts(provider: Eip1193Provider): Promise<string[]>;
69
+ export declare function getChainId(provider: Eip1193Provider): Promise<string>;
70
+ export declare function isWalletConnected(provider: Eip1193Provider): Promise<boolean>;
71
+ export declare function getBalance(provider: Eip1193Provider, address: string): Promise<bigint>;
72
+ export declare function isMetamaskInstalled(): boolean;
73
+ export declare function isCoinBaseInstalled(): boolean;
74
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAoBA,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAAC;CAC/C;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;CACjD;AAQD;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,eAAe,GAAG,SAAS,CAMjE;AAED,wBAAgB,uBAAuB,IAAI,eAAe,CAMzD;AAaD;;;;GAIG;AACH,eAAO,MAAM,WAAW;;;;CAId,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAExE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CACpC;AA+BD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,IAAI,WAAW,CAAC,MAAM,EAAE,qBAAqB,CAAC,CA2BrF;AAED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAM/F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,IAAI,eAAe,CAgBxD;AAED,wBAAgB,sBAAsB,IAAI,eAAe,CAgBxD;AAED,wBAAsB,WAAW,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAG9E;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGlF;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAG3E;AAED,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAGnF;AAED,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAOjB;AAMD,wBAAgB,mBAAmB,IAAI,OAAO,CAO7C;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAO7C"}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Minimal EIP-1193 provider type and probing helpers.
3
+ *
4
+ * The original v1.0.1 stuffed `window.ethereum` into `any` everywhere. This
5
+ * module replaces that with a typed shape and validates each response.
6
+ *
7
+ * Wallet-impersonation hardening (HIGH-1):
8
+ *
9
+ * `isMetaMask` / `isCoinbaseWallet` are self-reported flags any
10
+ * extension can set. To pick a wallet by *identity* rather than by
11
+ * claim, this module also implements EIP-6963 multi-provider
12
+ * discovery: wallets emit `eip6963:announceProvider` events with a
13
+ * reverse-DNS `rdns` identifier (`io.metamask`, `com.coinbase.wallet`,
14
+ * `app.phantom`, …). When the user picks a wallet we match on `rdns`,
15
+ * not on the spoofable `isXxx` flag. The legacy `window.ethereum`
16
+ * path remains as a fallback with a documented weaker guarantee.
17
+ */
18
+ import { z } from 'zod';
19
+ import { WalletNotFoundException } from './errors.js';
20
+ const AccountsResponseSchema = z.array(z.string().regex(/^0x[a-fA-F0-9]{40}$/u));
21
+ const HexResponseSchema = z.string().regex(/^0x[a-fA-F0-9]*$/u);
22
+ /**
23
+ * Resolves the EIP-1193 provider from the host environment. Returns
24
+ * undefined when not in a browser or when no injection is present —
25
+ * callers should throw a typed error in that case.
26
+ */
27
+ export function getInjectedProvider() {
28
+ if (typeof globalThis === 'undefined') {
29
+ return undefined;
30
+ }
31
+ const w = globalThis;
32
+ return w.ethereum;
33
+ }
34
+ export function requireInjectedProvider() {
35
+ const p = getInjectedProvider();
36
+ if (p === undefined) {
37
+ throw new WalletNotFoundException('No EVM wallet provider found on window');
38
+ }
39
+ return p;
40
+ }
41
+ /* -------------------------------------------------------------------------- */
42
+ /* EIP-6963: Multi-Injected Provider Discovery */
43
+ /* */
44
+ /* https://eips.ethereum.org/EIPS/eip-6963 */
45
+ /* */
46
+ /* Wallets dispatch `eip6963:announceProvider` whenever the page emits */
47
+ /* `eip6963:requestProvider`. We collect announcements into a Map keyed by */
48
+ /* the wallet's reverse-DNS `rdns` identifier — the canonical wallet */
49
+ /* identity, NOT the spoofable `info.name` string. */
50
+ /* -------------------------------------------------------------------------- */
51
+ /**
52
+ * Canonical rdns identifiers for the wallets this package supports.
53
+ * Match against these — never against `info.name`, which any extension
54
+ * can set.
55
+ */
56
+ export const WALLET_RDNS = {
57
+ metamask: 'io.metamask',
58
+ coinbase: 'com.coinbase.wallet',
59
+ phantom: 'app.phantom',
60
+ };
61
+ function getEventTarget() {
62
+ const g = globalThis;
63
+ // Test injection hook — lets node `testEnvironment: 'node'` provide
64
+ // its own EventTarget when one is not natively available.
65
+ if (g.__droplinkedEventTarget__ !== undefined &&
66
+ typeof g.__droplinkedEventTarget__.addEventListener === 'function') {
67
+ return g.__droplinkedEventTarget__;
68
+ }
69
+ if (typeof g.addEventListener === 'function')
70
+ return g;
71
+ if (g.window !== undefined && typeof g.window.addEventListener === 'function')
72
+ return g.window;
73
+ return undefined;
74
+ }
75
+ /**
76
+ * Synchronously collect EIP-6963 provider announcements. Dispatches
77
+ * `eip6963:requestProvider` and listens for `eip6963:announceProvider`
78
+ * responses. Announcements are deduplicated by `info.uuid`.
79
+ *
80
+ * NOTE: EIP-6963 announcements are synchronous; wallets respond to the
81
+ * request event before the dispatch returns. Async polling is not
82
+ * required.
83
+ */
84
+ export function discoverEip6963Providers() {
85
+ const map = new Map();
86
+ const target = getEventTarget();
87
+ if (target === undefined)
88
+ return map;
89
+ const handler = (e) => {
90
+ const ann = e;
91
+ const detail = ann.detail;
92
+ if (detail === undefined ||
93
+ detail.info === undefined ||
94
+ typeof detail.info.uuid !== 'string' ||
95
+ typeof detail.info.rdns !== 'string' ||
96
+ detail.provider === undefined ||
97
+ typeof detail.provider.request !== 'function') {
98
+ return;
99
+ }
100
+ map.set(detail.info.uuid, detail);
101
+ };
102
+ target.addEventListener('eip6963:announceProvider', handler);
103
+ try {
104
+ target.dispatchEvent(new Event('eip6963:requestProvider'));
105
+ }
106
+ finally {
107
+ target.removeEventListener('eip6963:announceProvider', handler);
108
+ }
109
+ return map;
110
+ }
111
+ /** Find the first announced provider whose `info.rdns` matches `rdns`. */
112
+ export function findProviderByRdns(rdns) {
113
+ const map = discoverEip6963Providers();
114
+ for (const detail of map.values()) {
115
+ if (detail.info.rdns === rdns)
116
+ return detail;
117
+ }
118
+ return undefined;
119
+ }
120
+ /**
121
+ * MetaMask-specific selection.
122
+ *
123
+ * Strict (EIP-6963) path: match on `info.rdns === 'io.metamask'`.
124
+ * Legacy fallback: when no EIP-6963 announcement is heard, fall back to
125
+ * `window.ethereum.isMetaMask` / `ethereum.providers[i].isMetaMask`.
126
+ * The legacy path is strictly weaker — an extension that injects
127
+ * `window.ethereum = { isMetaMask: true, request: drainerRequest }`
128
+ * before MetaMask loads will be matched there. Document this to
129
+ * consumers in JSDoc + THREAT_MODEL.md.
130
+ */
131
+ export function selectMetaMaskProvider() {
132
+ const detail = findProviderByRdns(WALLET_RDNS.metamask);
133
+ if (detail !== undefined)
134
+ return detail.provider;
135
+ const root = requireInjectedProvider();
136
+ if (Array.isArray(root.providers)) {
137
+ const mm = root.providers.find((p) => p.isMetaMask === true);
138
+ if (mm === undefined) {
139
+ throw new WalletNotFoundException('MetaMask provider not found');
140
+ }
141
+ return mm;
142
+ }
143
+ if (root.isMetaMask !== true) {
144
+ throw new WalletNotFoundException('MetaMask provider not found');
145
+ }
146
+ return root;
147
+ }
148
+ export function selectCoinbaseProvider() {
149
+ const detail = findProviderByRdns(WALLET_RDNS.coinbase);
150
+ if (detail !== undefined)
151
+ return detail.provider;
152
+ const root = requireInjectedProvider();
153
+ if (Array.isArray(root.providers)) {
154
+ const cb = root.providers.find((p) => p.isCoinbaseWallet === true);
155
+ if (cb === undefined) {
156
+ throw new WalletNotFoundException('Coinbase Wallet provider not found');
157
+ }
158
+ return cb;
159
+ }
160
+ if (root.isCoinbaseWallet !== true) {
161
+ throw new WalletNotFoundException('Coinbase Wallet provider not found');
162
+ }
163
+ return root;
164
+ }
165
+ export async function getAccounts(provider) {
166
+ const raw = await provider.request({ method: 'eth_accounts' });
167
+ return AccountsResponseSchema.parse(raw);
168
+ }
169
+ export async function requestAccounts(provider) {
170
+ const raw = await provider.request({ method: 'eth_requestAccounts' });
171
+ return AccountsResponseSchema.parse(raw);
172
+ }
173
+ export async function getChainId(provider) {
174
+ const raw = await provider.request({ method: 'eth_chainId' });
175
+ return HexResponseSchema.parse(raw);
176
+ }
177
+ export async function isWalletConnected(provider) {
178
+ const accounts = await getAccounts(provider);
179
+ return accounts.length > 0;
180
+ }
181
+ export async function getBalance(provider, address) {
182
+ const raw = await provider.request({
183
+ method: 'eth_getBalance',
184
+ params: [address, 'latest'],
185
+ });
186
+ const hex = HexResponseSchema.parse(raw);
187
+ return BigInt(hex);
188
+ }
189
+ /* -------------------------------------------------------------------------- */
190
+ /* Back-compat free-standing probes (mirror v1.0.1 boolean helpers) */
191
+ /* -------------------------------------------------------------------------- */
192
+ export function isMetamaskInstalled() {
193
+ try {
194
+ selectMetaMaskProvider();
195
+ return true;
196
+ }
197
+ catch {
198
+ return false;
199
+ }
200
+ }
201
+ export function isCoinBaseInstalled() {
202
+ try {
203
+ selectCoinbaseProvider();
204
+ return true;
205
+ }
206
+ catch {
207
+ return false;
208
+ }
209
+ }
210
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Session storage helpers. The original v1.0.1 had no notion of sessions
3
+ * — every call required the caller to pass an address as a string, which
4
+ * encouraged callers to stash addresses in cookies/localStorage with no
5
+ * binding to chain or origin.
6
+ *
7
+ * This module provides a typed, expiring, origin-bound session record.
8
+ * Storage backend is pluggable; defaults to `sessionStorage` (cleared on
9
+ * tab close) rather than `localStorage` (persists forever) — that matches
10
+ * the threat model for wallet sessions.
11
+ */
12
+ import { z } from 'zod';
13
+ import { type EvmAddress } from './types.js';
14
+ import type { Hex } from 'viem';
15
+ /**
16
+ * Hard upper bound on session TTL (HIGH-2 mitigation). Because the
17
+ * raw EIP-712 signature is persisted in sessionStorage alongside the
18
+ * payload, it functions as a bearer credential for whoever can read
19
+ * the storage entry — any XSS in any consumer, any malicious browser
20
+ * extension with the `storage` permission, or a screen-share leak.
21
+ * We refuse to issue a session longer than 15 minutes so the blast
22
+ * radius of a single sessionStorage exfil is bounded.
23
+ *
24
+ * Consumers that need longer-lived sessions MUST exchange the
25
+ * signature for a server-issued opaque session token and drop the
26
+ * raw signature client-side.
27
+ */
28
+ export declare const SESSION_MAX_TTL_SECONDS: number;
29
+ export declare const WalletSessionSchema: z.ZodObject<{
30
+ address: z.ZodEffects<z.ZodString, `0x${string}`, string>;
31
+ chainId: z.ZodNumber;
32
+ origin: z.ZodString;
33
+ signature: z.ZodString;
34
+ issuedAt: z.ZodString;
35
+ expiresAt: z.ZodString;
36
+ }, "strip", z.ZodTypeAny, {
37
+ address: `0x${string}`;
38
+ chainId: number;
39
+ issuedAt: string;
40
+ signature: string;
41
+ origin: string;
42
+ expiresAt: string;
43
+ }, {
44
+ address: string;
45
+ chainId: number;
46
+ issuedAt: string;
47
+ signature: string;
48
+ origin: string;
49
+ expiresAt: string;
50
+ }>;
51
+ export type WalletSession = z.infer<typeof WalletSessionSchema>;
52
+ export interface SessionStorage {
53
+ getItem(key: string): string | null;
54
+ setItem(key: string, value: string): void;
55
+ removeItem(key: string): void;
56
+ }
57
+ export declare function saveSession(session: WalletSession, storage?: SessionStorage | undefined): void;
58
+ export declare function loadSession(storage?: SessionStorage | undefined, nowMs?: number): WalletSession | undefined;
59
+ export declare function clearSession(storage?: SessionStorage | undefined): void;
60
+ export interface BuildSessionArgs {
61
+ readonly address: EvmAddress;
62
+ readonly chainId: number;
63
+ readonly origin: string;
64
+ readonly signature: Hex;
65
+ readonly ttlSeconds: number;
66
+ }
67
+ export declare function buildSession(args: BuildSessionArgs): WalletSession;
68
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE/D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAIhC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,QAAU,CAAC;AAE/C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;EAO9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAOD,wBAAgB,WAAW,CACzB,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,cAAc,GAAG,SAA4B,GACrD,IAAI,CAMN;AAED,wBAAgB,WAAW,CACzB,OAAO,GAAE,cAAc,GAAG,SAA4B,EACtD,KAAK,GAAE,MAAmB,GACzB,aAAa,GAAG,SAAS,CA0B3B;AAED,wBAAgB,YAAY,CAC1B,OAAO,GAAE,cAAc,GAAG,SAA4B,GACrD,IAAI,CAKN;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,aAAa,CAiBlE"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Session storage helpers. The original v1.0.1 had no notion of sessions
3
+ * — every call required the caller to pass an address as a string, which
4
+ * encouraged callers to stash addresses in cookies/localStorage with no
5
+ * binding to chain or origin.
6
+ *
7
+ * This module provides a typed, expiring, origin-bound session record.
8
+ * Storage backend is pluggable; defaults to `sessionStorage` (cleared on
9
+ * tab close) rather than `localStorage` (persists forever) — that matches
10
+ * the threat model for wallet sessions.
11
+ */
12
+ import { z } from 'zod';
13
+ import { EvmAddressSchema } from './types.js';
14
+ import { SignaturePayloadInvalidError } from './errors.js';
15
+ const STORAGE_KEY = 'droplinked:wallet-session:v1';
16
+ /**
17
+ * Hard upper bound on session TTL (HIGH-2 mitigation). Because the
18
+ * raw EIP-712 signature is persisted in sessionStorage alongside the
19
+ * payload, it functions as a bearer credential for whoever can read
20
+ * the storage entry — any XSS in any consumer, any malicious browser
21
+ * extension with the `storage` permission, or a screen-share leak.
22
+ * We refuse to issue a session longer than 15 minutes so the blast
23
+ * radius of a single sessionStorage exfil is bounded.
24
+ *
25
+ * Consumers that need longer-lived sessions MUST exchange the
26
+ * signature for a server-issued opaque session token and drop the
27
+ * raw signature client-side.
28
+ */
29
+ export const SESSION_MAX_TTL_SECONDS = 15 * 60;
30
+ export const WalletSessionSchema = z.object({
31
+ address: EvmAddressSchema,
32
+ chainId: z.number().int().positive(),
33
+ origin: z.string().min(1),
34
+ signature: z.string().regex(/^0x[a-fA-F0-9]+$/u),
35
+ issuedAt: z.string().datetime(),
36
+ expiresAt: z.string().datetime(),
37
+ });
38
+ function defaultStorage() {
39
+ const g = globalThis;
40
+ return g.sessionStorage;
41
+ }
42
+ export function saveSession(session, storage = defaultStorage()) {
43
+ if (storage === undefined) {
44
+ return; // headless / SSR — silently no-op
45
+ }
46
+ WalletSessionSchema.parse(session);
47
+ storage.setItem(STORAGE_KEY, JSON.stringify(session));
48
+ }
49
+ export function loadSession(storage = defaultStorage(), nowMs = Date.now()) {
50
+ if (storage === undefined) {
51
+ return undefined;
52
+ }
53
+ const raw = storage.getItem(STORAGE_KEY);
54
+ if (raw === null) {
55
+ return undefined;
56
+ }
57
+ let parsedJson;
58
+ try {
59
+ parsedJson = JSON.parse(raw);
60
+ }
61
+ catch {
62
+ storage.removeItem(STORAGE_KEY);
63
+ return undefined;
64
+ }
65
+ const result = WalletSessionSchema.safeParse(parsedJson);
66
+ if (!result.success) {
67
+ storage.removeItem(STORAGE_KEY);
68
+ return undefined;
69
+ }
70
+ const exp = Date.parse(result.data.expiresAt);
71
+ if (Number.isNaN(exp) || exp <= nowMs) {
72
+ storage.removeItem(STORAGE_KEY);
73
+ return undefined;
74
+ }
75
+ return result.data;
76
+ }
77
+ export function clearSession(storage = defaultStorage()) {
78
+ if (storage === undefined) {
79
+ return;
80
+ }
81
+ storage.removeItem(STORAGE_KEY);
82
+ }
83
+ export function buildSession(args) {
84
+ if (args.ttlSeconds <= 0 || args.ttlSeconds > SESSION_MAX_TTL_SECONDS) {
85
+ throw new SignaturePayloadInvalidError(`ttlSeconds must be in (0, ${SESSION_MAX_TTL_SECONDS}]; got ${args.ttlSeconds}. ` +
86
+ 'Long-lived sessions MUST be issued server-side, not from this client library.');
87
+ }
88
+ const now = Date.now();
89
+ const session = {
90
+ address: args.address,
91
+ chainId: args.chainId,
92
+ origin: args.origin,
93
+ signature: args.signature,
94
+ issuedAt: new Date(now).toISOString(),
95
+ expiresAt: new Date(now + args.ttlSeconds * 1000).toISOString(),
96
+ };
97
+ return WalletSessionSchema.parse(session);
98
+ }
99
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * EIP-712 typed-data signing + verification.
3
+ *
4
+ * Hardening deltas vs. v1.0.1:
5
+ * 1. v1.0.1 used `personal_sign` of a static plaintext — replayable
6
+ * across chains, origins, time. We use EIP-712 typed data with
7
+ * explicit domain (chainId + origin) and a per-attempt nonce.
8
+ * 2. Nonces are 256-bit cryptographically-random url-safe strings.
9
+ * 3. Signature verification is constant-time at the byte-array level.
10
+ * 4. Recovered address is compared as a normalized lowercase hex string.
11
+ */
12
+ import { type Hex } from 'viem';
13
+ import { type LoginPayload, type EvmAddress } from './types.js';
14
+ import type { Eip1193Provider } from './provider.js';
15
+ /** EIP-712 domain name — kept short, embedded in every signed payload. */
16
+ export declare const TYPED_DATA_DOMAIN_NAME: "droplinked";
17
+ /** EIP-712 type definitions. */
18
+ export declare const LOGIN_TYPES: {
19
+ readonly Login: readonly [{
20
+ readonly name: "domain";
21
+ readonly type: "string";
22
+ }, {
23
+ readonly name: "address";
24
+ readonly type: "address";
25
+ }, {
26
+ readonly name: "statement";
27
+ readonly type: "string";
28
+ }, {
29
+ readonly name: "uri";
30
+ readonly type: "string";
31
+ }, {
32
+ readonly name: "version";
33
+ readonly type: "string";
34
+ }, {
35
+ readonly name: "chainId";
36
+ readonly type: "uint256";
37
+ }, {
38
+ readonly name: "nonce";
39
+ readonly type: "string";
40
+ }, {
41
+ readonly name: "issuedAt";
42
+ readonly type: "string";
43
+ }, {
44
+ readonly name: "expirationTime";
45
+ readonly type: "string";
46
+ }];
47
+ };
48
+ /**
49
+ * Generates a 256-bit random url-safe nonce. Uses Web Crypto when available;
50
+ * throws if no CSPRNG is reachable (we refuse to fall back to Math.random).
51
+ */
52
+ export declare function generateNonce(): string;
53
+ /**
54
+ * Build a canonical login payload. Always binds:
55
+ * - origin (window.location.origin or caller-provided)
56
+ * - chainId (must match the wallet's current chain at signing time)
57
+ * - fresh nonce
58
+ * - issuedAt timestamp
59
+ * - optional expirationTime
60
+ */
61
+ export interface BuildLoginPayloadArgs {
62
+ readonly address: EvmAddress;
63
+ readonly chainId: number;
64
+ readonly origin: string;
65
+ readonly statement?: string;
66
+ readonly expiresInSeconds?: number;
67
+ }
68
+ export declare function buildLoginPayload(args: BuildLoginPayloadArgs): LoginPayload;
69
+ /**
70
+ * Request the wallet to sign the typed payload. Returns the 0x-prefixed
71
+ * signature.
72
+ */
73
+ export declare function signLoginPayload(provider: Eip1193Provider, payload: LoginPayload): Promise<Hex>;
74
+ /**
75
+ * Verify a previously-issued login signature. Server-side and client-side
76
+ * use the same function. Returns void on success, throws on any mismatch.
77
+ */
78
+ export interface VerifyLoginArgs {
79
+ readonly payload: LoginPayload;
80
+ readonly signature: Hex;
81
+ readonly expectedAddress: EvmAddress;
82
+ readonly expectedChainId: number;
83
+ readonly expectedOrigin: string;
84
+ readonly nowMs?: number;
85
+ }
86
+ export declare function verifyLoginSignature(args: VerifyLoginArgs): Promise<void>;
87
+ /**
88
+ * Constant-time string equality. Compares the UTF-8 byte representation;
89
+ * always touches every byte of both inputs regardless of mismatch position.
90
+ * Returns false immediately on length mismatch — note that length is
91
+ * inherently leaky and not considered a secret here.
92
+ */
93
+ export declare function constantTimeStringEquals(a: string, b: string): boolean;
94
+ //# sourceMappingURL=signing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../src/signing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAiC,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAC/D,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAOpB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,0EAA0E;AAC1E,eAAO,MAAM,sBAAsB,EAAG,YAAqB,CAAC;AAE5D,gCAAgC;AAChC,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYd,CAAC;AAEX;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CActC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,YAAY,CA4B3E;AAUD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,GAAG,CAAC,CAmBd;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC;IACxB,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAgE/E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAWtE"}