@nockchain/rose 0.1.4-nightly.5

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 (205) hide show
  1. package/.github/workflows/artifacts.yml +33 -0
  2. package/.github/workflows/ci.yml +68 -0
  3. package/.github/workflows/publish-sdk.yml +35 -0
  4. package/.nvmrc +1 -0
  5. package/.prettierignore +5 -0
  6. package/.prettierrc +8 -0
  7. package/LICENSE +22 -0
  8. package/README.md +117 -0
  9. package/extension/background/index.ts +1500 -0
  10. package/extension/content/index.ts +59 -0
  11. package/extension/icons/rose.svg +27 -0
  12. package/extension/icons/rose128.png +0 -0
  13. package/extension/icons/rose16.png +0 -0
  14. package/extension/icons/rose256.png +0 -0
  15. package/extension/icons/rose32.png +0 -0
  16. package/extension/icons/rose48.png +0 -0
  17. package/extension/icons/rose512.png +0 -0
  18. package/extension/inpage/index.ts +86 -0
  19. package/extension/manifest.json +48 -0
  20. package/extension/popup/Popup.tsx +94 -0
  21. package/extension/popup/Router.tsx +121 -0
  22. package/extension/popup/assets/arrow-down-icon.svg +3 -0
  23. package/extension/popup/assets/arrow-left-icon.svg +3 -0
  24. package/extension/popup/assets/arrow-right-icon.svg +3 -0
  25. package/extension/popup/assets/arrow-up-icon.svg +3 -0
  26. package/extension/popup/assets/arrow-up-right-icon.svg +3 -0
  27. package/extension/popup/assets/checkmark-icon.svg +3 -0
  28. package/extension/popup/assets/checkmark-pencil-icon.svg +3 -0
  29. package/extension/popup/assets/checkmark-success-icon.svg +3 -0
  30. package/extension/popup/assets/clock-icon.svg +3 -0
  31. package/extension/popup/assets/close-x-icon.svg +3 -0
  32. package/extension/popup/assets/copy-icon.svg +6 -0
  33. package/extension/popup/assets/explorer-icon.svg +3 -0
  34. package/extension/popup/assets/eye-off-icon.svg +3 -0
  35. package/extension/popup/assets/eye-open-icon.svg +4 -0
  36. package/extension/popup/assets/feedback-icon.svg +3 -0
  37. package/extension/popup/assets/green-status-dot.svg +3 -0
  38. package/extension/popup/assets/info-icon.svg +3 -0
  39. package/extension/popup/assets/iris-logo-40.svg +27 -0
  40. package/extension/popup/assets/iris-logo-96.svg +27 -0
  41. package/extension/popup/assets/iris-logo-blue.svg +27 -0
  42. package/extension/popup/assets/iris-logo-no-eye.svg +27 -0
  43. package/extension/popup/assets/iris-logo-orange.svg +27 -0
  44. package/extension/popup/assets/iris-logo.svg +27 -0
  45. package/extension/popup/assets/key-icon.svg +3 -0
  46. package/extension/popup/assets/lock-icon-yellow.svg +3 -0
  47. package/extension/popup/assets/lock-icon.svg +3 -0
  48. package/extension/popup/assets/pencil-edit-icon.svg +3 -0
  49. package/extension/popup/assets/permissions-icon.svg +3 -0
  50. package/extension/popup/assets/receipt-icon.svg +5 -0
  51. package/extension/popup/assets/refresh-icon.svg +3 -0
  52. package/extension/popup/assets/settings-gear-icon.svg +8 -0
  53. package/extension/popup/assets/settings-icon.svg +3 -0
  54. package/extension/popup/assets/theme-icon.svg +3 -0
  55. package/extension/popup/assets/trash-bin-icon.svg +3 -0
  56. package/extension/popup/assets/trend-down-arrow.svg +5 -0
  57. package/extension/popup/assets/trend-up-arrow.svg +5 -0
  58. package/extension/popup/assets/user-account-icon.svg +3 -0
  59. package/extension/popup/assets/vector-bottom-left.svg +9 -0
  60. package/extension/popup/assets/vector-left.svg +9 -0
  61. package/extension/popup/assets/vector-right.svg +9 -0
  62. package/extension/popup/assets/vector-top-right-rotated.svg +8 -0
  63. package/extension/popup/assets/vector-top-right.svg +9 -0
  64. package/extension/popup/assets/wallet-dropdown-arrow.svg +5 -0
  65. package/extension/popup/assets/wallet-icon-style-1.svg +6 -0
  66. package/extension/popup/assets/wallet-icon-style-10.svg +8 -0
  67. package/extension/popup/assets/wallet-icon-style-11.svg +8 -0
  68. package/extension/popup/assets/wallet-icon-style-12.svg +8 -0
  69. package/extension/popup/assets/wallet-icon-style-13.svg +8 -0
  70. package/extension/popup/assets/wallet-icon-style-14.svg +8 -0
  71. package/extension/popup/assets/wallet-icon-style-15.svg +8 -0
  72. package/extension/popup/assets/wallet-icon-style-2.svg +8 -0
  73. package/extension/popup/assets/wallet-icon-style-3.svg +8 -0
  74. package/extension/popup/assets/wallet-icon-style-4.svg +8 -0
  75. package/extension/popup/assets/wallet-icon-style-5.svg +8 -0
  76. package/extension/popup/assets/wallet-icon-style-6.svg +8 -0
  77. package/extension/popup/assets/wallet-icon-style-7.svg +8 -0
  78. package/extension/popup/assets/wallet-icon-style-8.svg +8 -0
  79. package/extension/popup/assets/wallet-icon-style-9.svg +8 -0
  80. package/extension/popup/components/AccountIcon.tsx +78 -0
  81. package/extension/popup/components/AccountSelector.tsx +246 -0
  82. package/extension/popup/components/Alert.tsx +48 -0
  83. package/extension/popup/components/ConfirmModal.tsx +81 -0
  84. package/extension/popup/components/PasswordInput.tsx +49 -0
  85. package/extension/popup/components/ScreenContainer.tsx +17 -0
  86. package/extension/popup/components/SiteIcon.tsx +60 -0
  87. package/extension/popup/components/ThemeToggle.tsx +44 -0
  88. package/extension/popup/components/icons/ArrowDownLeftIcon.tsx +20 -0
  89. package/extension/popup/components/icons/ArrowUpRightIcon.tsx +20 -0
  90. package/extension/popup/components/icons/CheckIcon.tsx +20 -0
  91. package/extension/popup/components/icons/ChevronDownIcon.tsx +15 -0
  92. package/extension/popup/components/icons/ChevronLeftIcon.tsx +15 -0
  93. package/extension/popup/components/icons/ChevronRightIcon.tsx +15 -0
  94. package/extension/popup/components/icons/ChevronUpIcon.tsx +15 -0
  95. package/extension/popup/components/icons/CloseIcon.tsx +26 -0
  96. package/extension/popup/components/icons/CopyIcon.tsx +20 -0
  97. package/extension/popup/components/icons/EditIcon.tsx +20 -0
  98. package/extension/popup/components/icons/EyeIcon.tsx +13 -0
  99. package/extension/popup/components/icons/EyeOffIcon.tsx +13 -0
  100. package/extension/popup/components/icons/InfoIcon.tsx +20 -0
  101. package/extension/popup/components/icons/LockIcon.tsx +20 -0
  102. package/extension/popup/components/icons/PlusIcon.tsx +15 -0
  103. package/extension/popup/components/icons/ReceiveArrowIcon.tsx +14 -0
  104. package/extension/popup/components/icons/ReceiveCircleIcon.tsx +20 -0
  105. package/extension/popup/components/icons/SendPaperPlaneIcon.tsx +18 -0
  106. package/extension/popup/components/icons/SentArrowIcon.tsx +21 -0
  107. package/extension/popup/components/icons/SettingsIcon.tsx +26 -0
  108. package/extension/popup/components/icons/ShieldIcon.tsx +20 -0
  109. package/extension/popup/components/icons/UploadIcon.tsx +20 -0
  110. package/extension/popup/components/icons/WalletIcon.tsx +20 -0
  111. package/extension/popup/contexts/ThemeContext.tsx +105 -0
  112. package/extension/popup/hooks/useApprovalDetection.ts +128 -0
  113. package/extension/popup/hooks/useAutoFocus.ts +36 -0
  114. package/extension/popup/hooks/useAutoRejectOnClose.ts +25 -0
  115. package/extension/popup/hooks/useClickOutside.ts +33 -0
  116. package/extension/popup/hooks/useCopyToClipboard.ts +33 -0
  117. package/extension/popup/hooks/useFavicon.ts +64 -0
  118. package/extension/popup/hooks/useNumericInput.ts +93 -0
  119. package/extension/popup/index.html +13 -0
  120. package/extension/popup/index.tsx +24 -0
  121. package/extension/popup/screens/AboutScreen.tsx +118 -0
  122. package/extension/popup/screens/HomeScreen.tailwind.css +85 -0
  123. package/extension/popup/screens/HomeScreen.tsx +902 -0
  124. package/extension/popup/screens/KeySettingsPasswordScreen.tsx +164 -0
  125. package/extension/popup/screens/LockTimeScreen.tsx +155 -0
  126. package/extension/popup/screens/ReceiveScreen.tsx +149 -0
  127. package/extension/popup/screens/RecoveryPhraseScreen.tsx +183 -0
  128. package/extension/popup/screens/SendReviewScreen.tsx +308 -0
  129. package/extension/popup/screens/SendScreen.tsx +825 -0
  130. package/extension/popup/screens/SendSubmittedScreen.tsx +193 -0
  131. package/extension/popup/screens/SettingsScreen.tsx +116 -0
  132. package/extension/popup/screens/ThemeSettingsScreen.tsx +107 -0
  133. package/extension/popup/screens/TransactionDetailsScreen.tsx +346 -0
  134. package/extension/popup/screens/ViewSecretPhraseScreen.tsx +212 -0
  135. package/extension/popup/screens/WalletPermissionsScreen.tsx +123 -0
  136. package/extension/popup/screens/WalletSettingsScreen.tsx +381 -0
  137. package/extension/popup/screens/WalletStylingScreen.tsx +306 -0
  138. package/extension/popup/screens/approvals/ConnectApprovalScreen.tsx +136 -0
  139. package/extension/popup/screens/approvals/SignMessageScreen.tsx +140 -0
  140. package/extension/popup/screens/approvals/SignRawTxScreen.tsx +320 -0
  141. package/extension/popup/screens/approvals/TransactionApprovalScreen.tsx +167 -0
  142. package/extension/popup/screens/onboarding/BackupScreen.tsx +254 -0
  143. package/extension/popup/screens/onboarding/CreateScreen.tsx +273 -0
  144. package/extension/popup/screens/onboarding/ImportScreen.tsx +676 -0
  145. package/extension/popup/screens/onboarding/ImportScreenV0.tsx +678 -0
  146. package/extension/popup/screens/onboarding/ImportSuccessScreen.tsx +236 -0
  147. package/extension/popup/screens/onboarding/ResumeBackupScreen.tsx +166 -0
  148. package/extension/popup/screens/onboarding/StartScreen.tsx +142 -0
  149. package/extension/popup/screens/onboarding/SuccessScreen.tsx +193 -0
  150. package/extension/popup/screens/onboarding/VerifyScreen.tsx +220 -0
  151. package/extension/popup/screens/system/LockedScreen.tsx +288 -0
  152. package/extension/popup/screens/transactions/ReceiveScreen.tsx +84 -0
  153. package/extension/popup/screens/transactions/SentScreen.tsx +138 -0
  154. package/extension/popup/store.ts +482 -0
  155. package/extension/popup/styles.css +246 -0
  156. package/extension/popup/utils/format.ts +58 -0
  157. package/extension/popup/utils/formatWalletError.ts +36 -0
  158. package/extension/popup/utils/memo.ts +299 -0
  159. package/extension/popup/utils/messaging.ts +16 -0
  160. package/extension/shared/address-encoding.ts +69 -0
  161. package/extension/shared/balance-query.ts +123 -0
  162. package/extension/shared/constants.ts +386 -0
  163. package/extension/shared/currency.ts +128 -0
  164. package/extension/shared/first-name-derivation.ts +128 -0
  165. package/extension/shared/keyfile.ts +58 -0
  166. package/extension/shared/onboarding.ts +78 -0
  167. package/extension/shared/price-api.ts +79 -0
  168. package/extension/shared/rpc-client-browser.ts +315 -0
  169. package/extension/shared/transaction-builder.ts +443 -0
  170. package/extension/shared/types.ts +450 -0
  171. package/extension/shared/utxo-diff.ts +212 -0
  172. package/extension/shared/utxo-store.ts +548 -0
  173. package/extension/shared/utxo-sync.ts +343 -0
  174. package/extension/shared/validators.ts +26 -0
  175. package/extension/shared/vault.ts +1580 -0
  176. package/extension/shared/wallet-crypto.ts +77 -0
  177. package/extension/shared/wasm-utils.ts +76 -0
  178. package/extension/shared/webcrypto.ts +67 -0
  179. package/extension/types/wasm.d.ts +13 -0
  180. package/package.json +39 -0
  181. package/postcss.config.js +6 -0
  182. package/rose-extension-dist.zip +0 -0
  183. package/sdk/README.md +88 -0
  184. package/sdk/examples/app.ts +166 -0
  185. package/sdk/examples/index.html +51 -0
  186. package/sdk/examples/tsconfig.json +15 -0
  187. package/sdk/examples/tx-builder.html +532 -0
  188. package/sdk/examples/tx-builder.ts +1766 -0
  189. package/sdk/package-lock.json +424 -0
  190. package/sdk/package.json +68 -0
  191. package/sdk/src/constants.ts +28 -0
  192. package/sdk/src/errors.ts +74 -0
  193. package/sdk/src/hooks/index.ts +1 -0
  194. package/sdk/src/hooks/use-rose.ts +94 -0
  195. package/sdk/src/index.ts +12 -0
  196. package/sdk/src/provider.ts +396 -0
  197. package/sdk/src/transaction.ts +163 -0
  198. package/sdk/src/types/rose-wasm.d.ts +14 -0
  199. package/sdk/src/types.ts +97 -0
  200. package/sdk/src/wasm.ts +13 -0
  201. package/sdk/tsconfig.json +20 -0
  202. package/sdk/vite.config.examples.ts +32 -0
  203. package/tailwind.config.ts +38 -0
  204. package/tsconfig.json +20 -0
  205. package/vite.config.ts +60 -0
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Onboarding Success Screen - Wallet created successfully
3
+ */
4
+
5
+ import { useEffect } from 'react';
6
+ import { useStore } from '../../store';
7
+ import { markOnboardingComplete } from '../../../shared/onboarding';
8
+ import { useCopyToClipboard } from '../../hooks/useCopyToClipboard';
9
+ import checkmarkIcon from '../../assets/checkmark-icon.svg';
10
+
11
+ export function SuccessScreen() {
12
+ const { navigate, wallet, goBack, fetchBalance } = useStore();
13
+ const { copied, copyToClipboard } = useCopyToClipboard();
14
+
15
+ // Mark onboarding as complete when user reaches this screen
16
+ useEffect(() => {
17
+ markOnboardingComplete();
18
+ }, []);
19
+
20
+ // Format address to show start and end with middle grayed out
21
+ function formatAddress(address: string) {
22
+ if (!address || address.length < 20) return address;
23
+ const start = address.slice(0, 6);
24
+ const middle = address.slice(6, -5);
25
+ const end = address.slice(-5);
26
+ return { start, middle, end };
27
+ }
28
+
29
+ const formattedAddress = formatAddress(wallet.address || '');
30
+
31
+ function handleStartUsing() {
32
+ // Start fetching balance in background (non-blocking)
33
+ fetchBalance();
34
+ // Navigate immediately - HomeScreen will show loading state
35
+ navigate('home');
36
+ }
37
+
38
+ return (
39
+ <div className="relative w-[357px] h-[600px] bg-[var(--color-bg)]">
40
+ {/* Header with back button */}
41
+ <div className="flex items-center justify-between h-16 px-4 py-3 border-b border-[var(--color-divider)]">
42
+ <button
43
+ onClick={goBack}
44
+ className="p-2 -ml-2 hover:opacity-70 transition-opacity"
45
+ aria-label="Go back"
46
+ >
47
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
48
+ <path
49
+ d="M10 12L6 8L10 4"
50
+ stroke="var(--color-text-primary)"
51
+ strokeWidth="2"
52
+ strokeLinecap="round"
53
+ strokeLinejoin="round"
54
+ />
55
+ </svg>
56
+ </button>
57
+ <h2
58
+ className="font-sans font-medium text-[var(--color-text-primary)]"
59
+ style={{
60
+ fontSize: 'var(--font-size-lg)',
61
+ lineHeight: 'var(--line-height-normal)',
62
+ letterSpacing: '0.01em',
63
+ }}
64
+ >
65
+ Wallet created!
66
+ </h2>
67
+ <div className="w-8" /> {/* Spacer for centering */}
68
+ </div>
69
+
70
+ {/* Main content */}
71
+ <div className="flex flex-col justify-between h-[536px]">
72
+ <div className="px-4 py-2 flex flex-col gap-8">
73
+ {/* Icon and heading */}
74
+ <div className="flex flex-col items-center gap-3">
75
+ <div className="w-10 h-10">
76
+ <img src={checkmarkIcon} alt="" className="w-full h-full" />
77
+ </div>
78
+ <div className="flex flex-col gap-2 items-center text-center w-full">
79
+ <h1
80
+ className="font-serif font-medium text-[var(--color-text-primary)]"
81
+ style={{
82
+ fontSize: 'var(--font-size-xl)',
83
+ lineHeight: 'var(--line-height-relaxed)',
84
+ letterSpacing: '-0.02em',
85
+ }}
86
+ >
87
+ Your wallet is ready!
88
+ </h1>
89
+ <p
90
+ className="font-sans text-[var(--color-text-muted)]"
91
+ style={{
92
+ fontSize: 'var(--font-size-sm)',
93
+ lineHeight: 'var(--line-height-snug)',
94
+ letterSpacing: '0.02em',
95
+ }}
96
+ >
97
+ Welcome to Nockchain
98
+ </p>
99
+ </div>
100
+ </div>
101
+
102
+ {/* Address section */}
103
+ <div className="flex flex-col gap-1.5 w-full">
104
+ <p
105
+ className="font-sans font-medium text-center text-[var(--color-text-primary)]"
106
+ style={{
107
+ fontSize: 'var(--font-size-sm)',
108
+ lineHeight: 'var(--line-height-snug)',
109
+ letterSpacing: '0.02em',
110
+ }}
111
+ >
112
+ Your address
113
+ </p>
114
+ <div className="bg-[var(--color-surface-900)] rounded-lg p-3 flex flex-col gap-5 items-center">
115
+ {/* Address display */}
116
+ <p
117
+ className="font-sans font-medium text-center text-[var(--color-text-primary)] break-words w-full"
118
+ style={{
119
+ fontSize: 'var(--font-size-base)',
120
+ lineHeight: 'var(--line-height-snug)',
121
+ letterSpacing: '0.01em',
122
+ }}
123
+ >
124
+ {typeof formattedAddress === 'string' ? (
125
+ formattedAddress
126
+ ) : (
127
+ <>
128
+ {formattedAddress.start}
129
+ <span className="text-[var(--color-text-muted)]">
130
+ {formattedAddress.middle}
131
+ </span>
132
+ {formattedAddress.end}
133
+ </>
134
+ )}
135
+ </p>
136
+
137
+ {/* Copy button */}
138
+ <button
139
+ onClick={() => copyToClipboard(wallet.address || '')}
140
+ className="border border-[var(--color-text-primary)] rounded-full px-4 py-1.5 flex items-center gap-1.5 hover:opacity-80 transition-opacity"
141
+ >
142
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
143
+ <path
144
+ d="M4 4V2.66667C4 2.29848 4.29848 2 4.66667 2H13.3333C13.7015 2 14 2.29848 14 2.66667V11.3333C14 11.7015 13.7015 12 13.3333 12H12"
145
+ stroke="var(--color-text-primary)"
146
+ strokeWidth="1.5"
147
+ strokeLinecap="round"
148
+ />
149
+ <rect
150
+ x="2"
151
+ y="4"
152
+ width="10"
153
+ height="10"
154
+ rx="0.666667"
155
+ stroke="var(--color-text-primary)"
156
+ strokeWidth="1.5"
157
+ />
158
+ </svg>
159
+ <span
160
+ className="font-sans font-medium text-[var(--color-text-primary)]"
161
+ style={{
162
+ fontSize: 'var(--font-size-base)',
163
+ lineHeight: 'var(--line-height-snug)',
164
+ letterSpacing: '0.01em',
165
+ }}
166
+ >
167
+ {copied ? 'Copied!' : 'Copy address'}
168
+ </span>
169
+ </button>
170
+ </div>
171
+ </div>
172
+ </div>
173
+
174
+ {/* Bottom button */}
175
+ <div className="border-t border-[var(--color-surface-800)] p-3">
176
+ <button
177
+ onClick={handleStartUsing}
178
+ className="w-full h-12 px-5 py-[15px] btn-primary text-[#000000] rounded-lg flex items-center justify-center transition-opacity hover:opacity-90"
179
+ style={{
180
+ fontFamily: 'var(--font-sans)',
181
+ fontSize: 'var(--font-size-base)',
182
+ fontWeight: 500,
183
+ lineHeight: 'var(--line-height-snug)',
184
+ letterSpacing: '0.01em',
185
+ }}
186
+ >
187
+ Start using wallet
188
+ </button>
189
+ </div>
190
+ </div>
191
+ </div>
192
+ );
193
+ }
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Onboarding Verify Screen - Verify user wrote down mnemonic correctly
3
+ */
4
+
5
+ import { useState, useMemo } from 'react';
6
+ import { useStore } from '../../store';
7
+ import { Alert } from '../../components/Alert';
8
+ import lockIcon from '../../assets/lock-icon.svg';
9
+
10
+ /**
11
+ * Generates 6 unique random positions from 0-23 for secret phrase verification
12
+ */
13
+ function generateRandomPositions(): number[] {
14
+ const positions = Array.from({ length: 24 }, (_, i) => i);
15
+ const selected: number[] = [];
16
+
17
+ // Fisher-Yates shuffle and take first 6
18
+ for (let i = positions.length - 1; i > 0 && selected.length < 6; i--) {
19
+ const j = Math.floor(Math.random() * (i + 1));
20
+ [positions[i], positions[j]] = [positions[j], positions[i]];
21
+ selected.push(positions[i]);
22
+ }
23
+
24
+ // Sort selected positions so they appear in order
25
+ return selected.sort((a, b) => a - b);
26
+ }
27
+
28
+ export function VerifyScreen() {
29
+ const { onboardingMnemonic, navigate, setOnboardingMnemonic } = useStore();
30
+ const [inputs, setInputs] = useState<Record<number, string>>({});
31
+ const [error, setError] = useState<string>('');
32
+
33
+ // Generate random positions once per mnemonic (stable across re-renders)
34
+ const testPositions = useMemo(() => generateRandomPositions(), [onboardingMnemonic]);
35
+
36
+ if (!onboardingMnemonic) {
37
+ return (
38
+ <div className="w-[357px] h-[600px] bg-[var(--color-bg)] flex items-center justify-center p-4">
39
+ <Alert type="error">No mnemonic found. Please restart onboarding.</Alert>
40
+ </div>
41
+ );
42
+ }
43
+
44
+ const words = onboardingMnemonic.split(' ');
45
+
46
+ function handleInputChange(position: number, value: string) {
47
+ setInputs(prev => ({ ...prev, [position]: value.trim().toLowerCase() }));
48
+ setError('');
49
+ }
50
+
51
+ function handleVerify() {
52
+ // Check if all positions are filled
53
+ const allFilled = testPositions.every(pos => inputs[pos]?.length > 0);
54
+ if (!allFilled) {
55
+ setError('Please fill in all word fields');
56
+ return;
57
+ }
58
+
59
+ // Verify all words are correct
60
+ const allCorrect = testPositions.every(pos => inputs[pos] === words[pos].toLowerCase());
61
+
62
+ if (allCorrect) {
63
+ // Clear the mnemonic from memory and navigate to success
64
+ setOnboardingMnemonic(null);
65
+ navigate('onboarding-success');
66
+ } else {
67
+ setError('One or more words are incorrect. Please check your secret phrase and try again.');
68
+ }
69
+ }
70
+
71
+ function handleBack() {
72
+ navigate('onboarding-backup');
73
+ }
74
+
75
+ return (
76
+ <div className="relative w-[357px] h-[600px] bg-[var(--color-bg)]">
77
+ {/* Header with back button */}
78
+ <div className="flex items-center justify-between h-16 px-4 py-3 border-b border-[var(--color-divider)]">
79
+ <button
80
+ onClick={handleBack}
81
+ className="p-2 -ml-2 hover:opacity-70 transition-opacity"
82
+ aria-label="Go back"
83
+ >
84
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
85
+ <path
86
+ d="M10 12L6 8L10 4"
87
+ stroke="var(--color-text-primary)"
88
+ strokeWidth="2"
89
+ strokeLinecap="round"
90
+ strokeLinejoin="round"
91
+ />
92
+ </svg>
93
+ </button>
94
+ <h2
95
+ className="font-sans font-medium text-[var(--color-text-primary)]"
96
+ style={{
97
+ fontSize: 'var(--font-size-lg)',
98
+ lineHeight: 'var(--line-height-normal)',
99
+ letterSpacing: '0.01em',
100
+ }}
101
+ >
102
+ Save your secret phrase
103
+ </h2>
104
+ <div className="w-8" /> {/* Spacer for centering */}
105
+ </div>
106
+
107
+ {/* Main content */}
108
+ <div className="flex flex-col justify-between h-[536px]">
109
+ <div className="px-4 py-2 flex flex-col gap-6">
110
+ {/* Icon and heading */}
111
+ <div className="flex flex-col items-center gap-3">
112
+ <div className="w-10 h-10">
113
+ <img src={lockIcon} alt="" className="w-full h-full" />
114
+ </div>
115
+ <div className="flex flex-col gap-2 items-center text-center w-full">
116
+ <h1
117
+ className="font-serif font-medium text-[var(--color-text-primary)]"
118
+ style={{
119
+ fontSize: 'var(--font-size-xl)',
120
+ lineHeight: 'var(--line-height-relaxed)',
121
+ letterSpacing: '-0.02em',
122
+ }}
123
+ >
124
+ Verify secret phrase.
125
+ </h1>
126
+ <p
127
+ className="font-sans text-[var(--color-text-muted)]"
128
+ style={{
129
+ fontSize: 'var(--font-size-sm)',
130
+ lineHeight: 'var(--line-height-snug)',
131
+ letterSpacing: '0.02em',
132
+ }}
133
+ >
134
+ Please write down the words with this number
135
+ </p>
136
+ </div>
137
+ </div>
138
+
139
+ {/* Input fields */}
140
+ <div className="flex flex-col gap-2 w-full">
141
+ {[0, 1, 2].map(row => (
142
+ <div key={row} className="flex gap-2 w-full">
143
+ {[0, 1].map(col => {
144
+ const index = row * 2 + col;
145
+ const position = testPositions[index];
146
+ const wordNumber = position + 1;
147
+
148
+ return (
149
+ <div
150
+ key={col}
151
+ className="flex-1 min-w-0 bg-[var(--color-bg)] border border-[var(--color-surface-700)] rounded-lg p-2 flex items-center gap-2.5 h-11"
152
+ >
153
+ <span
154
+ className="bg-[var(--color-surface-900)] rounded w-7 h-7 flex items-center justify-center font-sans font-medium text-[var(--color-text-primary)] flex-shrink-0"
155
+ style={{
156
+ fontSize: 'var(--font-size-base)',
157
+ lineHeight: 'var(--line-height-snug)',
158
+ letterSpacing: '0.01em',
159
+ }}
160
+ >
161
+ {wordNumber}
162
+ </span>
163
+ <input
164
+ type="text"
165
+ value={inputs[position] || ''}
166
+ onChange={e => handleInputChange(position, e.target.value)}
167
+ placeholder="word"
168
+ className="flex-1 min-w-0 bg-transparent font-sans font-medium text-[var(--color-text-primary)] placeholder:text-[var(--color-text-secondary)] outline-none"
169
+ style={{
170
+ fontSize: 'var(--font-size-base)',
171
+ lineHeight: 'var(--line-height-snug)',
172
+ letterSpacing: '0.01em',
173
+ }}
174
+ />
175
+ </div>
176
+ );
177
+ })}
178
+ </div>
179
+ ))}
180
+ </div>
181
+
182
+ {/* Error message */}
183
+ {error && <Alert type="error">{error}</Alert>}
184
+ </div>
185
+
186
+ {/* Bottom buttons */}
187
+ <div className="border-t border-[var(--color-surface-800)] px-4 py-3">
188
+ <div className="flex gap-3">
189
+ <button
190
+ onClick={handleBack}
191
+ className="flex-1 h-12 px-5 py-[15px] bg-[var(--color-surface-800)] text-[var(--color-text-primary)] rounded-lg flex items-center justify-center transition-opacity hover:opacity-90"
192
+ style={{
193
+ fontFamily: 'var(--font-sans)',
194
+ fontSize: 'var(--font-size-base)',
195
+ fontWeight: 500,
196
+ lineHeight: 'var(--line-height-snug)',
197
+ letterSpacing: '0.01em',
198
+ }}
199
+ >
200
+ Back
201
+ </button>
202
+ <button
203
+ onClick={handleVerify}
204
+ className="flex-1 h-12 px-5 py-[15px] btn-primary text-[#000000] rounded-lg flex items-center justify-center transition-opacity hover:opacity-90"
205
+ style={{
206
+ fontFamily: 'var(--font-sans)',
207
+ fontSize: 'var(--font-size-base)',
208
+ fontWeight: 500,
209
+ lineHeight: 'var(--line-height-snug)',
210
+ letterSpacing: '0.01em',
211
+ }}
212
+ >
213
+ Create wallet
214
+ </button>
215
+ </div>
216
+ </div>
217
+ </div>
218
+ </div>
219
+ );
220
+ }