@seams/wallet 0.18.0 → 0.19.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 (100) hide show
  1. package/dist/.build-inputs.sha256 +1 -1
  2. package/dist/esm/SeamsWeb/index.js +1 -1
  3. package/dist/esm/SeamsWeb/walletIframe/client/inboundMessages.js +1 -1
  4. package/dist/esm/SeamsWeb/walletIframe/client/router.js +10 -4
  5. package/dist/esm/SeamsWeb/walletIframe/coordinator.js +23 -1
  6. package/dist/esm/SeamsWeb/walletIframe/host/ui/auth-menu/AuthMenuSurface.js +33 -6
  7. package/dist/esm/SeamsWeb/walletIframe/host/ui/auth-menu/icons.js +37 -1
  8. package/dist/esm/SeamsWeb/walletIframe/host/ui/auth-menu/presentation.js +1 -0
  9. package/dist/esm/core/browser/walletIframe/events.js +6 -0
  10. package/dist/esm/core/signingEngine/uiConfirm/ui/appearance.js +27 -0
  11. package/dist/esm/core/signingEngine/uiConfirm/ui/export-private-key-reveal.js +155 -0
  12. package/dist/esm/core/signingEngine/uiConfirm/ui/export-viewer-host.js +209 -0
  13. package/dist/esm/core/signingEngine/uiConfirm/ui/preact/ExportPrivateKeySurface.js +319 -0
  14. package/dist/esm/core/signingEngine/uiConfirm/ui/preact/mountExportPrivateKeySurface.js +92 -0
  15. package/dist/esm/core/signingEngine/uiConfirm/ui/surface-measurement-binding.js +12 -0
  16. package/dist/esm/core/ui/messages.js +4 -0
  17. package/dist/esm/index.js +1 -1
  18. package/dist/esm/react/components/AccountMenuButton/AccountMenuButtonView.js +1 -1
  19. package/dist/esm/react/components/AccountMenuButton/ExportKeysSection.css +20 -0
  20. package/dist/esm/react/components/AccountMenuButton/LinkedDevicesModal.css +9 -3
  21. package/dist/esm/react/components/AccountMenuButton/UserAccountButton.css +1 -0
  22. package/dist/esm/react/components/AccountMenuButton/Web3AuthProfileButton.css +15 -0
  23. package/dist/esm/react/styles/styles.css +36 -0
  24. package/dist/esm/sdk/{ConfirmationDrawer-mu3iThxX.js → ConfirmationDrawer-DCw0m-Iv.js} +1 -1
  25. package/dist/{public/sdk/adapters-u7LVXthY.js → esm/sdk/adapters-BNmcyf9K.js} +1 -1
  26. package/dist/esm/sdk/appearance-token-vars-DxBm_cKA.js +2 -0
  27. package/dist/{public/sdk/export-viewer-host-ivf9LlBo.js → esm/sdk/export-viewer-host-DsdzagKK.js} +1 -1
  28. package/dist/esm/sdk/{exportKeypairOperation-Gw7L5Htj.js → exportKeypairOperation-BwW_E4Lt.js} +1 -1
  29. package/dist/esm/sdk/{host-B-2QXolt.js → host-DMR4KDy9.js} +1 -1
  30. package/dist/esm/sdk/{localOnly-BKpUHtHa.js → localOnly-DO191vDh.js} +1 -1
  31. package/dist/esm/sdk/{mountExportPrivateKeySurface-C8pUK6PQ.js → mountExportPrivateKeySurface-DQzFzhNu.js} +1 -1
  32. package/dist/esm/sdk/{mountRecoveryCodeBackupSurface-DUudF89t.js → mountRecoveryCodeBackupSurface-B1D0ovqx.js} +1 -1
  33. package/dist/esm/sdk/{pendingWalletRecoveryCodeBackup-7tBjuSe7.js → pendingWalletRecoveryCodeBackup-DOeIn_Qj.js} +1 -1
  34. package/dist/esm/sdk/{registration-CWpOVwhj.js → registration-DknFwoqn.js} +1 -1
  35. package/dist/esm/sdk/{registration-D2OEgY7O.js → registration-sQndIWRF.js} +1 -1
  36. package/dist/esm/sdk/router_ab_ed25519_yao_client_bg.wasm +0 -0
  37. package/dist/esm/sdk/runtime-auth-BxG-J-BB.js +1 -0
  38. package/dist/esm/sdk/{runtime-device-link-vhRhB-wS.js → runtime-device-link-Dn_5hPCq.js} +1 -1
  39. package/dist/{public/sdk/runtime-ecdsa-tempo-BXWgFVBa.js → esm/sdk/runtime-ecdsa-tempo-lTFTb9Rh.js} +1 -1
  40. package/dist/esm/sdk/{runtime-email-otp-BlAaSKtk.js → runtime-email-otp-CPqTCH8Q.js} +1 -1
  41. package/dist/esm/sdk/{runtime-export-B4FuHhcH.js → runtime-export-Brz53_oi.js} +1 -1
  42. package/dist/esm/sdk/{runtime-near-BnWOpEpA.js → runtime-near-Da_xFUXx.js} +1 -1
  43. package/dist/esm/sdk/{runtime-preferences-COm-LTiu.js → runtime-preferences-riUZGaTs.js} +1 -1
  44. package/dist/esm/sdk/{runtime-recovery-BJTo5Idi.js → runtime-recovery-CTj4nDAM.js} +1 -1
  45. package/dist/esm/sdk/{runtime-recovery-codes-CEOjdUHV.js → runtime-recovery-codes-D8T9LQ7-.js} +1 -1
  46. package/dist/esm/sdk/{shared-BKPGtAps.js → shared-hx7KVyeq.js} +1 -1
  47. package/dist/esm/sdk/tx-confirm-ui.js +4 -0
  48. package/dist/esm/sdk/wallet-iframe-host-ecdsa.js +1 -1
  49. package/dist/esm/sdk/wallet-iframe-host-full.js +1 -1
  50. package/dist/esm/sdk/wallet-iframe-host-near.js +1 -1
  51. package/dist/esm/sdk/wallet-iframe-host-runtime.js +1 -1
  52. package/dist/esm/sdk/wallet-ui.css +1 -1
  53. package/dist/esm/wasm/router_ab_ed25519_yao_client/pkg/router_ab_ed25519_yao_client_bg.wasm +0 -0
  54. package/dist/public/headers.manifest.json +1 -1
  55. package/dist/public/sdk/{ConfirmationDrawer-mu3iThxX.js → ConfirmationDrawer-DCw0m-Iv.js} +1 -1
  56. package/dist/{esm/sdk/adapters-u7LVXthY.js → public/sdk/adapters-BNmcyf9K.js} +1 -1
  57. package/dist/public/sdk/appearance-token-vars-DxBm_cKA.js +2 -0
  58. package/dist/{esm/sdk/export-viewer-host-ivf9LlBo.js → public/sdk/export-viewer-host-DsdzagKK.js} +1 -1
  59. package/dist/public/sdk/{exportKeypairOperation-Gw7L5Htj.js → exportKeypairOperation-BwW_E4Lt.js} +1 -1
  60. package/dist/public/sdk/{host-B-2QXolt.js → host-DMR4KDy9.js} +1 -1
  61. package/dist/public/sdk/{localOnly-BKpUHtHa.js → localOnly-DO191vDh.js} +1 -1
  62. package/dist/public/sdk/{mountExportPrivateKeySurface-C8pUK6PQ.js → mountExportPrivateKeySurface-DQzFzhNu.js} +1 -1
  63. package/dist/public/sdk/{mountRecoveryCodeBackupSurface-DUudF89t.js → mountRecoveryCodeBackupSurface-B1D0ovqx.js} +1 -1
  64. package/dist/public/sdk/{pendingWalletRecoveryCodeBackup-7tBjuSe7.js → pendingWalletRecoveryCodeBackup-DOeIn_Qj.js} +1 -1
  65. package/dist/public/sdk/{registration-CWpOVwhj.js → registration-DknFwoqn.js} +1 -1
  66. package/dist/public/sdk/{registration-D2OEgY7O.js → registration-sQndIWRF.js} +1 -1
  67. package/dist/public/sdk/router_ab_ed25519_yao_client_bg.wasm +0 -0
  68. package/dist/public/sdk/runtime-auth-BxG-J-BB.js +1 -0
  69. package/dist/public/sdk/{runtime-device-link-vhRhB-wS.js → runtime-device-link-Dn_5hPCq.js} +1 -1
  70. package/dist/{esm/sdk/runtime-ecdsa-tempo-BXWgFVBa.js → public/sdk/runtime-ecdsa-tempo-lTFTb9Rh.js} +1 -1
  71. package/dist/public/sdk/{runtime-email-otp-BlAaSKtk.js → runtime-email-otp-CPqTCH8Q.js} +1 -1
  72. package/dist/public/sdk/{runtime-export-B4FuHhcH.js → runtime-export-Brz53_oi.js} +1 -1
  73. package/dist/public/sdk/{runtime-near-BnWOpEpA.js → runtime-near-Da_xFUXx.js} +1 -1
  74. package/dist/public/sdk/{runtime-preferences-COm-LTiu.js → runtime-preferences-riUZGaTs.js} +1 -1
  75. package/dist/public/sdk/{runtime-recovery-BJTo5Idi.js → runtime-recovery-CTj4nDAM.js} +1 -1
  76. package/dist/public/sdk/{runtime-recovery-codes-CEOjdUHV.js → runtime-recovery-codes-D8T9LQ7-.js} +1 -1
  77. package/dist/public/sdk/{shared-BKPGtAps.js → shared-hx7KVyeq.js} +1 -1
  78. package/dist/public/sdk/tx-confirm-ui.js +4 -0
  79. package/dist/public/sdk/wallet-iframe-host-ecdsa.js +1 -1
  80. package/dist/public/sdk/wallet-iframe-host-full.js +1 -1
  81. package/dist/public/sdk/wallet-iframe-host-near.js +1 -1
  82. package/dist/public/sdk/wallet-iframe-host-runtime.js +1 -1
  83. package/dist/public/sdk/wallet-ui.css +1 -1
  84. package/dist/public/sdk/workers/router_ab_ed25519_yao_client_bg.wasm +0 -0
  85. package/dist/public/sdk/workers/wallet_custody_ceremony_bg.wasm +0 -0
  86. package/dist/public/wallet-assets.manifest.json +46 -46
  87. package/dist/public/wallet-service/index.html +4 -4
  88. package/dist/types/wallet/src/SeamsWeb/walletIframe/coordinator.d.ts +2 -1
  89. package/dist/types/wallet/src/SeamsWeb/walletIframe/host/auth-menu/domain.d.ts +20 -3
  90. package/dist/types/wallet/src/SeamsWeb/walletIframe/host/auth-menu/session.d.ts +3 -0
  91. package/dist/types/wallet/src/SeamsWeb/walletIframe/host/ui/auth-menu/AuthMenuSurface.d.ts +1 -0
  92. package/dist/types/wallet/src/SeamsWeb/walletIframe/host/ui/auth-menu/icons.d.ts +2 -0
  93. package/dist/types/wallet/src/core/ui/messages.d.ts +1 -1
  94. package/dist/workers/router_ab_ed25519_yao_client_bg.wasm +0 -0
  95. package/dist/workers/wallet_custody_ceremony_bg.wasm +0 -0
  96. package/package.json +1 -1
  97. package/dist/esm/sdk/appearance-token-vars-CzBVbO39.js +0 -2
  98. package/dist/esm/sdk/runtime-auth-jtyQAuxZ.js +0 -1
  99. package/dist/public/sdk/appearance-token-vars-CzBVbO39.js +0 -2
  100. package/dist/public/sdk/runtime-auth-jtyQAuxZ.js +0 -1
