@x1id/resolve 0.22.0 → 0.43.0

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.
Files changed (51) hide show
  1. package/README.md +71 -0
  2. package/dist/accounts.d.ts +6 -0
  3. package/dist/accounts.js +6 -1
  4. package/dist/agent.d.ts +184 -8
  5. package/dist/agent.js +351 -3
  6. package/dist/agentPolicy.d.ts +238 -0
  7. package/dist/agentPolicy.js +364 -0
  8. package/dist/attestation.d.ts +25 -0
  9. package/dist/attestation.js +25 -0
  10. package/dist/checkout.d.ts +216 -0
  11. package/dist/checkout.js +327 -0
  12. package/dist/credentials.d.ts +466 -0
  13. package/dist/credentials.js +669 -0
  14. package/dist/gate.d.ts +94 -4
  15. package/dist/gate.js +206 -7
  16. package/dist/gateClient.d.ts +12 -0
  17. package/dist/giftLink.d.ts +272 -0
  18. package/dist/giftLink.js +452 -0
  19. package/dist/index.d.ts +14 -0
  20. package/dist/index.js +33 -0
  21. package/dist/loginButton.d.ts +69 -0
  22. package/dist/loginButton.js +207 -0
  23. package/dist/logo.d.ts +1 -0
  24. package/dist/logo.js +8 -0
  25. package/dist/messaging.d.ts +439 -0
  26. package/dist/messaging.js +979 -0
  27. package/dist/mintNft.d.ts +247 -0
  28. package/dist/mintNft.js +328 -0
  29. package/dist/nsGate.d.ts +98 -0
  30. package/dist/nsGate.js +172 -0
  31. package/dist/oidc.d.ts +272 -0
  32. package/dist/oidc.js +641 -0
  33. package/dist/pay.d.ts +513 -0
  34. package/dist/pay.js +756 -0
  35. package/dist/payment.d.ts +9 -2
  36. package/dist/payment.js +9 -2
  37. package/dist/recovery.d.ts +186 -0
  38. package/dist/recovery.js +276 -0
  39. package/dist/recoveryNft.d.ts +183 -0
  40. package/dist/recoveryNft.js +291 -0
  41. package/dist/shield.d.ts +373 -0
  42. package/dist/shield.js +695 -0
  43. package/dist/subscription.d.ts +439 -0
  44. package/dist/subscription.js +642 -0
  45. package/dist/textRecords.d.ts +52 -6
  46. package/dist/textRecords.js +80 -8
  47. package/dist/types.d.ts +3 -0
  48. package/dist/x402Receipt.d.ts +246 -0
  49. package/dist/x402Receipt.js +374 -0
  50. package/package.json +18 -1
  51. package/schema/agent-manifest.json +91 -8
