@shuttle.technology/authorization 0.0.0-stage → 0.1.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 (56) hide show
  1. package/README.md +708 -2
  2. package/dist/aesGcmSiv.d.ts +14 -0
  3. package/dist/aesGcmSiv.js +160 -0
  4. package/dist/auth.d.ts +68 -0
  5. package/dist/auth.js +215 -0
  6. package/dist/balances.d.ts +31 -0
  7. package/dist/balances.js +44 -0
  8. package/dist/canonicalize.d.ts +19 -0
  9. package/dist/canonicalize.js +107 -0
  10. package/dist/client.d.ts +264 -0
  11. package/dist/client.js +754 -0
  12. package/dist/deviceKey.d.ts +13 -0
  13. package/dist/deviceKey.js +28 -0
  14. package/dist/deviceShare.d.ts +9 -0
  15. package/dist/deviceShare.js +24 -0
  16. package/dist/deviceShareEnvelope.d.ts +13 -0
  17. package/dist/deviceShareEnvelope.js +139 -0
  18. package/dist/linkedChecks.d.ts +17 -0
  19. package/dist/linkedChecks.js +31 -0
  20. package/dist/linkedSendDisplay.d.ts +73 -0
  21. package/dist/linkedSendDisplay.js +84 -0
  22. package/dist/linkedWalletSignals.d.ts +22 -0
  23. package/dist/linkedWalletSignals.js +101 -0
  24. package/dist/linkedWallets.d.ts +373 -0
  25. package/dist/linkedWallets.js +471 -0
  26. package/dist/mediatedOperation.d.ts +27 -0
  27. package/dist/mediatedOperation.js +68 -0
  28. package/dist/modeC.d.ts +131 -0
  29. package/dist/modeC.js +248 -0
  30. package/dist/modeCLinked.d.ts +207 -0
  31. package/dist/modeCLinked.js +270 -0
  32. package/dist/pages.d.ts +22 -0
  33. package/dist/pages.js +45 -0
  34. package/dist/poll.d.ts +15 -0
  35. package/dist/poll.js +76 -0
  36. package/dist/requestGrant.d.ts +169 -0
  37. package/dist/requestGrant.js +243 -0
  38. package/dist/sends.d.ts +89 -0
  39. package/dist/sends.js +127 -0
  40. package/dist/slice4.d.ts +173 -0
  41. package/dist/slice4.js +285 -0
  42. package/dist/streams.d.ts +212 -0
  43. package/dist/streams.js +282 -0
  44. package/dist/trackedWallets.d.ts +53 -0
  45. package/dist/trackedWallets.js +104 -0
  46. package/dist/transferStatus.d.ts +45 -0
  47. package/dist/transferStatus.js +43 -0
  48. package/dist/walletDisplayParts.d.ts +15 -0
  49. package/dist/walletDisplayParts.js +43 -0
  50. package/dist/walletEvents.d.ts +43 -0
  51. package/dist/walletEvents.js +97 -0
  52. package/dist/walletLimits.d.ts +65 -0
  53. package/dist/walletLimits.js +102 -0
  54. package/dist/walletOperations.d.ts +192 -0
  55. package/dist/walletOperations.js +308 -0
  56. package/package.json +64 -4