@@ -0,0 +1,209 @@
1
+ import { createWalletIframeSurfaceMeasurementReporter } from "../../../../SeamsWeb/walletIframe/host/surface-measurement-reporter.js";
2
+ import { sameSurfaceMeasurementBinding } from "./surface-measurement-binding.js";
3
+ import { resolveUiAppearance } from "./appearance.js";
4
+ //#region src/core/signingEngine/uiConfirm/ui/export-viewer-host.ts
5
+ let mountedHost = null;
6
+ let mountVersion = 0;
7
+ var ExportViewerHost = class {
8
+ surface;
9
+ state;
10
+ constructor(session, context, model, binding, lifecycle, mount) {
11
+ this.session = session;
12
+ this.context = context;
13
+ this.state = {
14
+ kind: "mounted",
15
+ lifecycle,
16
+ binding,
17
+ reporter: null
18
+ };
19
+ this.surface = mount({
20
+ parent: document.body,
21
+ context,
22
+ model,
23
+ onClosed: this.closed
24
+ });
25
+ }
26
+ start() {
27
+ if (this.state.kind === "disposed") return;
28
+ notifyLifecycle(this.state.lifecycle, "opened");
29
+ if (this.state.kind === "mounted") this.bindMeasurement(this.state.binding);
30
+ }
31
+ matches(session, context) {
32
+ return this.surface.element.isConnected && this.context === context && this.session.kind === session.kind && this.session.id === session.id;
33
+ }
34
+ update(model, binding, lifecycle) {
35
+ if (this.state.kind === "disposed") return;
36
+ if (lifecycle) this.state.lifecycle = lifecycle;
37
+ this.surface.update(model);
38
+ if (!sameSurfaceMeasurementBinding(this.state.binding, binding)) this.bindMeasurement(binding);
39
+ }
40
+ dispose() {
41
+ if (mountedHost === this) mountedHost = null;
42
+ this.surface.dispose();
43
+ }
44
+ closed = () => {
45
+ const state = this.state;
46
+ if (state.kind === "disposed") return;
47
+ this.state = { kind: "disposed" };
48
+ if (mountedHost === this) {
49
+ mountedHost = null;
50
+ mountVersion += 1;
51
+ }
52
+ state.reporter?.disconnect();
53
+ notifyLifecycle(state.lifecycle, "closed");
54
+ };
55
+ bindMeasurement(binding) {
56
+ const state = this.state;
57
+ if (state.kind === "disposed") return;
58
+ state.reporter?.disconnect();
59
+ state.binding = binding;
60
+ state.reporter = null;
61
+ if (binding.kind === "disabled") return;
62
+ const reporter = createWalletIframeSurfaceMeasurementReporter({
63
+ kind: "request_surface",
64
+ element: this.surface.element,
65
+ requestId: binding.requestId,
66
+ postMeasurement: binding.postMeasurement
67
+ });
68
+ if (this.state === state) state.reporter = reporter;
69
+ else reporter.disconnect();
70
+ }
71
+ };
72
+ function notifyLifecycle(listener, event) {
73
+ try {
74
+ listener?.(event);
75
+ } catch {}
76
+ }
77
+ function exportContext(args) {
78
+ const binding = args.surfaceMeasurementBinding;
79
+ if (binding.kind !== "wallet_iframe") return "standalone";
80
+ return (binding.hostSurfaceVariant ?? args.variant) === "modal" ? "wallet-iframe" : "standalone";
81
+ }
82
+ function normalizeGuidance(guidance) {
83
+ if (!guidance) return void 0;
84
+ const title = guidance.title.trim();
85
+ const body = guidance.body?.trim();
86
+ const steps = guidance.steps?.map(trimText).filter(nonemptyText);
87
+ if (!title && !body && !steps?.length) return void 0;
88
+ return {
89
+ title,
90
+ body,
91
+ steps
92
+ };
93
+ }
94
+ function trimText(value) {
95
+ return value.trim();
96
+ }
97
+ function nonemptyText(value) {
98
+ return value.length > 0;
99
+ }
100
+ function hasKey(entry) {
101
+ return !!entry.publicKey.trim() || !!entry.privateKey.trim();
102
+ }
103
+ function keyMetadata(entry, index) {
104
+ return {
105
+ id: `${entry.scheme}-${index}`,
106
+ scheme: entry.scheme,
107
+ label: entry.label.trim(),
108
+ publicKey: entry.publicKey.trim(),
109
+ address: entry.address?.trim() ?? ""
110
+ };
111
+ }
112
+ function normalizeExportContent(args) {
113
+ const accountId = args.accountId.trim();
114
+ const guidance = normalizeGuidance(args.guidance);
115
+ const message = args.errorMessage?.trim();
116
+ if (message) return {
117
+ kind: "failed",
118
+ accountId,
119
+ guidance,
120
+ message
121
+ };
122
+ const entries = args.keys?.filter(hasKey) ?? [];
123
+ if (entries.length === 0) {
124
+ const publicKey = args.publicKey?.trim() ?? "";
125
+ const privateKey = args.privateKey?.trim() ?? "";
126
+ if (publicKey || privateKey) entries.push({
127
+ scheme: "ed25519",
128
+ label: "NEAR Ed25519",
129
+ publicKey,
130
+ privateKey
131
+ });
132
+ }
133
+ if (args.loading) {
134
+ const loading = {
135
+ kind: "loading",
136
+ accountId,
137
+ guidance,
138
+ entries: []
139
+ };
140
+ for (const [index, entry] of entries.entries()) loading.entries.push({
141
+ ...keyMetadata(entry, index),
142
+ material: { kind: "loading" }
143
+ });
144
+ return loading;
145
+ }
146
+ const ready = {
147
+ kind: "ready",
148
+ accountId,
149
+ guidance,
150
+ entries: []
151
+ };
152
+ for (const [index, entry] of entries.entries()) {
153
+ const privateKey = entry.privateKey.trim();
154
+ ready.entries.push({
155
+ ...keyMetadata(entry, index),
156
+ material: privateKey ? {
157
+ kind: "ready",
158
+ value: privateKey
159
+ } : { kind: "unavailable" }
160
+ });
161
+ }
162
+ return ready;
163
+ }
164
+ function isExportViewerSessionOpen(sessionId) {
165
+ const id = sessionId.trim();
166
+ return !!id && mountedHost?.session.kind === "tracked" && mountedHost.session.id === id && mountedHost.surface.element.isConnected;
167
+ }
168
+ async function upsertExportViewerHost(args) {
169
+ if (typeof document === "undefined") throw new Error("Export viewer host requires a DOM environment");
170
+ const version = ++mountVersion;
171
+ const model = {
172
+ variant: args.variant,
173
+ appearance: resolveUiAppearance({
174
+ requestedAppearance: args.appearance,
175
+ requestedMode: args.theme
176
+ }),
177
+ content: normalizeExportContent(args)
178
+ };
179
+ const id = args.sessionId?.trim();
180
+ const session = id ? {
181
+ kind: "tracked",
182
+ id
183
+ } : { kind: "untracked" };
184
+ const context = exportContext(args);
185
+ const { mountExportPrivateKeySurface } = await import("./preact/mountExportPrivateKeySurface.js");
186
+ if (version !== mountVersion) return;
187
+ if (mountedHost?.matches(session, context)) {
188
+ mountedHost.update(model, args.surfaceMeasurementBinding, args.onLifecycle);
189
+ return;
190
+ }
191
+ mountedHost?.dispose();
192
+ if (version !== mountVersion) return;
193
+ const host = new ExportViewerHost(session, context, model, args.surfaceMeasurementBinding, args.onLifecycle ?? null, mountExportPrivateKeySurface);
194
+ mountedHost = host;
195
+ try {
196
+ host.start();
197
+ } catch (error) {
198
+ host.dispose();
199
+ throw error;
200
+ }
201
+ }
202
+ function removeExportViewerHostIfPresent() {
203
+ mountVersion += 1;
204
+ mountedHost?.dispose();
205
+ }
206
+ //#endregion
207
+ export { isExportViewerSessionOpen, removeExportViewerHostIfPresent, upsertExportViewerHost };
208
+
209
+ //# sourceMappingURL=export-viewer-host.js.map
@@ -0,0 +1,319 @@
1
+ import { walletDisplayText, walletText } from "../../../../ui/messages.js";
2
+ import { WalletLocaleContext, WalletText, useWalletLocale } from "./WalletLocale.js";
3
+ import { copySurfaceText } from "./clipboard.js";
4
+ import { CopyStatusIcon } from "./CopyStatusIcon.js";
5
+ import { advanceRevealState, createSpinningState, maskedPrivateKey, settlingState } from "../export-private-key-reveal.js";
6
+ import { Component, createRef } from "preact";
7
+ import { Fragment as Fragment$1, jsx, jsxs } from "preact/jsx-runtime";
8
+ //#region src/core/signingEngine/uiConfirm/ui/preact/ExportPrivateKeySurface.tsx
9
+ /** @jsxImportSource preact */
10
+ function ExportPrivateKeySurface({ model, onClose }) {
11
+ const locale = useWalletLocale();
12
+ const entries = model.kind === "failed" ? [] : model.entries;
13
+ const showAccount = entries.length === 0 || entries.some(isNearKey);
14
+ return /* @__PURE__ */ jsx("div", {
15
+ class: "seams-export-key-viewer",
16
+ "data-seams-drawer-no-drag": true,
17
+ onPointerDown: stopDrag,
18
+ onMouseDown: stopDrag,
19
+ onTouchStart: stopDrag,
20
+ children: /* @__PURE__ */ jsxs("div", {
21
+ class: "content",
22
+ children: [
23
+ /* @__PURE__ */ jsxs("div", {
24
+ class: "seams-export-header",
25
+ children: [/* @__PURE__ */ jsx("h2", {
26
+ class: "title",
27
+ children: /* @__PURE__ */ jsx(WalletText, { message: "Exported Keys" })
28
+ }), onClose && /* @__PURE__ */ jsx("button", {
29
+ type: "button",
30
+ class: "seams-export-modal-close",
31
+ "aria-label": walletText(locale, "Close exported keys"),
32
+ onClick: onClose,
33
+ children: "×"
34
+ })]
35
+ }),
36
+ model.kind === "failed" && /* @__PURE__ */ jsx("div", {
37
+ class: "error-banner",
38
+ role: "alert",
39
+ children: /* @__PURE__ */ jsx(WalletText, { copy: model.message })
40
+ }),
41
+ /* @__PURE__ */ jsxs("div", {
42
+ class: "fields",
43
+ children: [showAccount && /* @__PURE__ */ jsxs("div", {
44
+ class: "field",
45
+ children: [/* @__PURE__ */ jsx("div", {
46
+ class: "field-label",
47
+ children: /* @__PURE__ */ jsx(WalletText, { message: "Near Account ID" })
48
+ }), /* @__PURE__ */ jsx("div", {
49
+ class: "field-value",
50
+ children: /* @__PURE__ */ jsx("span", {
51
+ class: "value",
52
+ children: model.accountId || "—"
53
+ })
54
+ })]
55
+ }), entries.length > 0 ? entries.map(renderKey) : /* @__PURE__ */ jsx("div", {
56
+ class: "field",
57
+ children: /* @__PURE__ */ jsx("div", {
58
+ class: "field-value",
59
+ children: /* @__PURE__ */ jsx("span", {
60
+ class: "muted",
61
+ children: model.kind === "loading" ? /* @__PURE__ */ jsx(WalletText, { message: "Preparing private key…" }) : /* @__PURE__ */ jsx(WalletText, { message: "No keys available" })
62
+ })
63
+ })
64
+ })]
65
+ }),
66
+ model.guidance && /* @__PURE__ */ jsx(ExportGuidanceContent, { guidance: model.guidance }),
67
+ /* @__PURE__ */ jsx("div", {
68
+ class: "warning",
69
+ children: /* @__PURE__ */ jsx(WalletText, { message: "Warning: your private keys grant full control of your account and funds. Keep it in a secret place." })
70
+ })
71
+ ]
72
+ })
73
+ });
74
+ }
75
+ function isNearKey(entry) {
76
+ return entry.scheme === "ed25519";
77
+ }
78
+ function renderKey(entry) {
79
+ return /* @__PURE__ */ jsx(ExportKeyCard, { entry }, entry.id);
80
+ }
81
+ function stopDrag(event) {
82
+ event.stopPropagation();
83
+ }
84
+ function ExportGuidanceContent({ guidance }) {
85
+ return /* @__PURE__ */ jsxs("div", {
86
+ class: "warning",
87
+ children: [
88
+ /* @__PURE__ */ jsx("strong", { children: /* @__PURE__ */ jsx(WalletText, { copy: guidance.title || "Next Steps" }) }),
89
+ guidance.body && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(WalletText, { copy: guidance.body }) }),
90
+ guidance.steps?.length ? /* @__PURE__ */ jsx("ol", { children: guidance.steps.map(renderGuidanceStep) }) : null
91
+ ]
92
+ });
93
+ }
94
+ function renderGuidanceStep(step, index) {
95
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(WalletText, { copy: step }) }, index);
96
+ }
97
+ var ExportKeyCard = class extends Component {
98
+ static contextType = WalletLocaleContext;
99
+ state = {
100
+ reveal: null,
101
+ publicCopied: false,
102
+ privateCopied: false
103
+ };
104
+ root = createRef();
105
+ frame = null;
106
+ timers = /* @__PURE__ */ new Map();
107
+ generation = 0;
108
+ copyLifetime = new AbortController();
109
+ active = false;
110
+ componentDidMount() {
111
+ this.active = true;
112
+ this.reset(this.props.entry);
113
+ }
114
+ componentWillReceiveProps(next) {
115
+ if (!sameKey(this.props.entry, next.entry)) this.reset(next.entry);
116
+ }
117
+ componentDidUpdate() {
118
+ this.schedule();
119
+ }
120
+ componentWillUnmount() {
121
+ this.active = false;
122
+ this.clearPending();
123
+ this.state.reveal = null;
124
+ }
125
+ clearPending() {
126
+ this.generation += 1;
127
+ this.copyLifetime.abort();
128
+ const view = this.root.current?.ownerDocument.defaultView;
129
+ if (this.frame !== null) view?.cancelAnimationFrame(this.frame);
130
+ this.frame = null;
131
+ for (const timer of this.timers.values()) view?.clearTimeout(timer);
132
+ this.timers.clear();
133
+ }
134
+ reset(entry) {
135
+ this.clearPending();
136
+ this.copyLifetime = new AbortController();
137
+ const view = this.root.current.ownerDocument.defaultView;
138
+ const reduced = view.matchMedia("(prefers-reduced-motion: reduce)").matches;
139
+ const now = view.performance.now();
140
+ let reveal = null;
141
+ switch (entry.material.kind) {
142
+ case "loading":
143
+ reveal = createSpinningState(entry.id, entry.scheme, reduced, now);
144
+ break;
145
+ case "ready":
146
+ reveal = reduced ? {
147
+ kind: "settled",
148
+ entryKey: entry.id
149
+ } : settlingState(createSpinningState(entry.id, entry.scheme, false, now), maskedPrivateKey(entry.material.value), now);
150
+ break;
151
+ case "unavailable": break;
152
+ default: assertNever(entry.material);
153
+ }
154
+ this.setState({
155
+ reveal,
156
+ publicCopied: false,
157
+ privateCopied: false
158
+ });
159
+ }
160
+ schedule() {
161
+ const reveal = this.state.reveal;
162
+ if (!this.active || this.frame !== null || !reveal || reveal.kind === "settled") return;
163
+ const view = this.root.current.ownerDocument.defaultView;
164
+ if (view.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
165
+ this.frame = view.requestAnimationFrame(this.tick);
166
+ }
167
+ tick = (now) => {
168
+ this.frame = null;
169
+ const reveal = this.state.reveal;
170
+ if (!this.active || !reveal || reveal.kind === "settled") return;
171
+ const next = advanceRevealState(reveal, now);
172
+ if (next !== reveal) this.setState({ reveal: next });
173
+ this.schedule();
174
+ };
175
+ copyPublic = () => {
176
+ this.copy("public");
177
+ };
178
+ copyPrivate = () => {
179
+ this.copy("private");
180
+ };
181
+ clearPublic = () => {
182
+ this.timers.delete("public");
183
+ if (this.active) this.setState({ publicCopied: false });
184
+ };
185
+ clearPrivate = () => {
186
+ this.timers.delete("private");
187
+ if (this.active) this.setState({ privateCopied: false });
188
+ };
189
+ async copy(field) {
190
+ const entry = this.props.entry;
191
+ if (!this.active) return;
192
+ if (field === "private" && (entry.material.kind !== "ready" || this.state.reveal?.kind !== "settled")) return;
193
+ let value = entry.publicKey;
194
+ if (field === "private") {
195
+ if (entry.material.kind !== "ready") return;
196
+ value = entry.material.value;
197
+ }
198
+ if (!value) return;
199
+ const generation = this.generation;
200
+ const root = this.root.current;
201
+ const view = root.ownerDocument.defaultView;
202
+ view.focus();
203
+ if (!await copySurfaceText(root, value, this.copyLifetime.signal).catch(copyFailed) || !this.active || generation !== this.generation) return;
204
+ const previous = this.timers.get(field);
205
+ if (previous !== void 0) view.clearTimeout(previous);
206
+ if (field === "public") this.setState({ publicCopied: true });
207
+ else this.setState({ privateCopied: true });
208
+ this.timers.set(field, view.setTimeout(field === "public" ? this.clearPublic : this.clearPrivate, 3e3));
209
+ }
210
+ render() {
211
+ const entry = this.props.entry;
212
+ const privateReady = entry.material.kind === "ready" && this.state.reveal?.kind === "settled";
213
+ return /* @__PURE__ */ jsxs("div", {
214
+ class: "key-card",
215
+ ref: this.root,
216
+ children: [
217
+ /* @__PURE__ */ jsx("div", {
218
+ class: "key-title",
219
+ children: /* @__PURE__ */ jsx(WalletText, { copy: entry.label })
220
+ }),
221
+ entry.address && /* @__PURE__ */ jsxs("div", {
222
+ class: "field",
223
+ children: [/* @__PURE__ */ jsx("div", {
224
+ class: "field-label",
225
+ children: /* @__PURE__ */ jsx(WalletText, { message: "Address" })
226
+ }), /* @__PURE__ */ jsx("div", {
227
+ class: "field-value",
228
+ children: /* @__PURE__ */ jsx("span", {
229
+ class: "value",
230
+ children: entry.address
231
+ })
232
+ })]
233
+ }),
234
+ entry.scheme === "ed25519" && /* @__PURE__ */ jsxs("button", {
235
+ type: "button",
236
+ class: `field copy-field${this.state.publicCopied ? " copied" : ""}`,
237
+ "aria-label": walletDisplayText(this.context, this.state.publicCopied ? "Public key copied" : "Copy public key"),
238
+ disabled: !entry.publicKey,
239
+ onClick: this.copyPublic,
240
+ children: [/* @__PURE__ */ jsx("div", {
241
+ class: "field-label",
242
+ children: /* @__PURE__ */ jsx(WalletText, { message: "Public Key" })
243
+ }), /* @__PURE__ */ jsxs("div", {
244
+ class: "field-value",
245
+ children: [/* @__PURE__ */ jsx("span", {
246
+ class: "value",
247
+ children: entry.publicKey || "—"
248
+ }), /* @__PURE__ */ jsx(CopyStatusIcon, {})]
249
+ })]
250
+ }),
251
+ /* @__PURE__ */ jsxs("button", {
252
+ type: "button",
253
+ class: `field copy-field${this.state.privateCopied ? " copied" : ""}`,
254
+ "aria-label": walletDisplayText(this.context, this.state.privateCopied ? "Private key copied" : "Copy private key"),
255
+ disabled: !privateReady,
256
+ onClick: this.copyPrivate,
257
+ children: [/* @__PURE__ */ jsx("div", {
258
+ class: "field-label",
259
+ children: /* @__PURE__ */ jsx(WalletText, { message: "Private Key" })
260
+ }), /* @__PURE__ */ jsxs("div", {
261
+ class: "field-value",
262
+ children: [/* @__PURE__ */ jsx("span", {
263
+ class: "value private-key",
264
+ children: /* @__PURE__ */ jsx(PrivateKeyText, {
265
+ material: entry.material,
266
+ reveal: this.state.reveal
267
+ })
268
+ }), /* @__PURE__ */ jsx(CopyStatusIcon, {})]
269
+ })]
270
+ })
271
+ ]
272
+ });
273
+ }
274
+ };
275
+ function sameKey(left, right) {
276
+ return left.id === right.id && left.scheme === right.scheme && left.publicKey === right.publicKey && left.material.kind === right.material.kind && left.material.value === right.material.value;
277
+ }
278
+ function copyFailed() {
279
+ return false;
280
+ }
281
+ function PrivateKeyText({ material, reveal }) {
282
+ if (reveal && reveal.kind !== "settled") return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
283
+ class: "private-key-reel",
284
+ "aria-hidden": "true",
285
+ children: [/* @__PURE__ */ jsx("span", {
286
+ class: "reel-prefix",
287
+ children: reveal.prefix
288
+ }), renderSlots(reveal)]
289
+ }), /* @__PURE__ */ jsx("span", {
290
+ class: "seams-sr-only",
291
+ role: "status",
292
+ children: /* @__PURE__ */ jsx(WalletText, { message: "Decrypting private key" })
293
+ })] });
294
+ if (material.kind !== "ready") return /* @__PURE__ */ jsx("span", {
295
+ class: "muted",
296
+ children: "—"
297
+ });
298
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", { children: maskedPrivateKey(material.value) }), /* @__PURE__ */ jsx("span", {
299
+ class: "seams-sr-only",
300
+ role: "status",
301
+ children: /* @__PURE__ */ jsx(WalletText, { message: "Private key ready" })
302
+ })] });
303
+ }
304
+ function renderSlots(reveal) {
305
+ const lockedSlots = reveal.kind === "settling" ? reveal.lockedSlots : 0;
306
+ const slots = [];
307
+ for (let index = 0; index < reveal.slots.length; index += 1) slots.push(/* @__PURE__ */ jsx("span", {
308
+ class: `reel-slot${index < lockedSlots ? " settled" : ""}`,
309
+ children: reveal.slots[index].glyph
310
+ }, index));
311
+ return slots;
312
+ }
313
+ function assertNever(value) {
314
+ throw new Error(`Unexpected export key material: ${String(value)}`);
315
+ }
316
+ //#endregion
317
+ export { ExportPrivateKeySurface };
318
+
319
+ //# sourceMappingURL=ExportPrivateKeySurface.js.map
@@ -0,0 +1,92 @@
1
+ import { appearanceTokenCssRule } from "../appearance-token-vars.js";
2
+ import { withWalletLocale } from "./WalletLocale.js";
3
+ import { confirmationDocumentStyles } from "./confirmation-styles.js";
4
+ import { ConfirmationModal } from "./ConfirmationModal.js";
5
+ import { ConfirmationDrawer } from "./ConfirmationDrawer.js";
6
+ import { WalletIframeDomEvents } from "../../../../browser/walletIframe/events.js";
7
+ import { ExportPrivateKeySurface } from "./ExportPrivateKeySurface.js";
8
+ import { render } from "preact";
9
+ import { jsx } from "preact/jsx-runtime";
10
+ //#region src/core/signingEngine/uiConfirm/ui/preact/mountExportPrivateKeySurface.tsx
11
+ /** @jsxImportSource preact */
12
+ let nextExportId = 0;
13
+ var MountedExportSurface = class {
14
+ element;
15
+ styles;
16
+ context;
17
+ state;
18
+ constructor(input) {
19
+ this.styles = confirmationDocumentStyles(input.parent.ownerDocument);
20
+ this.context = input.context;
21
+ this.state = {
22
+ kind: "mounted",
23
+ onClosed: input.onClosed
24
+ };
25
+ this.element = input.parent.ownerDocument.createElement("div");
26
+ this.element.id = `seams-export-surface-${++nextExportId}`;
27
+ this.element.className = "seams-wallet-ui seams-export-surface";
28
+ this.element.dataset.seamsExportSurface = input.context;
29
+ this.element.addEventListener(WalletIframeDomEvents.TX_CONFIRMER_CANCEL, this.handleCancel);
30
+ input.parent.appendChild(this.element);
31
+ try {
32
+ this.update(input.model);
33
+ } catch (error) {
34
+ this.remove();
35
+ throw error;
36
+ }
37
+ }
38
+ update(model) {
39
+ if (this.state.kind === "disposed") return;
40
+ this.element.lang = model.appearance.locale ?? "en";
41
+ this.element.dataset.theme = model.appearance.theme.mode;
42
+ this.element.dataset.seamsExportVariant = model.variant;
43
+ this.styles.setDynamicRule(this.element.id, appearanceTokenCssRule(this.element.id, model.appearance));
44
+ if (model.variant === "modal") {
45
+ render(withWalletLocale(model.appearance.locale ?? "en", /* @__PURE__ */ jsx(ConfirmationModal, {
46
+ context: this.context,
47
+ label: "Exported Keys",
48
+ onCancel: this.dispose,
49
+ children: /* @__PURE__ */ jsx(ExportPrivateKeySurface, {
50
+ model: model.content,
51
+ onClose: this.dispose
52
+ })
53
+ })), this.element);
54
+ return;
55
+ }
56
+ render(withWalletLocale(model.appearance.locale ?? "en", /* @__PURE__ */ jsx(ConfirmationDrawer, {
57
+ context: this.context,
58
+ label: "Exported Keys",
59
+ dismissOnBackdrop: false,
60
+ styles: this.styles,
61
+ state: {
62
+ kind: "open",
63
+ interaction: "ready"
64
+ },
65
+ onCancel: this.dispose,
66
+ children: /* @__PURE__ */ jsx(ExportPrivateKeySurface, { model: model.content })
67
+ })), this.element);
68
+ }
69
+ dispose = () => {
70
+ if (this.state.kind === "disposed") return;
71
+ const onClosed = this.state.onClosed;
72
+ this.remove();
73
+ onClosed();
74
+ };
75
+ handleCancel = () => {
76
+ this.dispose();
77
+ };
78
+ remove() {
79
+ this.state = { kind: "disposed" };
80
+ this.element.removeEventListener(WalletIframeDomEvents.TX_CONFIRMER_CANCEL, this.handleCancel);
81
+ render(null, this.element);
82
+ this.styles.deleteDynamicRule(this.element.id);
83
+ this.element.remove();
84
+ }
85
+ };
86
+ function mountExportPrivateKeySurface(input) {
87
+ return new MountedExportSurface(input);
88
+ }
89
+ //#endregion
90
+ export { mountExportPrivateKeySurface };
91
+
92
+ //# sourceMappingURL=mountExportPrivateKeySurface.js.map
@@ -0,0 +1,12 @@
1
+ //#region src/core/signingEngine/uiConfirm/ui/surface-measurement-binding.ts
2
+ function sameSurfaceMeasurementBinding(left, right) {
3
+ if (!left || left.kind !== right.kind) return false;
4
+ switch (left.kind) {
5
+ case "disabled": return right.kind === "disabled";
6
+ case "wallet_iframe": return right.kind === "wallet_iframe" && left.requestId === right.requestId && left.postMeasurement === right.postMeasurement && left.hostSurfaceVariant === right.hostSurfaceVariant;
7
+ }
8
+ }
9
+ //#endregion
10
+ export { sameSurfaceMeasurementBinding };
11
+
12
+ //# sourceMappingURL=surface-measurement-binding.js.map
@@ -15,6 +15,10 @@ const walletMessages = [
15
15
  ["Choose your Google account.", "Google アカウントを選択してください。"],
16
16
  ["Creating passkey wallet…", "パスキーでウォレットを作成中…"],
17
17
  ["Unlocking wallet…", "ウォレットのロックを解除中…"],
18
+ ["Wallet created", "ウォレットを作成しました"],
19
+ ["Your wallet is ready on this device.", "このデバイスでウォレットを利用できます。"],
20
+ ["You’re in", "サインインしました"],
21
+ ["Your wallet is unlocked.", "ウォレットのロックを解除しました。"],
18
22
  ["Too many attempts. Wait a moment.", "試行回数が多すぎます。しばらくお待ちください。"],
19
23
  ["Can’t reach Seams right now.", "現在 Seams に接続できません。"],
20
24
  ["That took too long.", "時間がかかりすぎたため、操作を終了しました。"],
package/dist/esm/index.js CHANGED
@@ -5,8 +5,8 @@ import { configuredThresholdEcdsaChainTargets, nearAccountRefFromAccountId, thre
5
5
  import { BrowserCapabilityUnavailableError } from "./SeamsWeb/publicApi/capabilitySelection.js";
6
6
  import { toAccountId } from "./core/types/accountIds.js";
7
7
  import { AccountSyncEventPhase, KeyExportEventPhase, LinkDeviceEventPhase, RegistrationEventPhase, SigningEventPhase, UnlockEventPhase, WALLET_FLOW_EVENT_MESSAGES, WALLET_FLOW_EVENT_STEPS, WALLET_FLOW_EVENT_VERSION, createAccountSyncFlowEvent, createKeyExportFlowEvent, createLinkDeviceFlowEvent, createRegistrationFlowEvent, createSigningFlowEvent, createUnlockFlowEvent, createWalletFlowEvent, isWalletFlowEvent } from "./core/types/sdkSentEvents.js";
8
- import { SeamsWeb } from "./SeamsWeb/SeamsWeb.js";
9
8
  import { buildHostedAuthMenuOpenRequest, hostedAuthMenuExternalAuthRequestIdFromBoundary, hostedAuthMenuSessionIdFromBoundary } from "./SeamsWeb/walletIframe/shared/messages.js";
9
+ import { SeamsWeb } from "./SeamsWeb/SeamsWeb.js";
10
10
  import { ExternalEvmController } from "./externalEvm/controller.js";
11
11
  import { DEVICE_LINKING_CONFIG, SIGNER_WORKER_MANAGER_CONFIG } from "./config.js";
12
12
  import { defineSeamsConfig, seamsTestnetConfig } from "./core/config/defineConfig.js";
@@ -10,7 +10,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
10
  import "./Web3AuthProfileButton.css";
11
11
  //#region src/react/components/AccountMenuButton/AccountMenuButtonView.tsx
12
12
  function measurePanel(element, setHeight) {
13
- setHeight(element.getBoundingClientRect().height);
13
+ setHeight(element.offsetHeight);
14
14
  }
15
15
  function observePanel(contentRef, isOpen, setHeight) {
16
16
  const content = contentRef.current;
@@ -100,3 +100,23 @@
100
100
  width: 100%;
101
101
  height: 100%;
102
102
  }
103
+
104
+ /* A phone-width menu left the description beside the label only a few
105
+ characters, so it moves to a line of its own under the label. */
106
+ @media (max-width: 480px) {
107
+ .seams-account-screen .seams-export-keys-row {
108
+ flex-wrap: wrap;
109
+ row-gap: 2px;
110
+ }
111
+
112
+ .seams-account-screen .seams-export-keys-row-spinner {
113
+ margin-left: auto;
114
+ }
115
+
116
+ .seams-account-screen .seams-export-keys-row-description {
117
+ flex-basis: 100%;
118
+ order: 1;
119
+ white-space: normal;
120
+ text-align: left;
121
+ }
122
+ }