package/dist/nsGate.js ADDED
@@ -0,0 +1,172 @@
1
+ /**
2
+ * TLD token gate (program upgrade 6, OpenProject #8457; spec
3
+ * docs/specs/tld-communities.md §2).
4
+ *
5
+ * A TLD creator sets `["ns_gate", label]` = { mint, min_amount } with
6
+ * {@link buildSetNamespaceGateIx}; the namespace's registration mode becomes
7
+ * `TokenGated` (2). A non-creator, non-minter payer then registers through
8
+ * `register_under_namespace_v2` with two more remaining accounts after the
9
+ * pricing PDA: the gate PDA and a token account of the gate mint owned by the
10
+ * RECIPIENT (the registration's `owner`, the new name's owner) holding
11
+ * `>= min_amount` ({@link appendNamespaceGateAccounts}). The gate checks who
12
+ * RECEIVES the name, never who pays: a holder cannot buy a gated name for a
13
+ * non-holder, and anyone may pay for a holder. A creator or authorised-minter
14
+ * PAYER bypasses the gate (issuing to anyone).
15
+ *
16
+ * {@link decodeRegistrationMode} FAILS CLOSED: any byte other than 0 (Open)
17
+ * is not open — 1 is invite-only, 2 token-gated, anything else "restricted".
18
+ */
19
+ import { encodeBase58, decodeBase58_32 } from "./base58.js";
20
+ export const NAMESPACE_GATE_SEED = "ns_gate";
21
+ export const SET_NAMESPACE_GATE_DISCRIMINATOR = Uint8Array.from([1, 89, 110, 52, 27, 181, 228, 203]);
22
+ export const CLEAR_NAMESPACE_GATE_DISCRIMINATOR = Uint8Array.from([168, 198, 44, 238, 202, 217, 63, 7]);
23
+ /** `sha256("account:NamespaceGate")[0..8]`. */
24
+ export const NAMESPACE_GATE_ACCOUNT_DISCRIMINATOR = Uint8Array.from([76, 234, 116, 167, 238, 185, 71, 218]);
25
+ /** `NamespaceRegistrationMode` bytes. */
26
+ export const NAMESPACE_MODE_OPEN = 0;
27
+ export const NAMESPACE_MODE_INVITE_ONLY = 1;
28
+ export const NAMESPACE_MODE_TOKEN_GATED = 2;
29
+ /** Program error codes (NsGateError, offset 6220). */
30
+ export const NAMESPACE_GATE_ERRORS = {
31
+ 6220: "NsGateRequired",
32
+ 6221: "NsGateMismatch",
33
+ 6222: "NsGateTokenAccountMismatch",
34
+ 6223: "NsGateBalanceTooLow",
35
+ 6224: "NsGateInvalid",
36
+ };
37
+ /** Map a raw mode byte. FAIL CLOSED: only 0 is open; an unknown value (a
38
+ * future mode this client does not know) is "restricted", never "open". */
39
+ export function decodeRegistrationMode(byte) {
40
+ if (byte === NAMESPACE_MODE_OPEN)
41
+ return "open";
42
+ if (byte === NAMESPACE_MODE_INVITE_ONLY)
43
+ return "invite-only";
44
+ if (byte === NAMESPACE_MODE_TOKEN_GATED)
45
+ return "token-gated";
46
+ return "restricted";
47
+ }
48
+ const SYSTEM_PROGRAM = "11111111111111111111111111111111";
49
+ const TE = new TextEncoder();
50
+ function bytes(v, what) {
51
+ if (typeof v === "string") {
52
+ const b = decodeBase58_32(v);
53
+ if (!b)
54
+ throw new Error(`${what} is not a valid base58 address`);
55
+ return b;
56
+ }
57
+ if (v.length !== 32)
58
+ throw new Error(`${what} must be exactly 32 bytes`);
59
+ return v;
60
+ }
61
+ function k(v, what, isSigner, isWritable) {
62
+ return { pubkey: encodeBase58(bytes(v, what)), isSigner, isWritable };
63
+ }
64
+ function borshStr(s) {
65
+ const b = TE.encode(s);
66
+ const out = new Uint8Array(4 + b.length);
67
+ new DataView(out.buffer).setUint32(0, b.length, true);
68
+ out.set(b, 4);
69
+ return out;
70
+ }
71
+ /** `["ns_gate", label]`. */
72
+ export async function deriveNamespaceGatePda(find, programId, label) {
73
+ return find([TE.encode(NAMESPACE_GATE_SEED), TE.encode(label)], encodeBase58(bytes(programId, "programId")));
74
+ }
75
+ /** `set_namespace_gate(label, mint, min_amount)`: creator(s,w), namespace(w), ns_gate(w), mint, system. Sets mode 2. */
76
+ export function buildSetNamespaceGateIx(p) {
77
+ if (typeof p.minAmount !== "bigint" || p.minAmount <= 0n || p.minAmount > 0xffffffffffffffffn) {
78
+ throw new Error("minAmount must be a u64 bigint > 0");
79
+ }
80
+ const amt = new Uint8Array(8);
81
+ new DataView(amt.buffer).setBigUint64(0, p.minAmount, true);
82
+ const label = borshStr(p.label);
83
+ const data = new Uint8Array(8 + label.length + 32 + 8);
84
+ data.set(SET_NAMESPACE_GATE_DISCRIMINATOR, 0);
85
+ data.set(label, 8);
86
+ data.set(bytes(p.mint, "mint"), 8 + label.length);
87
+ data.set(amt, 8 + label.length + 32);
88
+ return {
89
+ programId: encodeBase58(bytes(p.programId, "programId")),
90
+ keys: [
91
+ k(p.creator, "creator", true, true),
92
+ k(p.namespace, "namespace", false, true),
93
+ k(p.namespaceGate, "namespaceGate", false, true),
94
+ k(p.mint, "mint", false, false),
95
+ k(SYSTEM_PROGRAM, "systemProgram", false, false),
96
+ ],
97
+ data,
98
+ };
99
+ }
100
+ /** `clear_namespace_gate(label)`: creator(s,w), namespace(w), ns_gate(w). Mode 2 returns to Open. */
101
+ export function buildClearNamespaceGateIx(p) {
102
+ const label = borshStr(p.label);
103
+ const data = new Uint8Array(8 + label.length);
104
+ data.set(CLEAR_NAMESPACE_GATE_DISCRIMINATOR, 0);
105
+ data.set(label, 8);
106
+ return {
107
+ programId: encodeBase58(bytes(p.programId, "programId")),
108
+ keys: [
109
+ k(p.creator, "creator", true, true),
110
+ k(p.namespace, "namespace", false, true),
111
+ k(p.namespaceGate, "namespaceGate", false, true),
112
+ ],
113
+ data,
114
+ };
115
+ }
116
+ /**
117
+ * Append the gate accounts to a `buildRegisterUnderNamespaceV2Ix` result
118
+ * (which ends with the pricing PDA at `remaining_accounts[0]`): `[1]` the
119
+ * `["ns_gate", label]` PDA, `[2]` a gate-mint token account OWNED BY THE
120
+ * RECIPIENT (the instruction's `owner`, not the payer). Not needed when the
121
+ * payer is the creator or an authorised minter.
122
+ */
123
+ export function appendNamespaceGateAccounts(ix, namespaceGate, ownerTokenAccount) {
124
+ return {
125
+ ...ix,
126
+ keys: [...ix.keys, k(namespaceGate, "namespaceGate", false, false), k(ownerTokenAccount, "ownerTokenAccount", false, false)],
127
+ };
128
+ }
129
+ /**
130
+ * Client-side mirror of the program's gate test, for UI pre-checks (the
131
+ * program is the authority). `payer` decides the bypass (creator, or a
132
+ * minter the caller knows is authorised); otherwise the `recipient` must own
133
+ * `tokenAccount` (decoded base layout: `owner`, `mint`, `amount`) of the gate
134
+ * mint with `amount >= gate.minAmount`.
135
+ */
136
+ export function namespaceGateAllows(p) {
137
+ const eq = (a, b, w) => encodeBase58(bytes(a, w)) === encodeBase58(bytes(b, w));
138
+ if (eq(p.payer, p.creator, "payer") || p.payerIsAuthorisedMinter === true)
139
+ return true;
140
+ const ta = p.tokenAccount;
141
+ if (!ta)
142
+ return false;
143
+ return eq(ta.mint, p.gate.mint, "mint") && eq(ta.owner, p.recipient, "recipient") && ta.amount >= p.gate.minAmount;
144
+ }
145
+ /** Decode a `NamespaceGate` (disc | version | bump | mint@10 | token_program@42 | min_amount@74 | updated_at@82 | label@90). */
146
+ export function decodeNamespaceGate(data) {
147
+ if (data.length < 94)
148
+ return null;
149
+ for (let i = 0; i < 8; i++)
150
+ if (data[i] !== NAMESPACE_GATE_ACCOUNT_DISCRIMINATOR[i])
151
+ return null;
152
+ const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);
153
+ const len = dv.getUint32(90, true);
154
+ if (len > 16 || data.length < 94 + len)
155
+ return null;
156
+ let label;
157
+ try {
158
+ label = new TextDecoder("utf-8", { fatal: true }).decode(data.subarray(94, 94 + len));
159
+ }
160
+ catch {
161
+ return null;
162
+ }
163
+ return {
164
+ version: data[8],
165
+ bump: data[9],
166
+ mint: encodeBase58(data.subarray(10, 42)),
167
+ tokenProgram: encodeBase58(data.subarray(42, 74)),
168
+ minAmount: dv.getBigUint64(74, true),
169
+ updatedAt: dv.getBigInt64(82, true),
170
+ label,
171
+ };
172
+ }
package/dist/oidc.d.ts ADDED
@@ -0,0 +1,272 @@
1
+ /**
2
+ * "Sign in with X1ID" — a relying-party (RP) client for the X1ID OpenID Connect
3
+ * provider at `https://auth.x1id.io` (services/auth, OpenProject #8842).
4
+ *
5
+ * Authorization code flow with PKCE S256, `state` and `nonce`; the ID token is
6
+ * verified against the provider's JWKS (signature for the algorithms discovery
7
+ * advertises, `iss`, `aud`, `azp`, `exp`/`iat` with a small clock skew,
8
+ * `nonce`), then `/me` (UserInfo) is fetched and its `sub` checked against the
9
+ * ID token's.
10
+ *
11
+ * Runs in browsers and in Node 20+: Web Crypto + `fetch` only, no runtime
12
+ * dependency, no DOM access at import time. Browser SPAs use
13
+ * {@link beginX1idLogin} / {@link completeX1idLogin} (pending state kept in
14
+ * `sessionStorage`); servers call {@link X1idOidcClient.createAuthorization}
15
+ * and {@link X1idOidcClient.handleCallback} and keep the pending state in their
16
+ * own session.
17
+ *
18
+ * What a sign-in proves: the user controlled the wallet (`sub`) at sign-in. It
19
+ * is NOT proof of legal identity, personhood or KYC. Key accounts on `sub`
20
+ * (the wallet), never on the handle — handles move.
21
+ */
22
+ export declare const X1ID_ISSUER = "https://auth.x1id.io";
23
+ export declare const X1ID_DEFAULT_SCOPE = "openid profile wallet";
24
+ /** ID-token algorithms this client can verify (the provider's ES256 default,
25
+ * EdDSA/Ed25519, and the opt-in RS256 chain). Never `none`, never HS*. */
26
+ export declare const X1ID_SUPPORTED_ID_TOKEN_ALGS: readonly ["ES256", "EdDSA", "RS256"];
27
+ export type X1idIdTokenAlg = (typeof X1ID_SUPPORTED_ID_TOKEN_ALGS)[number];
28
+ /** Default tolerance for `exp` / `iat` against the local clock, in seconds. */
29
+ export declare const X1ID_DEFAULT_CLOCK_SKEW_SECS = 60;
30
+ /** How long a pending login (state/nonce/verifier) stays usable. Matches the
31
+ * provider's interaction lifetime. */
32
+ export declare const X1ID_PENDING_TTL_MS: number;
33
+ /**
34
+ * Every failure is an `X1idAuthError`. `code` is either one of this client's
35
+ * own codes below, or the provider's OAuth `error` value verbatim
36
+ * (`access_denied`, `invalid_grant`, `login_required`, …).
37
+ */
38
+ export type X1idAuthErrorCode = "invalid_config" | "discovery_failed" | "state_mismatch" | "iss_mismatch" | "missing_code" | "pending_expired" | "token_request_failed" | "invalid_token_response" | "invalid_id_token" | "userinfo_failed" | "no_crypto" | (string & {});
39
+ export declare class X1idAuthError extends Error {
40
+ readonly code: X1idAuthErrorCode;
41
+ /** The provider's `error_description`, when it sent one. */
42
+ readonly description: string | undefined;
43
+ constructor(code: X1idAuthErrorCode, message: string, description?: string);
44
+ }
45
+ export interface X1idOidcConfig {
46
+ /** Your client id from the X1ID client registry (`x1c_…`). */
47
+ readonly clientId: string;
48
+ /** Registered redirect URI (exact match). */
49
+ readonly redirectUri: string;
50
+ /** Default `https://auth.x1id.io`. https only (loopback http for local dev). */
51
+ readonly issuer?: string;
52
+ /** Default `openid profile wallet`. `openid` is always added. */
53
+ readonly scope?: string | readonly string[];
54
+ /** Confidential (server-side) clients only. NEVER put a secret in a browser
55
+ * bundle. Omit for public clients (SPA / native: PKCE, no secret). */
56
+ readonly clientSecret?: string;
57
+ /** How a confidential client authenticates at `/token`. Default
58
+ * `client_secret_basic` (the registry default). */
59
+ readonly tokenEndpointAuthMethod?: "client_secret_basic" | "client_secret_post";
60
+ /** Pin the ID-token algorithm (e.g. "RS256" if your client is registered
61
+ * for it). Default: any algorithm the provider advertises that this client
62
+ * supports. */
63
+ readonly idTokenSigningAlg?: X1idIdTokenAlg;
64
+ /** `exp`/`iat` tolerance in seconds. Default 60. */
65
+ readonly clockSkewSecs?: number;
66
+ /** Injected `fetch` (tests, proxies). Default `globalThis.fetch`. */
67
+ readonly fetch?: typeof fetch;
68
+ /** Injected Web Crypto (tests, old runtimes). Default `globalThis.crypto`. */
69
+ readonly crypto?: Crypto;
70
+ /** Injected clock in ms (tests). Default `Date.now`. */
71
+ readonly now?: () => number;
72
+ }
73
+ /** The subset of the provider's discovery document this client uses. */
74
+ export interface X1idDiscovery {
75
+ readonly issuer: string;
76
+ readonly authorization_endpoint: string;
77
+ readonly token_endpoint: string;
78
+ readonly jwks_uri: string;
79
+ readonly userinfo_endpoint?: string;
80
+ readonly end_session_endpoint?: string;
81
+ readonly revocation_endpoint?: string;
82
+ readonly id_token_signing_alg_values_supported?: readonly string[];
83
+ readonly code_challenge_methods_supported?: readonly string[];
84
+ readonly authorization_response_iss_parameter_supported?: boolean;
85
+ readonly [k: string]: unknown;
86
+ }
87
+ /**
88
+ * What must survive the redirect: keep it server-side (session) or in
89
+ * `sessionStorage` (SPA, see {@link beginX1idLogin}). Never put it in the URL.
90
+ */
91
+ export interface X1idPendingLogin {
92
+ readonly state: string;
93
+ readonly nonce: string;
94
+ readonly codeVerifier: string;
95
+ readonly redirectUri: string;
96
+ readonly issuer: string;
97
+ /** ms since epoch. */
98
+ readonly createdAt: number;
99
+ }
100
+ export interface X1idAuthorizationOptions {
101
+ /** e.g. "login" to force a fresh sign-in, "consent" (required by a PUBLIC
102
+ * client that asks for `offline_access`). */
103
+ readonly prompt?: string;
104
+ /** Override the configured scope for this request. */
105
+ readonly scope?: string | readonly string[];
106
+ /** `max_age` in seconds. */
107
+ readonly maxAge?: number;
108
+ /** `ui_locales`. */
109
+ readonly uiLocales?: string;
110
+ /** Any further authorization parameters. The protocol parameters this client
111
+ * owns (state, nonce, PKCE, client_id, redirect_uri, response_type) cannot
112
+ * be overridden. */
113
+ readonly extraParams?: Readonly<Record<string, string>>;
114
+ }
115
+ export interface X1idIdTokenClaims {
116
+ readonly iss: string;
117
+ /** The wallet address (base58). Your account key. */
118
+ readonly sub: string;
119
+ readonly aud: string | readonly string[];
120
+ readonly exp: number;
121
+ readonly iat: number;
122
+ readonly nonce?: string;
123
+ readonly azp?: string;
124
+ readonly auth_time?: number;
125
+ /** `["pop"]`: proof of possession of the wallet key at sign-in. */
126
+ readonly amr?: readonly string[];
127
+ readonly [k: string]: unknown;
128
+ }
129
+ /** `/me` claims, by scope (see services/auth/README.md "Scopes and claims"). */
130
+ export interface X1idUserInfo {
131
+ readonly sub: string;
132
+ /** `profile`: the wallet's primary @handle (no `@`), read live from chain. */
133
+ readonly x1id_handle?: string;
134
+ readonly preferred_username?: string;
135
+ /** `profile`: the handle's https avatar. */
136
+ readonly picture?: string;
137
+ /** `wallet` */
138
+ readonly wallet_address?: string;
139
+ readonly wallet_chain?: string;
140
+ readonly [k: string]: unknown;
141
+ }
142
+ export interface X1idTokens {
143
+ readonly accessToken: string;
144
+ readonly tokenType: string;
145
+ /** ms since epoch, from `expires_in`. */
146
+ readonly expiresAt: number | undefined;
147
+ readonly refreshToken: string | undefined;
148
+ readonly scope: string | undefined;
149
+ readonly idToken: string | undefined;
150
+ readonly idTokenClaims: X1idIdTokenClaims | undefined;
151
+ }
152
+ export interface X1idLoginResult extends X1idTokens {
153
+ /** The wallet address that signed in (the verified ID token's `sub`). */
154
+ readonly sub: string;
155
+ readonly idToken: string;
156
+ readonly idTokenClaims: X1idIdTokenClaims;
157
+ /** Present unless `{ userInfo: false }` was passed. */
158
+ readonly userInfo: X1idUserInfo | undefined;
159
+ }
160
+ export interface X1idVerifyIdTokenOptions {
161
+ readonly issuer: string;
162
+ readonly clientId: string;
163
+ /** The nonce sent in the authorization request. Required for a login; omit
164
+ * only for an ID token from a refresh. */
165
+ readonly nonce?: string;
166
+ /** Allowed `alg` values. */
167
+ readonly algorithms: readonly string[];
168
+ /** Resolve the verification key for a header. */
169
+ readonly getKey: (header: JwtHeader) => Promise<JsonWebKey | null>;
170
+ readonly clockSkewSecs?: number;
171
+ readonly now?: () => number;
172
+ readonly crypto?: Crypto;
173
+ }
174
+ export interface JwtHeader {
175
+ readonly alg: string;
176
+ readonly kid?: string;
177
+ readonly typ?: string;
178
+ readonly [k: string]: unknown;
179
+ }
180
+ /** `bytes` random bytes, base64url (32 bytes → 43 chars, 256 bits). */
181
+ export declare function randomUrlSafe(bytes?: number, crypto?: Crypto): string;
182
+ /** A fresh RFC 7636 code verifier: 32 random bytes → 43 base64url chars. */
183
+ export declare function generateCodeVerifier(crypto?: Crypto): string;
184
+ /** RFC 7636 S256: BASE64URL(SHA-256(ASCII(verifier))). */
185
+ export declare function codeChallengeS256(verifier: string, crypto?: Crypto): Promise<string>;
186
+ /** Decode a JWT without verifying it (for logging / inspection only). */
187
+ export declare function decodeJwtUnverified(jwt: string): {
188
+ header: JwtHeader;
189
+ payload: Record<string, unknown>;
190
+ };
191
+ /**
192
+ * Verify an X1ID ID token: signature (only `algorithms`, never `none`/HS*),
193
+ * `iss` exact match, `aud` contains the client, `azp` (if present, or if
194
+ * several audiences) equals the client, `exp` in the future and `iat` not in
195
+ * the future (± `clockSkewSecs`), `nonce` equal to the one sent, `sub` a
196
+ * non-empty string. Returns the claims; throws `X1idAuthError("invalid_id_token")`.
197
+ */
198
+ export declare function verifyX1idIdToken(jwt: string, o: X1idVerifyIdTokenOptions): Promise<X1idIdTokenClaims>;
199
+ export interface X1idOidcClient {
200
+ readonly issuer: string;
201
+ readonly clientId: string;
202
+ readonly redirectUri: string;
203
+ /** Fetch (once, then cached) and validate the discovery document. */
204
+ discover(): Promise<X1idDiscovery>;
205
+ /** Build the authorization URL + the pending state to keep until the callback. */
206
+ createAuthorization(opts?: X1idAuthorizationOptions): Promise<{
207
+ url: string;
208
+ pending: X1idPendingLogin;
209
+ }>;
210
+ /**
211
+ * Handle the redirect back: check `state`, the RFC 9207 `iss` parameter and
212
+ * any `error`, exchange the code (PKCE), verify the ID token, fetch `/me`.
213
+ * Call it once per pending login (codes are single-use).
214
+ */
215
+ handleCallback(callbackUrl: string | URL, pending: X1idPendingLogin, opts?: {
216
+ userInfo?: boolean;
217
+ }): Promise<X1idLoginResult>;
218
+ /** Exchange a code directly (when you parsed the callback yourself). */
219
+ exchangeCode(code: string, pending: X1idPendingLogin): Promise<X1idTokens & {
220
+ idToken: string;
221
+ idTokenClaims: X1idIdTokenClaims;
222
+ }>;
223
+ /** Verify an ID token from this provider for this client. */
224
+ verifyIdToken(idToken: string, opts?: {
225
+ nonce?: string;
226
+ }): Promise<X1idIdTokenClaims>;
227
+ /** GET `/me` with an access token. Pass `expectedSub` (the ID token's sub) —
228
+ * OIDC Core §5.3.2 requires the two to match. */
229
+ fetchUserInfo(accessToken: string, expectedSub?: string): Promise<X1idUserInfo>;
230
+ /** Refresh (rotating). An ID token in the response is verified; pass the
231
+ * account's `sub` so a different subject is rejected. */
232
+ refresh(refreshToken: string, opts?: {
233
+ expectedSub?: string;
234
+ }): Promise<X1idTokens>;
235
+ /** RFC 7009 revocation of an access or refresh token. */
236
+ revoke(token: string, hint?: "access_token" | "refresh_token"): Promise<void>;
237
+ /** RP-initiated logout URL at auth.x1id.io. */
238
+ logoutUrl(opts?: {
239
+ idTokenHint?: string;
240
+ postLogoutRedirectUri?: string;
241
+ state?: string;
242
+ }): Promise<string>;
243
+ }
244
+ /** Create an RP client. Nothing is fetched until first use. */
245
+ export declare function createX1idOidcClient(config: X1idOidcConfig): X1idOidcClient;
246
+ /** Minimal Storage (sessionStorage, or a test double). */
247
+ export interface X1idStorage {
248
+ getItem(key: string): string | null;
249
+ setItem(key: string, value: string): void;
250
+ removeItem(key: string): void;
251
+ }
252
+ /**
253
+ * Start "Sign in with X1ID" in a browser: stores the pending login in
254
+ * `sessionStorage` (keyed by state, so two tabs don't collide) and navigates
255
+ * to auth.x1id.io. Pass `navigate` to handle the redirect yourself.
256
+ */
257
+ export declare function beginX1idLogin(client: X1idOidcClient, opts?: X1idAuthorizationOptions & {
258
+ storage?: X1idStorage;
259
+ navigate?: (url: string) => void;
260
+ }): Promise<string>;
261
+ /**
262
+ * Finish the login on your redirect page: looks up (and removes — single use)
263
+ * the pending login for the callback's `state`, then runs
264
+ * {@link X1idOidcClient.handleCallback}. By default strips `code`/`state` from
265
+ * the address bar afterwards (`history.replaceState`).
266
+ */
267
+ export declare function completeX1idLogin(client: X1idOidcClient, opts?: {
268
+ url?: string | URL;
269
+ storage?: X1idStorage;
270
+ userInfo?: boolean;
271
+ cleanUrl?: boolean;
272
+ }): Promise<X1idLoginResult>;