@shuttle.technology/authorization 0.0.0-stage → 0.2.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 (93) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/README.md +1124 -2
  3. package/dist/accountLists.d.ts +28 -0
  4. package/dist/accountLists.js +27 -0
  5. package/dist/aesGcmSiv.d.ts +14 -0
  6. package/dist/aesGcmSiv.js +160 -0
  7. package/dist/auth.d.ts +68 -0
  8. package/dist/auth.js +189 -0
  9. package/dist/balances.d.ts +31 -0
  10. package/dist/balances.js +44 -0
  11. package/dist/canonicalize.d.ts +19 -0
  12. package/dist/canonicalize.js +107 -0
  13. package/dist/client.d.ts +152 -0
  14. package/dist/client.js +781 -0
  15. package/dist/clientTypes.d.ts +56 -0
  16. package/dist/clientTypes.js +5 -0
  17. package/dist/configuration.d.ts +48 -0
  18. package/dist/configuration.js +72 -0
  19. package/dist/consentDebit.d.ts +36 -0
  20. package/dist/consentDebit.js +95 -0
  21. package/dist/credentials.d.ts +116 -0
  22. package/dist/credentials.js +315 -0
  23. package/dist/debitPermissionWire.d.ts +90 -0
  24. package/dist/debitPermissionWire.js +118 -0
  25. package/dist/debitPermissions.d.ts +39 -0
  26. package/dist/debitPermissions.js +117 -0
  27. package/dist/deviceKey.d.ts +13 -0
  28. package/dist/deviceKey.js +28 -0
  29. package/dist/deviceRecovery.d.ts +40 -0
  30. package/dist/deviceRecovery.js +143 -0
  31. package/dist/deviceShare.d.ts +9 -0
  32. package/dist/deviceShare.js +24 -0
  33. package/dist/deviceShareEnvelope.d.ts +13 -0
  34. package/dist/deviceShareEnvelope.js +139 -0
  35. package/dist/deviceShares.d.ts +91 -0
  36. package/dist/deviceShares.js +204 -0
  37. package/dist/errors.d.ts +280 -0
  38. package/dist/errors.js +85 -0
  39. package/dist/linkedChecks.d.ts +17 -0
  40. package/dist/linkedChecks.js +31 -0
  41. package/dist/linkedRecovery.d.ts +40 -0
  42. package/dist/linkedRecovery.js +49 -0
  43. package/dist/linkedRegistrations.d.ts +11 -0
  44. package/dist/linkedRegistrations.js +109 -0
  45. package/dist/linkedSendDisplay.d.ts +73 -0
  46. package/dist/linkedSendDisplay.js +84 -0
  47. package/dist/linkedWalletSignals.d.ts +22 -0
  48. package/dist/linkedWalletSignals.js +101 -0
  49. package/dist/linkedWallets.d.ts +401 -0
  50. package/dist/linkedWallets.js +436 -0
  51. package/dist/me.d.ts +27 -0
  52. package/dist/me.js +30 -0
  53. package/dist/mediatedOperation.d.ts +27 -0
  54. package/dist/mediatedOperation.js +68 -0
  55. package/dist/mobile.d.ts +64 -0
  56. package/dist/mobile.js +69 -0
  57. package/dist/modeC.d.ts +131 -0
  58. package/dist/modeC.js +248 -0
  59. package/dist/modeCLinked.d.ts +207 -0
  60. package/dist/modeCLinked.js +270 -0
  61. package/dist/pages.d.ts +22 -0
  62. package/dist/pages.js +45 -0
  63. package/dist/poll.d.ts +15 -0
  64. package/dist/poll.js +76 -0
  65. package/dist/redirects.d.ts +45 -0
  66. package/dist/redirects.js +108 -0
  67. package/dist/requestGrant.d.ts +169 -0
  68. package/dist/requestGrant.js +243 -0
  69. package/dist/sends.d.ts +89 -0
  70. package/dist/sends.js +127 -0
  71. package/dist/serviceGrants.d.ts +52 -0
  72. package/dist/serviceGrants.js +46 -0
  73. package/dist/slice4.d.ts +187 -0
  74. package/dist/slice4.js +299 -0
  75. package/dist/streams.d.ts +212 -0
  76. package/dist/streams.js +282 -0
  77. package/dist/trackedWallets.d.ts +53 -0
  78. package/dist/trackedWallets.js +104 -0
  79. package/dist/transferStatus.d.ts +45 -0
  80. package/dist/transferStatus.js +43 -0
  81. package/dist/walletCreateGrant.d.ts +62 -0
  82. package/dist/walletCreateGrant.js +89 -0
  83. package/dist/walletDisplayParts.d.ts +17 -0
  84. package/dist/walletDisplayParts.js +47 -0
  85. package/dist/walletEvents.d.ts +43 -0
  86. package/dist/walletEvents.js +97 -0
  87. package/dist/walletLimits.d.ts +65 -0
  88. package/dist/walletLimits.js +102 -0
  89. package/dist/walletOperations.d.ts +209 -0
  90. package/dist/walletOperations.js +317 -0
  91. package/dist/webRenewal.d.ts +92 -0
  92. package/dist/webRenewal.js +179 -0
  93. package/package.json +65 -3