@@ -0,0 +1,97 @@
1
+ // The wallet event 3.0: one shape for everything a client hears about a
2
+ // tracked wallet.
3
+ //
4
+ // kind "deposit" (value came in), "withdrawal" (value went out),
5
+ // "activity" (anything else)
6
+ // status "completed" (it is in a block), "finalized" (the block is final),
7
+ // "reverted" (the block was replaced)
8
+ // revision "1" for the first status of a subject, "2" for the next
9
+ //
10
+ // Every subject is told at least twice, completed and then finalized, on
11
+ // every network. Where a block is final as soon as it exists the two arrive
12
+ // together; on Ethereum finalized follows completed after thirteen to
13
+ // nineteen minutes. A client that acts on a transfer once it is in a block
14
+ // waits for completed and may ignore what follows.
15
+ //
16
+ // The parser is closed, like every parser of this package: a member that is
17
+ // missing, unknown or owned by another kind refuses the event.
18
+ import { ClientFlowError, integer, opaqueId, record, rfc3339UTC } from "./auth.js";
19
+ /** MaxWalletEventPayloadLength bounds the body text one activity event releases whole. */
20
+ export const MaxWalletEventPayloadLength = 131072;
21
+ const kinds = ["deposit", "withdrawal", "activity"];
22
+ const statuses = ["completed", "finalized", "reverted"];
23
+ const decimalPattern = /^[1-9][0-9]{0,255}$/;
24
+ const revisionPattern = /^[1-9][0-9]{0,19}$/;
25
+ const cursorPattern = /^[1-9][0-9]{0,18}\.[1-9]$/;
26
+ const optional = ["asset", "raw_amount", "counterparty", "activity_type", "invalidation_reason", "payload_json", "payload_omitted_bytes"];
27
+ /** parseWalletEvent parses one wallet event 3.0, closed. */
28
+ export function parseWalletEvent(value) {
29
+ const event = record(value, [
30
+ "contract_version", "event_id", "cursor", "kind", "status", "revision", "subject_id",
31
+ "registration_id", "network_id", "address", "source_reference", "observed_at",
32
+ ], optional);
33
+ const has = (member) => Object.prototype.hasOwnProperty.call(event, member);
34
+ const transfer = event.kind === "deposit" || event.kind === "withdrawal";
35
+ if (event.contract_version !== "3.0" || !text(event.event_id, 512) || !matches(cursorPattern, event.cursor) ||
36
+ typeof event.kind !== "string" || !kinds.includes(event.kind) ||
37
+ typeof event.status !== "string" || !statuses.includes(event.status) ||
38
+ !matches(revisionPattern, event.revision) || (event.status === "completed") !== (event.revision === "1") ||
39
+ !text(event.subject_id, 256) || !opaqueId(event.registration_id) || !text(event.network_id, 256) ||
40
+ !text(event.address, 256) || !text(event.source_reference, 512) || !rfc3339UTC(event.observed_at) ||
41
+ // A transfer names its asset and its amount and nothing an activity owns.
42
+ (transfer && (!text(event.asset, 512) || !matches(decimalPattern, event.raw_amount) || has("activity_type") ||
43
+ has("payload_json") || has("payload_omitted_bytes"))) ||
44
+ (!transfer && (!text(event.activity_type, 128) || (has("asset") && !text(event.asset, 512)) ||
45
+ (has("raw_amount") && !matches(decimalPattern, event.raw_amount)) ||
46
+ (has("payload_json") && has("payload_omitted_bytes")))) ||
47
+ (has("counterparty") && !text(event.counterparty, 512)) ||
48
+ (has("invalidation_reason") && (event.status !== "reverted" || !text(event.invalidation_reason, 128))) ||
49
+ (has("payload_omitted_bytes") && !(integer(event.payload_omitted_bytes) && event.payload_omitted_bytes >= 1))) {
50
+ throw new ClientFlowError("invalid_server_response");
51
+ }
52
+ const parsed = {
53
+ contractVersion: "3.0", eventId: event.event_id, cursor: event.cursor, kind: event.kind, status: event.status,
54
+ revision: event.revision, subjectId: event.subject_id, registrationId: event.registration_id,
55
+ networkId: event.network_id, address: event.address, sourceReference: event.source_reference,
56
+ observedAt: event.observed_at,
57
+ };
58
+ if (has("asset"))
59
+ parsed.asset = event.asset;
60
+ if (has("raw_amount"))
61
+ parsed.rawAmount = event.raw_amount;
62
+ if (has("counterparty"))
63
+ parsed.counterparty = event.counterparty;
64
+ if (has("activity_type"))
65
+ parsed.activityType = event.activity_type;
66
+ if (has("invalidation_reason"))
67
+ parsed.invalidationReason = event.invalidation_reason;
68
+ if (has("payload_json")) {
69
+ parsed.payload = payloadObject(event.payload_json);
70
+ parsed.payloadJson = event.payload_json;
71
+ }
72
+ if (has("payload_omitted_bytes"))
73
+ parsed.payloadOmittedBytes = event.payload_omitted_bytes;
74
+ return Object.freeze(parsed);
75
+ }
76
+ /** Only the JSON text of an object within the bound is a body; anything else refuses the event. */
77
+ function payloadObject(value) {
78
+ if (typeof value !== "string" || value.length < 1 || value.length > MaxWalletEventPayloadLength) {
79
+ throw new ClientFlowError("invalid_server_response");
80
+ }
81
+ let parsed;
82
+ try {
83
+ parsed = JSON.parse(value);
84
+ }
85
+ catch {
86
+ throw new ClientFlowError("invalid_server_response");
87
+ }
88
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
89
+ throw new ClientFlowError("invalid_server_response");
90
+ return Object.freeze(parsed);
91
+ }
92
+ function text(value, maximum) {
93
+ return typeof value === "string" && value.length >= 1 && value.length <= maximum;
94
+ }
95
+ function matches(pattern, value) {
96
+ return typeof value === "string" && pattern.test(value);
97
+ }
@@ -0,0 +1,65 @@
1
+ export type LimitAsset = 'native' | 'usdt' | 'usdc';
2
+ /** At most this many network and asset pairs, and this many recipients. */
3
+ export declare const MaxLimitCeilings = 24;
4
+ export declare const MaxLimitRecipients = 100;
5
+ /** The ceilings of one asset on one network, in that network's minimal units. An absent ceiling bounds nothing. */
6
+ export interface WalletCeiling {
7
+ network: string;
8
+ asset: LimitAsset;
9
+ perTransferRaw?: string;
10
+ perDayRaw?: string;
11
+ }
12
+ /** A wallet's limits now. revision "0" is a wallet whose limits were never set; no recipient means any recipient. */
13
+ export interface WalletLimits {
14
+ requestId: string;
15
+ walletId: string;
16
+ revision: string;
17
+ ceilings: readonly WalletCeiling[];
18
+ recipients: readonly string[];
19
+ }
20
+ /**
21
+ * The whole of a wallet's new limits. Empty ceilings and recipients remove every limit. revision is the
22
+ * revision of the limits they were edited from, as limits() read it: a change made from limits that
23
+ * changed since (in another tab, say) is refused with VERSION_CONFLICT; read them again and redo it.
24
+ */
25
+ export interface WalletLimitsInput {
26
+ ceilings: readonly WalletCeiling[];
27
+ recipients: readonly string[];
28
+ revision: string;
29
+ }
30
+ /** What the owner confirms: the wallet's address and its new limits as they will be kept, recipients in the form the network compares them by. */
31
+ export interface WalletLimitsDisplay {
32
+ kind: 'wallet_limits.set';
33
+ ownerId: string;
34
+ requesterId: string;
35
+ linkedWalletId: string;
36
+ walletAddress: string;
37
+ ceilings: readonly WalletCeiling[];
38
+ recipients: readonly string[];
39
+ expectedRevision: string;
40
+ }
41
+ /**
42
+ * The answers to a send the wallet's limits do not allow. Each is 403 and
43
+ * nothing is sent; the send goes through only after the limits change.
44
+ * - LIMIT_PER_TRANSFER_EXCEEDED: the amount is over the ceiling of one
45
+ * transfer of its asset on its network.
46
+ * - LIMIT_DAILY_EXCEEDED: with what the wallet's sends of that asset on that
47
+ * network moved in the last 24 hours, the send would pass the daily
48
+ * ceiling. It is judged when the send is executed.
49
+ * - RECIPIENT_NOT_ALLOWED: the wallet has a recipient list and the recipient
50
+ * is not in it.
51
+ * The first and the last are answered when the send is created and again
52
+ * when it is executed, against the limits as they are then; a repeated
53
+ * create with the same key answers the send it created. A speed-up is
54
+ * judged by them too and adds nothing to the day, but is refused when the
55
+ * day already holds more than the daily ceiling; a cancel by none.
56
+ */
57
+ export declare const WalletLimitRefusals: readonly ['LIMIT_PER_TRANSFER_EXCEEDED', 'LIMIT_DAILY_EXCEEDED', 'RECIPIENT_NOT_ALLOWED'];
58
+ export type WalletLimitRefusal = (typeof WalletLimitRefusals)[number];
59
+ export declare const isWalletLimitRefusal: (code: unknown) => code is WalletLimitRefusal;
60
+ /** The closed body of POST /v1/operations that asks to replace a linked wallet's limits. */
61
+ export declare function walletLimitsCreate(ownerId: string, linkedWalletId: string, input: WalletLimitsInput): Record<string, unknown>;
62
+ /** The answer of GET /v1/linked-wallets/{id}/limits for walletId. */
63
+ export declare function parseWalletLimits(payload: unknown, walletId: string): WalletLimits;
64
+ /** The display of a wallet_limits.set operation. */
65
+ export declare function parseWalletLimitsDisplay(value: unknown): WalletLimitsDisplay;
@@ -0,0 +1,102 @@
1
+ // The limits of a linked wallet (owner decision of 14 October 2026). The
2
+ // account's session reads them; changing them, removing them included, is the
3
+ // wallet_limits.set operation the owner confirms with a passkey on the
4
+ // provider's page, which says the new limits in words; and every send from
5
+ // the wallet obeys them. Amounts are in each asset's minimal units on its own
6
+ // network: a token's decimals differ between networks (USDT has 6 on Ethereum
7
+ // and 18 on BNB Smart Chain), so a ceiling names its network.
8
+ import { ClientFlowError, canonicalDecimal, integer, opaqueId, record } from './auth.js';
9
+ import { fault, network, uuid } from './linkedChecks.js';
10
+ /** At most this many network and asset pairs, and this many recipients. */
11
+ export const MaxLimitCeilings = 24;
12
+ export const MaxLimitRecipients = 100;
13
+ /**
14
+ * The answers to a send the wallet's limits do not allow. Each is 403 and
15
+ * nothing is sent; the send goes through only after the limits change.
16
+ * - LIMIT_PER_TRANSFER_EXCEEDED: the amount is over the ceiling of one
17
+ * transfer of its asset on its network.
18
+ * - LIMIT_DAILY_EXCEEDED: with what the wallet's sends of that asset on that
19
+ * network moved in the last 24 hours, the send would pass the daily
20
+ * ceiling. It is judged when the send is executed.
21
+ * - RECIPIENT_NOT_ALLOWED: the wallet has a recipient list and the recipient
22
+ * is not in it.
23
+ * The first and the last are answered when the send is created and again
24
+ * when it is executed, against the limits as they are then; a repeated
25
+ * create with the same key answers the send it created. A speed-up is
26
+ * judged by them too and adds nothing to the day, but is refused when the
27
+ * day already holds more than the daily ceiling; a cancel by none.
28
+ */
29
+ export const WalletLimitRefusals = ['LIMIT_PER_TRANSFER_EXCEEDED', 'LIMIT_DAILY_EXCEEDED', 'RECIPIENT_NOT_ALLOWED'];
30
+ export const isWalletLimitRefusal = (code) => WalletLimitRefusals.includes(code);
31
+ /** The closed body of POST /v1/operations that asks to replace a linked wallet's limits. */
32
+ export function walletLimitsCreate(ownerId, linkedWalletId, input) {
33
+ const invalid = () => { throw new ClientFlowError('invalid_operation_create'); };
34
+ const closed = (value, required, optional = []) => { try {
35
+ return record(value, required, optional);
36
+ }
37
+ catch {
38
+ return invalid();
39
+ } };
40
+ const declared = closed(input, ['ceilings', 'recipients', 'revision']);
41
+ if (!opaqueId(ownerId) || !uuid(linkedWalletId) || !Array.isArray(declared.ceilings) || declared.ceilings.length > MaxLimitCeilings || !recipients(declared.recipients) || !revision(declared.revision))
42
+ invalid();
43
+ const pairs = new Set();
44
+ const ceilings = declared.ceilings.map((value) => {
45
+ const c = closed(value, ['network', 'asset'], ['perTransferRaw', 'perDayRaw']);
46
+ const pair = `${c.network} ${c.asset}`;
47
+ if (!network(c.network) || !asset(c.asset) || pairs.has(pair) || (c.perTransferRaw === undefined && c.perDayRaw === undefined) ||
48
+ (c.perTransferRaw !== undefined && !amount(c.perTransferRaw)) || (c.perDayRaw !== undefined && !amount(c.perDayRaw)))
49
+ invalid();
50
+ pairs.add(pair);
51
+ const out = { network: c.network, asset: c.asset };
52
+ if (c.perTransferRaw !== undefined)
53
+ out.per_transfer_raw = c.perTransferRaw;
54
+ if (c.perDayRaw !== undefined)
55
+ out.per_day_raw = c.perDayRaw;
56
+ return out;
57
+ });
58
+ return { kind: 'wallet_limits.set', owner_type: 'account', owner_id: ownerId, linked_wallet_id: linkedWalletId, payload: { ceilings, recipients: [...declared.recipients], expected_revision: declared.revision } };
59
+ }
60
+ /** The answer of GET /v1/linked-wallets/{id}/limits for walletId. */
61
+ export function parseWalletLimits(payload, walletId) {
62
+ const root = record(payload, ['request_id', 'limits']);
63
+ const l = record(root.limits, ['ceilings', 'recipients', 'revision', 'wallet_id']);
64
+ if (!opaqueId(root.request_id) || l.wallet_id !== walletId || !canonicalDecimal(l.revision) || !recipients(l.recipients))
65
+ fault();
66
+ return Object.freeze({ requestId: root.request_id, walletId, revision: l.revision, ceilings: parseCeilings(l.ceilings), recipients: Object.freeze([...l.recipients]) });
67
+ }
68
+ /** The display of a wallet_limits.set operation. */
69
+ export function parseWalletLimitsDisplay(value) {
70
+ const d = record(value, ['kind', 'owner_id', 'requester_id', 'linked_wallet_id', 'wallet_address', 'ceilings', 'recipients', 'expected_revision']);
71
+ if (d.kind !== 'wallet_limits.set' || !opaqueId(d.owner_id) || !opaqueId(d.requester_id) || !uuid(d.linked_wallet_id) || typeof d.wallet_address !== 'string' ||
72
+ d.wallet_address.length < 1 || d.wallet_address.length > 256 || !recipients(d.recipients) || !revision(d.expected_revision))
73
+ fault();
74
+ return Object.freeze({ kind: 'wallet_limits.set', ownerId: d.owner_id, requesterId: d.requester_id, linkedWalletId: d.linked_wallet_id, walletAddress: d.wallet_address,
75
+ ceilings: parseCeilings(d.ceilings), recipients: Object.freeze([...d.recipients]), expectedRevision: d.expected_revision });
76
+ }
77
+ function parseCeilings(value) {
78
+ if (!Array.isArray(value) || value.length > MaxLimitCeilings)
79
+ fault();
80
+ const pairs = new Set();
81
+ return Object.freeze(value.map((item) => {
82
+ const c = record(item, ['network', 'asset'], ['per_transfer_raw', 'per_day_raw', 'decimals']);
83
+ const pair = `${c.network} ${c.asset}`;
84
+ if (!network(c.network) || !asset(c.asset) || pairs.has(pair) || (c.per_transfer_raw === undefined && c.per_day_raw === undefined) ||
85
+ (c.per_transfer_raw !== undefined && !amount(c.per_transfer_raw)) || (c.per_day_raw !== undefined && !amount(c.per_day_raw)) ||
86
+ (c.decimals !== undefined && (!integer(c.decimals) || c.decimals < 0 || c.decimals > 30)))
87
+ fault();
88
+ pairs.add(pair);
89
+ const out = { network: c.network, asset: c.asset };
90
+ if (c.per_transfer_raw !== undefined)
91
+ out.perTransferRaw = c.per_transfer_raw;
92
+ if (c.per_day_raw !== undefined)
93
+ out.perDayRaw = c.per_day_raw;
94
+ return Object.freeze(out);
95
+ }));
96
+ }
97
+ function asset(v) { return v === 'native' || v === 'usdt' || v === 'usdc'; }
98
+ function amount(v) { return canonicalDecimal(v) && v.length <= 78; }
99
+ function revision(v) { return canonicalDecimal(v) && v.length <= 20; }
100
+ function recipients(v) {
101
+ return Array.isArray(v) && v.length <= MaxLimitRecipients && new Set(v).size === v.length && v.every((r) => typeof r === 'string' && /^[\x21-\x7e]{1,128}$/.test(r));
102
+ }
@@ -0,0 +1,192 @@
1
+ import { type NextAction } from "./auth.ts";
2
+ import type { ResultRecipient } from "./slice4.ts";
3
+ import { type DisplayCommon } from "./walletDisplayParts.ts";
4
+ import { type LinkedSendDisplay, type LinkedWalletIdentity } from "./linkedSendDisplay.ts";
5
+ import { type MediatedDisplay, type MediatedPurgedDisplay } from "./mediatedOperation.ts";
6
+ export { LinkedSendAssets, MaxTransferCommentBytes, ReplaceActions, linkedSendAsset, replaceAction, transferComment } from "./linkedSendDisplay.ts";
7
+ export type { LinkedSendAsset, LinkedSendDisplay, LinkedWalletIdentity, ReplaceAction } from "./linkedSendDisplay.ts";
8
+ export type { MediatedDisplay, MediatedLinkedSendDisplay, MediatedPurgedDisplay, MediatedSendDisplay } from "./mediatedOperation.ts";
9
+ export type UserWalletOperationKind = "wallet.create" | "wallet.sign" | "wallet.send" | "wallet.export" | "wallet.recover";
10
+ export type WalletResultKind = "signature" | "transfer_receipt" | "wallet_created";
11
+ export type UserWalletState = "awaiting_confirmation" | "authorized" | "dispatching" | "outcome_unknown" | "succeeded" | "failed" | "denied" | "canceled" | "expired";
12
+ export type UserWalletEffectState = "no_effect" | "possible" | "known";
13
+ /**
14
+ * session_authorized: the account's live session authorized the operation
15
+ * with no passkey. A send from a linked wallet, plain or a replacement, is
16
+ * authorized so (owner decision, 14 October 2026), as is the registration of
17
+ * a linked wallet for tracking; every other wallet operation is confirmed
18
+ * with a passkey (user_confirmed). user_request_signed: a service forwarded
19
+ * the send on the person's signed request (Mode C); its display is a
20
+ * MediatedDisplay, with no result recipient.
21
+ */
22
+ export type UserWalletAuthorizationBasis = "" | "user_confirmed" | "session_authorized" | "user_request_signed";
23
+ type UserWalletCommon = {
24
+ owner_type: "account";
25
+ owner_id: string;
26
+ result_recipient?: ResultRecipient;
27
+ };
28
+ /**
29
+ * UserWalletOperationCreate is the closed request body of source §2.2: the
30
+ * top-level wallet ID is required for every kind except wallet.create, and
31
+ * each payload carries exactly its kind's fields.
32
+ */
33
+ export type UserWalletOperationCreate = (UserWalletCommon & {
34
+ kind: "wallet.create";
35
+ payload: {
36
+ network: string;
37
+ recipient_public_key: string;
38
+ };
39
+ }) | (UserWalletCommon & {
40
+ kind: "wallet.sign";
41
+ wallet_id: string;
42
+ payload: {
43
+ network: string;
44
+ message_base64url: string;
45
+ };
46
+ }) | (UserWalletCommon & {
47
+ kind: "wallet.send";
48
+ wallet_id: string;
49
+ payload: {
50
+ network: string;
51
+ asset: "native";
52
+ recipient: string;
53
+ amount_raw: string;
54
+ max_fee_raw: string;
55
+ };
56
+ }) | (UserWalletCommon & {
57
+ kind: "wallet.export";
58
+ wallet_id: string;
59
+ payload: {
60
+ recipient_public_key: string;
61
+ };
62
+ }) | (UserWalletCommon & {
63
+ kind: "wallet.recover";
64
+ wallet_id: string;
65
+ payload: {
66
+ expected_generation: string;
67
+ recipient_public_key: string;
68
+ };
69
+ });
70
+ /** UserWalletPurgedDisplay is the safe identity left after material retention expires. */
71
+ export type UserWalletPurgedDisplay = DisplayCommon & {
72
+ kind: UserWalletOperationKind;
73
+ materialPurged: true;
74
+ };
75
+ /**
76
+ * UserWalletDisplay is the safe display of the frozen material. A purged
77
+ * record keeps its identity and reports materialPurged instead of inventing
78
+ * material; it never carries signing output or custody material. Narrow with
79
+ * `walletMaterialPurged` before reading any per-kind material field.
80
+ */
81
+ export type UserWalletDisplay = UserWalletPurgedDisplay | (DisplayCommon & {
82
+ kind: "wallet.create";
83
+ network: string;
84
+ recipientPublicKey: string;
85
+ preparedSummary?: string;
86
+ }) | (DisplayCommon & {
87
+ kind: "wallet.sign";
88
+ network: string;
89
+ messageBase64url: string;
90
+ preparedSummary?: string;
91
+ }) | (DisplayCommon & {
92
+ kind: "wallet.send";
93
+ network: string;
94
+ asset: string;
95
+ recipient: string;
96
+ amountRaw: string;
97
+ maxFeeRaw: string;
98
+ preparedSummary?: string;
99
+ }) | LinkedSendDisplay | (DisplayCommon & {
100
+ kind: "wallet.export";
101
+ recipientPublicKey: string;
102
+ preparedSummary?: string;
103
+ }) | (DisplayCommon & {
104
+ kind: "wallet.recover";
105
+ recipientPublicKey: string;
106
+ expectedGeneration: string;
107
+ preparedSummary?: string;
108
+ }) | MediatedDisplay;
109
+ /** walletMaterialPurged separates the purged display from every material display. */
110
+ export declare function walletMaterialPurged(display: UserWalletDisplay): display is UserWalletPurgedDisplay | MediatedPurgedDisplay;
111
+ export interface UserWalletOperation {
112
+ id: string;
113
+ version: string;
114
+ kind: UserWalletOperationKind;
115
+ state: UserWalletState;
116
+ effectState: UserWalletEffectState;
117
+ authorizationBasis: UserWalletAuthorizationBasis;
118
+ ownerType: "account";
119
+ ownerId: string;
120
+ requesterId: string;
121
+ walletId?: string;
122
+ /** Present exactly when the operation names a linked wallet instead of walletId. */
123
+ linkedWallet?: LinkedWalletIdentity;
124
+ requestFingerprint: string;
125
+ operationFingerprint: string;
126
+ display: UserWalletDisplay;
127
+ /** UTC RFC 3339 date-time string (source §2.2), not NumericDate seconds. */
128
+ createdAt: string;
129
+ /** UTC RFC 3339 date-time string (source §2.2), not NumericDate seconds. */
130
+ expiresAt: string;
131
+ confirmationLocation?: string;
132
+ resultKind?: WalletResultKind;
133
+ nextAction: NextAction;
134
+ }
135
+ /** CreatedWallet is the public identity of a wallet the own-wallet system created. */
136
+ export interface CreatedWallet {
137
+ walletId: string;
138
+ keyId: string;
139
+ network: string;
140
+ address: string;
141
+ algorithm: string;
142
+ publicKey: string;
143
+ }
144
+ /**
145
+ * DeviceSharePackage is the device share exactly as the own-wallet system
146
+ * sealed it to the recipient key frozen in the operation. The provider never
147
+ * opens it; only the holder of the matching device private key can. Every
148
+ * binary member is lowercase hexadecimal.
149
+ */
150
+ export interface DeviceSharePackage {
151
+ ciphertext: string;
152
+ nonce: string;
153
+ ephemeralPublicKey: string;
154
+ encryptionAlgorithm: string;
155
+ encryptionContext: string;
156
+ }
157
+ export interface WalletResult {
158
+ requestId: string;
159
+ result: {
160
+ operationId: string;
161
+ kind: WalletResultKind;
162
+ receiptId: string;
163
+ outputBase64url?: string;
164
+ /** Present exactly for a wallet_created result. */
165
+ wallet?: CreatedWallet;
166
+ /** Present exactly for a wallet_created result. */
167
+ deviceShare?: DeviceSharePackage;
168
+ };
169
+ }
170
+ /** MaxWalletMessageBytes is the decoded wallet.sign payload bound of source §2.8. */
171
+ export declare const MaxWalletMessageBytes = 4096;
172
+ /**
173
+ * validateUserWalletCreate rejects every locally detectable fault before any
174
+ * request leaves the client: a foreign owner, a wallet ID present or absent
175
+ * against its kind, a non-compressed recipient key, a noncanonical or
176
+ * out-of-range quantity, a non-native asset, and a sign message outside
177
+ * 1..4096 decoded bytes. It returns the exact value it was given so the
178
+ * caller sends the same closed body it validated.
179
+ */
180
+ export declare function validateUserWalletCreate(value: UserWalletOperationCreate, expectedOwnerId: string): UserWalletOperationCreate;
181
+ export declare function parseUserWalletOperationEnvelope(payload: unknown): {
182
+ requestId: string;
183
+ operation: UserWalletOperation;
184
+ };
185
+ export declare function parseUserWalletOperation(payload: unknown): UserWalletOperation;
186
+ /**
187
+ * parseWalletResult accepts the protected wallet output of source §2.2:
188
+ * output_base64url is present for a signature and forbidden for a transfer
189
+ * receipt. A wallet_created result is its own closed shape: the created
190
+ * wallet and its sealed device share, with no output member.
191
+ */
192
+ export declare function parseWalletResult(payload: unknown, expectedOperationId: string): WalletResult;