package/dist/slice4.js ADDED
@@ -0,0 +1,299 @@
1
+ import { ClientFlowError, canonicalDecimal, deadlineAfter, identityMethods, integer, isNextAction, opaqueId, record, rfc3339UTC, unexpiredRFC3339, } from "./auth.js";
2
+ import { parseWalletLimitsDisplay } from "./walletLimits.js";
3
+ import { parseDebitPermissionDisplay, parseDebitPermissionRevokeDisplay } from "./debitPermissionWire.js";
4
+ import { parseConsentDebitOutcome, parseDebitTerms } from "./consentDebit.js";
5
+ import { parseLinkedEnrollmentDisplay, parseLinkedRequestGrantResult, validateLinkedEnrollmentCreate, } from "./modeCLinked.js";
6
+ /** parseIdentityList accepts the closed answer of GET /v1/identities. */
7
+ export function parseIdentityList(payload) {
8
+ const root = record(payload, ["request_id", "items"]);
9
+ if (!opaqueId(root.request_id) || !Array.isArray(root.items) || root.items.length > 1000)
10
+ throw new ClientFlowError("invalid_server_response");
11
+ const items = root.items.map((value) => {
12
+ const item = record(value, ["identity_id", "method", "created_at"], ["credential_id"]);
13
+ const passkey = item.method === "passkey";
14
+ if (!opaqueId(item.identity_id) || typeof item.method !== "string" || !identityMethods.includes(item.method) || typeof item.created_at !== "string" || Number.isNaN(Date.parse(item.created_at)) ||
15
+ passkey !== (item.credential_id !== undefined) || (passkey && (typeof item.credential_id !== "string" || !/^[A-Za-z0-9_-]{1,1024}$/.test(item.credential_id)))) {
16
+ throw new ClientFlowError("invalid_server_response");
17
+ }
18
+ const identity = { identityId: item.identity_id, method: item.method, createdAt: item.created_at };
19
+ if (passkey)
20
+ identity.credentialId = item.credential_id;
21
+ return identity;
22
+ });
23
+ if (new Set(items.map((item) => item.identityId)).size !== items.length)
24
+ throw new ClientFlowError("invalid_server_response");
25
+ return items;
26
+ }
27
+ export function parseHostedIdentityFlow(payload, now) {
28
+ const root = record(payload, ["request_id", "flow_id", "launch_url", "expires_at"]);
29
+ if (!opaqueId(root.request_id) || !opaqueId(root.flow_id) || !httpsURL(root.launch_url) || !integer(root.expires_at) || root.expires_at <= now / 1_000) {
30
+ throw new ClientFlowError("invalid_server_response");
31
+ }
32
+ return { requestId: root.request_id, flowId: root.flow_id, launchUrl: root.launch_url, expiresAt: root.expires_at };
33
+ }
34
+ export function parsePasskeyBootstrapResult(payload) {
35
+ const root = record(payload, ["request_id", "credential_id", "version", "state"]);
36
+ if (!opaqueId(root.request_id) || !opaqueId(root.credential_id) || !canonicalDecimal(root.version) || root.state !== "active") {
37
+ throw new ClientFlowError("invalid_server_response");
38
+ }
39
+ return { requestId: root.request_id, credentialId: root.credential_id, version: root.version, state: root.state };
40
+ }
41
+ export function parseVerifiedIdentityResult(payload, now) {
42
+ const root = record(payload, ["request_id", "verified_identity_handle", "expires_at"]);
43
+ if (!opaqueId(root.request_id) || !opaqueId(root.verified_identity_handle) || !integer(root.expires_at) || root.expires_at <= now / 1_000) {
44
+ throw new ClientFlowError("invalid_server_response");
45
+ }
46
+ return { requestId: root.request_id, verifiedIdentityHandle: root.verified_identity_handle, expiresAt: root.expires_at };
47
+ }
48
+ export function parseIdentityFlowCallback(value, expectedRedirect) {
49
+ let callback;
50
+ let target;
51
+ try {
52
+ callback = new URL(value);
53
+ target = new URL(expectedRedirect);
54
+ }
55
+ catch {
56
+ throw new ClientFlowError("invalid_callback");
57
+ }
58
+ if (`${callback.origin}${callback.pathname}` !== `${target.origin}${target.pathname}` || callback.hash !== "" || callback.searchParams.size !== 3) {
59
+ throw new ClientFlowError("invalid_callback");
60
+ }
61
+ const code = callback.searchParams.getAll("code");
62
+ const state = callback.searchParams.getAll("state");
63
+ const flowId = callback.searchParams.getAll("flow_id");
64
+ if (code.length !== 1 || state.length !== 1 || flowId.length !== 1 || !opaqueId(code[0]) || !opaqueId(state[0]) || !opaqueId(flowId[0])) {
65
+ throw new ClientFlowError("invalid_callback");
66
+ }
67
+ return { code: code[0], state: state[0], flowId: flowId[0] };
68
+ }
69
+ export function validateLocalOperationCreate(value, expectedOwnerId) {
70
+ const common = record(value, ["kind", "owner_type", "owner_id", "payload"], ["wallet_id", "result_recipient"]);
71
+ if (common.owner_type !== "account" || common.owner_id !== expectedOwnerId || !opaqueId(common.owner_id))
72
+ throw new ClientFlowError("invalid_operation_create");
73
+ if (common.result_recipient !== undefined) {
74
+ const recipient = record(common.result_recipient, ["type", "id"]);
75
+ if ((recipient.type !== "account" && recipient.type !== "service") || !opaqueId(recipient.id))
76
+ throw new ClientFlowError("invalid_operation_create");
77
+ }
78
+ switch (common.kind) {
79
+ case "identity.link": {
80
+ if (common.wallet_id !== undefined)
81
+ throw new ClientFlowError("invalid_operation_create");
82
+ const payload = record(common.payload, ["verified_identity_handle"]);
83
+ if (!opaqueId(payload.verified_identity_handle))
84
+ throw new ClientFlowError("invalid_operation_create");
85
+ break;
86
+ }
87
+ case "identity.unlink": {
88
+ if (common.wallet_id !== undefined)
89
+ throw new ClientFlowError("invalid_operation_create");
90
+ const payload = record(common.payload, ["identity_id"]);
91
+ if (!opaqueId(payload.identity_id))
92
+ throw new ClientFlowError("invalid_operation_create");
93
+ break;
94
+ }
95
+ case "session.revoke": {
96
+ if (common.wallet_id !== undefined)
97
+ throw new ClientFlowError("invalid_operation_create");
98
+ const payload = record(common.payload, ["session_id"]);
99
+ if (!opaqueId(payload.session_id))
100
+ throw new ClientFlowError("invalid_operation_create");
101
+ break;
102
+ }
103
+ case "service_grant.set": {
104
+ if (!opaqueId(common.wallet_id))
105
+ throw new ClientFlowError("invalid_operation_create");
106
+ const payload = record(common.payload, ["service_principal_id", "enabled", "scopes"], ["external_ref"]);
107
+ if (!opaqueId(payload.service_principal_id) || typeof payload.enabled !== "boolean" || !serviceScopes(payload.scopes) || (payload.external_ref !== undefined && !printableReference(payload.external_ref))) {
108
+ throw new ClientFlowError("invalid_operation_create");
109
+ }
110
+ break;
111
+ }
112
+ case "session.authorize_requests":
113
+ validateLinkedEnrollmentCreate(value, expectedOwnerId);
114
+ break;
115
+ default:
116
+ throw new ClientFlowError("invalid_operation_create");
117
+ }
118
+ return value;
119
+ }
120
+ export function parseOperationEnvelope(payload) {
121
+ const root = record(payload, ["request_id", "operation"]);
122
+ if (!opaqueId(root.request_id))
123
+ throw new ClientFlowError("invalid_server_response");
124
+ return { requestId: root.request_id, operation: parseOperation(root.operation) };
125
+ }
126
+ export function parseOperation(payload) {
127
+ const root = record(payload, [
128
+ "id", "version", "kind", "state", "effect_state", "authorization_basis", "owner_type", "owner_id", "requester_id",
129
+ "request_fingerprint", "operation_fingerprint", "display", "created_at", "expires_at", "next_action",
130
+ ], ["wallet_id", "confirmation_location", "result_kind"]);
131
+ if (!opaqueId(root.id) || !canonicalDecimal(root.version) || !localOperationKind(root.kind) || !operationState(root.state) || !effectState(root.effect_state) || (root.authorization_basis !== "" && root.authorization_basis !== "user_confirmed") || root.owner_type !== "account" || !opaqueId(root.owner_id) || !opaqueId(root.requester_id) || (root.wallet_id !== undefined && !opaqueId(root.wallet_id)) || !lowerHexDigest(root.request_fingerprint) || !lowerHexDigest(root.operation_fingerprint) || !rfc3339UTC(root.created_at) || !rfc3339UTC(root.expires_at) || !deadlineAfter(root.created_at, root.expires_at) || (root.confirmation_location !== undefined && !httpsURL(root.confirmation_location)) || (root.result_kind !== undefined && !localResultKind(root.result_kind)) || !isNextAction(root.next_action)) {
132
+ throw new ClientFlowError("invalid_server_response");
133
+ }
134
+ const display = parseDisplay(root.display, root.kind);
135
+ if (display.ownerId !== root.owner_id || display.requesterId !== root.requester_id) {
136
+ throw new ClientFlowError("invalid_server_response");
137
+ }
138
+ if (root.kind === "service_grant.set") {
139
+ if (display.kind !== "service_grant.set" || root.wallet_id === undefined || display.walletId !== root.wallet_id)
140
+ throw new ClientFlowError("invalid_server_response");
141
+ }
142
+ else if (root.wallet_id !== undefined) {
143
+ throw new ClientFlowError("invalid_server_response");
144
+ }
145
+ const operation = {
146
+ id: root.id,
147
+ version: root.version,
148
+ kind: root.kind,
149
+ state: root.state,
150
+ effectState: root.effect_state,
151
+ authorizationBasis: root.authorization_basis,
152
+ ownerType: root.owner_type,
153
+ ownerId: root.owner_id,
154
+ requesterId: root.requester_id,
155
+ requestFingerprint: root.request_fingerprint,
156
+ operationFingerprint: root.operation_fingerprint,
157
+ display,
158
+ createdAt: root.created_at,
159
+ expiresAt: root.expires_at,
160
+ nextAction: root.next_action,
161
+ };
162
+ if (root.wallet_id !== undefined)
163
+ operation.walletId = root.wallet_id;
164
+ if (root.confirmation_location !== undefined)
165
+ operation.confirmationLocation = root.confirmation_location;
166
+ if (root.result_kind !== undefined)
167
+ operation.resultKind = root.result_kind;
168
+ return operation;
169
+ }
170
+ export function parseConfirmationChallenge(payload, now) {
171
+ const root = record(payload, ["request_id", "challenge_id", "public_key", "confirmation_location", "expires_at"]);
172
+ const publicKey = record(root.public_key, ["challenge", "rp_id", "timeout_ms", "allow_credentials", "user_verification"]);
173
+ if (!opaqueId(root.request_id) || !opaqueId(root.challenge_id) || !base64url(publicKey.challenge) || typeof publicKey.rp_id !== "string" || publicKey.rp_id.length === 0 || !integer(publicKey.timeout_ms) || publicKey.timeout_ms < 1 || publicKey.timeout_ms > 120_000 || !Array.isArray(publicKey.allow_credentials) || publicKey.allow_credentials.length !== 1 || publicKey.user_verification !== "required" || !httpsURL(root.confirmation_location) || !unexpiredRFC3339(root.expires_at, now)) {
174
+ throw new ClientFlowError("invalid_server_response");
175
+ }
176
+ const credential = record(publicKey.allow_credentials[0], ["type", "id"]);
177
+ if (credential.type !== "public-key" || !base64url(credential.id))
178
+ throw new ClientFlowError("invalid_server_response");
179
+ return {
180
+ requestId: root.request_id,
181
+ challengeId: root.challenge_id,
182
+ publicKey: { challenge: publicKey.challenge, rpId: publicKey.rp_id, timeoutMs: publicKey.timeout_ms, allowCredentials: [{ type: "public-key", id: credential.id }], userVerification: "required" },
183
+ confirmationLocation: root.confirmation_location,
184
+ expiresAt: root.expires_at,
185
+ };
186
+ }
187
+ export function parseOperationConfirmationCallback(value, expectedRedirect) {
188
+ let callback;
189
+ let target;
190
+ try {
191
+ callback = new URL(value);
192
+ target = new URL(expectedRedirect);
193
+ }
194
+ catch {
195
+ throw new ClientFlowError("invalid_callback");
196
+ }
197
+ if (`${callback.origin}${callback.pathname}` !== `${target.origin}${target.pathname}` || callback.hash !== "" || callback.searchParams.size !== 2)
198
+ throw new ClientFlowError("invalid_callback");
199
+ const state = callback.searchParams.getAll("state");
200
+ const operationId = callback.searchParams.getAll("operation_id");
201
+ if (state.length !== 1 || operationId.length !== 1 || !opaqueId(state[0]) || !opaqueId(operationId[0]))
202
+ throw new ClientFlowError("invalid_callback");
203
+ return { state: state[0], operationId: operationId[0] };
204
+ }
205
+ export function parseLocalOperationResult(payload) {
206
+ const root = record(payload, ["request_id", "result"]);
207
+ const result = record(root.result, ["kind", "target_id", "new_version", "state"], ["grant", "debit"]);
208
+ if (!opaqueId(root.request_id) || !localResultKind(result.kind) || !opaqueId(result.target_id) || !canonicalDecimal(result.new_version) || (result.state !== "active" && result.state !== "revoked") ||
209
+ (result.grant !== undefined) !== (result.kind === "request_grant") || (result.debit !== undefined && result.kind !== "service_grant")) {
210
+ throw new ClientFlowError("invalid_server_response");
211
+ }
212
+ const parsed = { kind: result.kind, targetId: result.target_id, newVersion: result.new_version, state: result.state };
213
+ if (result.grant !== undefined) {
214
+ parsed.grant = parseLinkedRequestGrantResult(result.grant);
215
+ if (parsed.grant.requestGrantId !== result.target_id)
216
+ throw new ClientFlowError("invalid_server_response");
217
+ }
218
+ if (result.debit !== undefined)
219
+ parsed.debit = parseConsentDebitOutcome(result.debit);
220
+ return { requestId: root.request_id, result: parsed };
221
+ }
222
+ function parseDisplay(value, kind) {
223
+ if (kind === "identity.link") {
224
+ const display = record(value, ["kind", "owner_id", "requester_id", "method"]);
225
+ if (display.kind !== kind || !opaqueId(display.owner_id) || !opaqueId(display.requester_id) || typeof display.method !== "string" || !identityMethods.includes(display.method))
226
+ throw new ClientFlowError("invalid_server_response");
227
+ return { kind, ownerId: display.owner_id, requesterId: display.requester_id, method: display.method };
228
+ }
229
+ if (kind === "identity.unlink") {
230
+ const display = record(value, ["kind", "owner_id", "requester_id", "identity_id"]);
231
+ if (display.kind !== kind || !opaqueId(display.owner_id) || !opaqueId(display.requester_id) || !opaqueId(display.identity_id))
232
+ throw new ClientFlowError("invalid_server_response");
233
+ return { kind, ownerId: display.owner_id, requesterId: display.requester_id, identityId: display.identity_id };
234
+ }
235
+ if (kind === "wallet_limits.set")
236
+ return parseWalletLimitsDisplay(value);
237
+ if (kind === "session.authorize_requests")
238
+ return parseLinkedEnrollmentDisplay(value);
239
+ if (kind === "debit_permission.create")
240
+ return parseDebitPermissionDisplay(value);
241
+ if (kind === "debit_permission.revoke")
242
+ return parseDebitPermissionRevokeDisplay(value);
243
+ if (kind === "session.revoke") {
244
+ const display = record(value, ["kind", "owner_id", "requester_id", "session_id"]);
245
+ if (display.kind !== kind || !opaqueId(display.owner_id) || !opaqueId(display.requester_id) || !opaqueId(display.session_id))
246
+ throw new ClientFlowError("invalid_server_response");
247
+ return { kind, ownerId: display.owner_id, requesterId: display.requester_id, sessionId: display.session_id };
248
+ }
249
+ const display = record(value, ["kind", "owner_id", "requester_id", "wallet_id", "service_principal_id", "enabled", "scopes"], ["external_ref", "debit"]);
250
+ if (display.kind !== kind || !opaqueId(display.owner_id) || !opaqueId(display.requester_id) || !opaqueId(display.wallet_id) || !opaqueId(display.service_principal_id) || typeof display.enabled !== "boolean" || !serviceScopes(display.scopes) || (display.external_ref !== undefined && !printableReference(display.external_ref)))
251
+ throw new ClientFlowError("invalid_server_response");
252
+ const result = { kind, ownerId: display.owner_id, requesterId: display.requester_id, walletId: display.wallet_id, servicePrincipalId: display.service_principal_id, enabled: display.enabled, scopes: display.scopes };
253
+ if (display.external_ref !== undefined)
254
+ result.externalRef = display.external_ref;
255
+ if (display.debit !== undefined)
256
+ result.debit = parseDebitTerms(display.debit);
257
+ return result;
258
+ }
259
+ function localOperationKind(value) {
260
+ return value === "identity.link" || value === "identity.unlink" || value === "session.revoke" || value === "service_grant.set" || value === "wallet_limits.set" || value === "session.authorize_requests" ||
261
+ value === "debit_permission.create" || value === "debit_permission.revoke";
262
+ }
263
+ function localResultKind(value) {
264
+ return value === "identity" || value === "session" || value === "service_grant" || value === "wallet_limits" || value === "request_grant" || value === "debit_permission";
265
+ }
266
+ function operationState(value) {
267
+ return value === "awaiting_confirmation" || value === "authorized" || value === "pending_target_fence" || value === "succeeded" || value === "failed" ||
268
+ value === "denied" || value === "canceled" || value === "expired";
269
+ }
270
+ function effectState(value) {
271
+ return value === "no_effect" || value === "known";
272
+ }
273
+ function lowerHexDigest(value) {
274
+ return typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
275
+ }
276
+ function base64url(value) {
277
+ return typeof value === "string" && /^[A-Za-z0-9_-]+$/.test(value);
278
+ }
279
+ /** serviceScopes accepts the read scopes of a service grant: at most the three, each once (none: a withdrawal). */
280
+ export function serviceScopes(value) {
281
+ if (!Array.isArray(value) || value.length > 3 || new Set(value).size !== value.length)
282
+ return false;
283
+ return value.every((scope) => scope === "wallet:read" || scope === "operation:read" || scope === "streams:read");
284
+ }
285
+ /** printableReference accepts a grant's external_ref: 1 to 128 printable ASCII characters. */
286
+ export function printableReference(value) {
287
+ return typeof value === "string" && /^[\x20-\x7E]{1,128}$/.test(value);
288
+ }
289
+ function httpsURL(value) {
290
+ if (typeof value !== "string")
291
+ return false;
292
+ try {
293
+ const parsed = new URL(value);
294
+ return parsed.protocol === "https:" && parsed.username === "" && parsed.password === "";
295
+ }
296
+ catch {
297
+ return false;
298
+ }
299
+ }
@@ -0,0 +1,212 @@
1
+ import { type PollResult } from "./poll.ts";
2
+ import { type WalletEvent } from "./walletEvents.ts";
3
+ export { pollAuthoritative } from "./poll.ts";
4
+ export type { PollDisposition, PollOptions, PollResult } from "./poll.ts";
5
+ export { AuthorizationError, ClientFlowError } from "./auth.ts";
6
+ export type { NextAction } from "./auth.ts";
7
+ export { MaxWalletEventPayloadLength, parseWalletEvent } from "./walletEvents.ts";
8
+ export type { WalletEvent, WalletEventKind, WalletEventStatus } from "./walletEvents.ts";
9
+ export { TrackedWallets, TrackedWalletsPath, parseTrackedWalletPage, trackedWalletsPath } from "./trackedWallets.ts";
10
+ export type { TrackedWallet, TrackedWalletKind, TrackedWalletPage, TrackedWalletPageOptions, TrackedWalletsGet } from "./trackedWallets.ts";
11
+ /** DefaultStreamsPageLimit is the served page size when no limit is supplied (source §2.8). */
12
+ export declare const DefaultStreamsPageLimit = 50;
13
+ /** MaxStreamsPageLimit is the largest page the deposit route accepts (source §2.8). */
14
+ export declare const MaxStreamsPageLimit = 100;
15
+ /** MaxStreamsCursorLength bounds one opaque scope-bound wrapper. */
16
+ export declare const MaxStreamsCursorLength = 4096;
17
+ /** MaxStreamsAssets bounds one registration's validated asset list. */
18
+ export declare const MaxStreamsAssets = 32;
19
+ /** MaxStreamsActivityTypes bounds the activity kinds one registration may ask for. */
20
+ export declare const MaxStreamsActivityTypes = 16;
21
+ /** MaxStreamsAddressLength bounds one released address. */
22
+ export declare const MaxStreamsAddressLength = 256;
23
+ /**
24
+ * StreamsReadScope selects which credential class the path belongs to. The
25
+ * account routes accept only the account access JWT and the service routes only
26
+ * a tenant-access service credential; neither body nor header can select
27
+ * another tenant (source §2.2).
28
+ */
29
+ export type StreamsReadScope = "account" | "service";
30
+ /** StreamsRegistrationStatus is the closed source registration status set. */
31
+ export type StreamsRegistrationStatus = "pending" | "active";
32
+ /** StreamsRegistration is one authorized registration exactly as the source owns it. */
33
+ export interface StreamsRegistration {
34
+ readonly registrationId: string;
35
+ readonly walletId: string;
36
+ /** Streams-owned identifier, never inferred from and never equal to an Authorization identifier. */
37
+ readonly sourceRegistrationId: string;
38
+ readonly network: string;
39
+ readonly address: string;
40
+ readonly assets: readonly string[];
41
+ readonly status: StreamsRegistrationStatus;
42
+ readonly effectiveFrom: string;
43
+ readonly revision: number;
44
+ readonly sourceVersion: string;
45
+ }
46
+ /**
47
+ * StreamsRegistrationList is the closed registrations response. The unique
48
+ * wallet and network binding bounds the permitted set, so the route releases it
49
+ * in one page and issues no cursor.
50
+ */
51
+ export interface StreamsRegistrationList {
52
+ readonly items: readonly StreamsRegistration[];
53
+ readonly hasMore: boolean;
54
+ }
55
+ /**
56
+ * StreamsWindow is the authorized visible boundary, as two opaque wrappers.
57
+ * latestCursor is also a place to read on from: what came after the end of
58
+ * the stream as the read saw it. earliestCursor is never accepted as a cursor.
59
+ */
60
+ export interface StreamsWindow {
61
+ readonly earliestCursor: string;
62
+ readonly latestCursor: string;
63
+ }
64
+ /**
65
+ * WalletEventPage is one page of a wallet's retained events as wallet events
66
+ * 3.0: deposits, withdrawals and other activity in one shape. One stored
67
+ * event gives no event, one or two, so a page holds at most twice the limit
68
+ * asked for; a page filtered by kind may hold fewer, or none, and still go
69
+ * on. `nextCursor` is present exactly when `hasMore` is true.
70
+ */
71
+ export interface WalletEventPage {
72
+ readonly events: readonly WalletEvent[];
73
+ readonly nextCursor?: string;
74
+ readonly hasMore: boolean;
75
+ readonly window: StreamsWindow;
76
+ }
77
+ /**
78
+ * resumeCursor is the cursor to pass to the next read of the same wallet so
79
+ * that it returns only what this page did not: the next page while there is
80
+ * one, and at the end of the stream what comes after it. Keep it between
81
+ * rounds instead of reading a history again from its start. It ends with the
82
+ * session, like every cursor; a refused one means the history is read anew.
83
+ */
84
+ export declare function resumeCursor(page: WalletEventPage): string;
85
+ /** StreamsListOptions is the closed registrations query: a limit only. */
86
+ export interface StreamsListOptions {
87
+ readonly limit?: number;
88
+ readonly signal?: AbortSignal;
89
+ }
90
+ /** StreamsRegistrationReadOptions adds the caller-owned replay key to a list read. */
91
+ export interface StreamsRegistrationReadOptions extends StreamsListOptions {
92
+ /** Stable across retries of this exact route and query; never generated by the SDK. */
93
+ readonly idempotencyKey: string;
94
+ }
95
+ /**
96
+ * StreamsPageOptions is the closed events query. A wrapper carries its own
97
+ * original limit, so omitting `limit` while resuming keeps it and supplying a
98
+ * different one is CURSOR_INVALID at the server (source §2.6).
99
+ *
100
+ * `eventTypes` is the kinds of wallet event the caller wants: "deposit",
101
+ * "withdrawal" and "activity" in any combination, or "activity:<type>" for
102
+ * one type of activity. Left out, every kind. The filter is applied to the
103
+ * page that was read and does not change its cursor.
104
+ */
105
+ export interface StreamsPageOptions {
106
+ readonly cursor?: string;
107
+ readonly limit?: number;
108
+ readonly eventTypes?: readonly string[];
109
+ readonly signal?: AbortSignal;
110
+ }
111
+ /** MaxWalletEventTypes is how many selectors a filter may name. */
112
+ export declare const MaxWalletEventTypes = 64;
113
+ /**
114
+ * appendEventTypes writes the filter by kind into a query. Each selector is
115
+ * named once; what the server makes of a combination is the server's to say.
116
+ */
117
+ export declare function appendEventTypes(query: URLSearchParams, value: unknown): void;
118
+ /** StreamsEventsReadOptions adds the caller-owned replay key to one events read. */
119
+ export interface StreamsEventsReadOptions extends StreamsPageOptions {
120
+ /** Stable across retries of this exact route and query; never generated by the SDK. */
121
+ readonly idempotencyKey: string;
122
+ }
123
+ /**
124
+ * StreamsResync is the typed expired-boundary outcome: the authorized visible
125
+ * boundary the caller must restart from.
126
+ *
127
+ * Its two values are the window's wrappers. The server binds every released
128
+ * wrapper to the boundary it was issued for. A caller that wants the retained
129
+ * history restarts with a fresh read of this wallet with no cursor and pages
130
+ * forward again; one that wants only what comes from now on reads from
131
+ * latestCursor. earliestCursor is never accepted as a cursor. This module
132
+ * never retries the failed read and never derives a position of its own.
133
+ */
134
+ export interface StreamsResync {
135
+ readonly requestId: string;
136
+ readonly window: StreamsWindow;
137
+ }
138
+ /**
139
+ * streamsRegistrationsPath builds the exact registrations path. The route
140
+ * declares no cursor at all, so this builder accepts none: a cursor member is
141
+ * refused here rather than sent and answered INVALID_REQUEST.
142
+ */
143
+ export declare function streamsRegistrationsPath(scope: StreamsReadScope, walletId: string, options?: StreamsListOptions): string;
144
+ /** streamsEventsPath builds the exact wallet events path with its closed query. */
145
+ export declare function streamsEventsPath(scope: StreamsReadScope, walletId: string, options?: StreamsPageOptions): string;
146
+ /** parseStreamsRegistrationList parses the closed registrations response. */
147
+ export declare function parseStreamsRegistrationList(payload: unknown): StreamsRegistrationList;
148
+ /** parseWalletEventPage parses the closed page of wallet events 3.0. */
149
+ export declare function parseWalletEventPage(payload: unknown): WalletEventPage;
150
+ /** parseStreamsWindow parses the required two-wrapper authorized window. */
151
+ export declare function parseStreamsWindow(payload: unknown): StreamsWindow;
152
+ /**
153
+ * streamsResync reports the authorized window of an expired boundary and
154
+ * nothing else. `parseAuthorizationError` already refuses a RESYNC_REQUIRED
155
+ * without its window and a window on any other code, so this returns undefined
156
+ * for every other failure instead of guessing a recovery position.
157
+ */
158
+ export declare function streamsResync(error: unknown): StreamsResync | undefined;
159
+ /**
160
+ * StreamsAuthorizedGet performs one authorized GET and returns its parsed JSON
161
+ * body. Implementations must send `idempotencyKey` as the Idempotency-Key
162
+ * header; retries of the same request must pass through the exact same key.
163
+ */
164
+ export type StreamsAuthorizedGet = (path: string, signal: AbortSignal | undefined, idempotencyKey: string) => Promise<unknown>;
165
+ /** StreamsReadsDependencies is the closed construction input of `StreamsReads`. */
166
+ export interface StreamsReadsDependencies {
167
+ readonly scope: StreamsReadScope;
168
+ readonly get: StreamsAuthorizedGet;
169
+ }
170
+ /**
171
+ * StreamsReads is the two authorized reads bound to one caller's own authorized
172
+ * GET. It owns no credential: the account caller receives one already bound to
173
+ * its session from `AuthorizationClient.streams()`, and a service caller
174
+ * supplies a GET that carries its own tenant-access service credential. Each
175
+ * read requires the caller's stable key; reuse it only for retries of the same
176
+ * route and query because the server conflicts when a key is bound to changed
177
+ * request material.
178
+ */
179
+ export declare class StreamsReads {
180
+ #private;
181
+ readonly scope: StreamsReadScope;
182
+ constructor(dependencies: StreamsReadsDependencies);
183
+ /** registrations reads the wallet's authorized registrations in one page. */
184
+ registrations(walletId: string, options: StreamsRegistrationReadOptions): Promise<StreamsRegistrationList>;
185
+ /**
186
+ * events reads one page of the wallet's retained events as wallet events
187
+ * 3.0: deposits, withdrawals and other activity in one shape with a status,
188
+ * those of the kinds `eventTypes` names. A denial is thrown exactly as the
189
+ * server classified it: an expired boundary raises the RESYNC_REQUIRED
190
+ * AuthorizationError carrying its authorized window, which this method
191
+ * never catches, retries or converts into an empty success.
192
+ */
193
+ events(walletId: string, options: StreamsEventsReadOptions): Promise<WalletEventPage>;
194
+ }
195
+ /** StreamsPollOptions is the closed input of `pollStreamsEvents`. */
196
+ export interface StreamsPollOptions {
197
+ readonly read: (signal: AbortSignal) => Promise<WalletEventPage>;
198
+ readonly signal?: AbortSignal;
199
+ readonly intervalMs?: number;
200
+ readonly timeoutMs?: number;
201
+ readonly now?: () => number;
202
+ readonly sleep?: (milliseconds: number, signal: AbortSignal) => Promise<void>;
203
+ }
204
+ /**
205
+ * pollStreamsEvents follows a page of wallet events until the server itself reports no
206
+ * further retained work. It adds no bound of its own: it delegates to the one
207
+ * `pollAuthoritative` helper, so the source §2.8 bounds — at least two seconds
208
+ * between polls and at most sixty seconds in total — are enforced in a single
209
+ * place, and cancellation or timeout returns the last observed page with its
210
+ * local disposition rather than a claimed server outcome.
211
+ */
212
+ export declare function pollStreamsEvents(options: StreamsPollOptions): Promise<PollResult<WalletEventPage>>;