@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,288 @@
1
+ /**
2
+ * Locked Screen - Unlock wallet with password
3
+ */
4
+
5
+ import { useState } from 'react';
6
+ import { INTERNAL_METHODS } from '../../../shared/constants';
7
+ import { useStore } from '../../store';
8
+ import { send } from '../../utils/messaging';
9
+ import { formatWalletError } from '../../utils/formatWalletError';
10
+ import { Alert } from '../../components/Alert';
11
+ import { ConfirmModal } from '../../components/ConfirmModal';
12
+ import { EyeIcon } from '../../components/icons/EyeIcon';
13
+ import { EyeOffIcon } from '../../components/icons/EyeOffIcon';
14
+ import vectorLeft from '../../assets/vector-left.svg';
15
+ import vectorRight from '../../assets/vector-right.svg';
16
+ import vectorTopRight from '../../assets/vector-top-right.svg';
17
+ import vectorTopRightRotated from '../../assets/vector-top-right-rotated.svg';
18
+ import vectorBottomLeft from '../../assets/vector-bottom-left.svg';
19
+ import RoseLogo from '../../../icons/rose.svg';
20
+
21
+ export function LockedScreen() {
22
+ const [password, setPassword] = useState('');
23
+ const [showPassword, setShowPassword] = useState(false);
24
+ const [error, setError] = useState('');
25
+ const [showResetConfirm, setShowResetConfirm] = useState(false);
26
+ const {
27
+ navigate,
28
+ syncWallet,
29
+ wallet,
30
+ fetchBalance,
31
+ pendingConnectRequest,
32
+ pendingTransactionRequest,
33
+ pendingSignRequest,
34
+ pendingSignRawTxRequest,
35
+ } = useStore();
36
+
37
+ async function handleUnlock() {
38
+ // Clear previous errors
39
+ setError('');
40
+
41
+ if (!password) {
42
+ setError('Please enter a password');
43
+ return;
44
+ }
45
+
46
+ const result = await send<{
47
+ ok?: boolean;
48
+ address?: string;
49
+ accounts?: Array<{ name: string; address: string; index: number }>;
50
+ currentAccount?: { name: string; address: string; index: number };
51
+ error?: string;
52
+ }>(INTERNAL_METHODS.UNLOCK, [password]);
53
+
54
+ if (result?.error) {
55
+ setError(formatWalletError(result.error));
56
+ setPassword(''); // Clear password on error
57
+ } else {
58
+ setPassword('');
59
+ const accounts = result.accounts || [];
60
+ const currentAccount = result.currentAccount || accounts[0] || null;
61
+
62
+ // Load cached balances from storage
63
+ const { STORAGE_KEYS } = await import('../../../shared/constants');
64
+ const stored = await chrome.storage.local.get([STORAGE_KEYS.CACHED_BALANCES]);
65
+ const cachedBalances = (stored[STORAGE_KEYS.CACHED_BALANCES] || {}) as Record<string, number>;
66
+ const cachedBalance = currentAccount ? (cachedBalances[currentAccount.address] ?? 0) : 0;
67
+
68
+ syncWallet({
69
+ ...wallet,
70
+ locked: false,
71
+ address: result.address || null,
72
+ accounts,
73
+ currentAccount,
74
+ balance: cachedBalance,
75
+ availableBalance: cachedBalance,
76
+ accountBalances: cachedBalances,
77
+ });
78
+
79
+ // Trigger balance fetch after successful unlock
80
+ fetchBalance();
81
+
82
+ // Navigate to pending approval if one exists, otherwise go home
83
+ if (pendingConnectRequest) {
84
+ navigate('connect-approval');
85
+ } else if (pendingTransactionRequest) {
86
+ navigate('approve-transaction');
87
+ } else if (pendingSignRequest) {
88
+ navigate('sign-message');
89
+ } else if (pendingSignRawTxRequest) {
90
+ navigate('approve-sign-raw-tx');
91
+ } else {
92
+ navigate('home');
93
+ }
94
+ }
95
+ }
96
+
97
+ function handleResetWallet() {
98
+ setShowResetConfirm(true);
99
+ }
100
+
101
+ async function confirmResetWallet() {
102
+ // Reset the wallet via the background service
103
+ const result = await send<{ ok?: boolean }>(INTERNAL_METHODS.RESET_WALLET, []);
104
+
105
+ if (result?.ok) {
106
+ // Navigate to onboarding start
107
+ navigate('onboarding-start');
108
+ setShowResetConfirm(false);
109
+ }
110
+ }
111
+
112
+ function cancelResetWallet() {
113
+ setShowResetConfirm(false);
114
+ }
115
+
116
+ return (
117
+ <div className="relative w-[357px] h-[600px] bg-[var(--color-bg)] overflow-hidden">
118
+ {/* Decorative vector elements - final positioning */}
119
+ {/* Top-left curved wave */}
120
+ <img
121
+ src={vectorLeft}
122
+ alt=""
123
+ className="absolute left-[-14px] top-[93px] w-[89px] h-[70px]"
124
+ aria-hidden="true"
125
+ />
126
+ {/* Top-right curved line */}
127
+ <img
128
+ src={vectorTopRight}
129
+ alt=""
130
+ className="absolute left-[303px] top-[168px] w-[80px] h-[45px]"
131
+ aria-hidden="true"
132
+ />
133
+ {/* Top-right rotated icon - partially off-screen at top */}
134
+ <img
135
+ src={vectorTopRightRotated}
136
+ alt=""
137
+ className="absolute left-[247px] top-[-19px] w-[63px] h-[67px]"
138
+ style={{ transform: 'rotate(24.65deg)' }}
139
+ aria-hidden="true"
140
+ />
141
+ {/* Bottom-right icon */}
142
+ <img
143
+ src={vectorRight}
144
+ alt=""
145
+ className="absolute left-[287px] top-[395px] w-[49px] h-[79px]"
146
+ aria-hidden="true"
147
+ />
148
+ {/* Bottom-left icon */}
149
+ <img
150
+ src={vectorBottomLeft}
151
+ alt=""
152
+ className="absolute left-[-11px] top-[414px] w-[64px] h-[64px]"
153
+ aria-hidden="true"
154
+ />
155
+ <div className="relative flex flex-col justify-between h-full px-4 py-8 z-10">
156
+ {/* Main content */}
157
+ <div className="flex flex-col gap-8 w-full">
158
+ {/* Logo and heading */}
159
+ <div className="flex flex-col items-center gap-3 w-full">
160
+ <img src={RoseLogo} alt="Rose Wallet" className="w-[104px] h-[104px]" />
161
+ <div className="flex flex-col gap-2 items-center text-center w-full">
162
+ <h1
163
+ className="font-serif font-medium text-[var(--color-text-primary)]"
164
+ style={{
165
+ fontSize: 'var(--font-size-xl)',
166
+ lineHeight: 'var(--line-height-relaxed)',
167
+ letterSpacing: '-0.02em',
168
+ }}
169
+ >
170
+ Welcome back
171
+ </h1>
172
+ <p
173
+ className="font-sans text-[var(--color-text-muted)]"
174
+ style={{
175
+ fontSize: 'var(--font-size-sm)',
176
+ lineHeight: 'var(--line-height-snug)',
177
+ letterSpacing: '0.02em',
178
+ }}
179
+ >
180
+ Your Nockchain companion
181
+ </p>
182
+ </div>
183
+ </div>
184
+
185
+ {/* Password input and unlock button */}
186
+ <div className="flex flex-col gap-4 w-full">
187
+ <div className="flex flex-col gap-1.5 w-full">
188
+ <label
189
+ className="font-sans font-medium text-[var(--color-text-primary)]"
190
+ style={{
191
+ fontSize: 'var(--font-size-sm)',
192
+ lineHeight: 'var(--line-height-snug)',
193
+ letterSpacing: '0.02em',
194
+ }}
195
+ >
196
+ Password
197
+ </label>
198
+ <div className="bg-[var(--color-bg)] border border-[var(--color-surface-700)] rounded-lg p-3 flex items-center gap-2.5 h-[52px]">
199
+ <input
200
+ type={showPassword ? 'text' : 'password'}
201
+ value={password}
202
+ onChange={e => {
203
+ setPassword(e.target.value);
204
+ setError('');
205
+ }}
206
+ onKeyDown={e => e.key === 'Enter' && handleUnlock()}
207
+ placeholder="Enter your password"
208
+ autoFocus
209
+ className="flex-1 bg-transparent font-sans font-medium text-[var(--color-text-primary)] placeholder:text-[var(--color-text-secondary)] outline-none"
210
+ style={{
211
+ fontSize: 'var(--font-size-base)',
212
+ lineHeight: 'var(--line-height-snug)',
213
+ letterSpacing: '0.01em',
214
+ }}
215
+ />
216
+ <button
217
+ onClick={() => setShowPassword(!showPassword)}
218
+ className="text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)]"
219
+ >
220
+ {showPassword ? (
221
+ <EyeOffIcon className="h-4 w-4" />
222
+ ) : (
223
+ <EyeIcon className="h-4 w-4" />
224
+ )}
225
+ </button>
226
+ </div>
227
+ </div>
228
+
229
+ {/* Error message */}
230
+ {error && <Alert type="error">{error}</Alert>}
231
+
232
+ {/* Unlock button */}
233
+ <button
234
+ onClick={handleUnlock}
235
+ className="w-full h-12 px-5 py-[15px] btn-secondary text-[var(--color-bg)] rounded-lg flex items-center justify-center transition-opacity hover:opacity-90"
236
+ style={{
237
+ fontFamily: 'var(--font-sans)',
238
+ fontSize: 'var(--font-size-base)',
239
+ fontWeight: 500,
240
+ lineHeight: 'var(--line-height-snug)',
241
+ letterSpacing: '0.01em',
242
+ }}
243
+ >
244
+ Unlock
245
+ </button>
246
+ </div>
247
+ </div>
248
+
249
+ {/* Bottom text with reset link */}
250
+ <div className="flex flex-col gap-3 items-center text-center w-full">
251
+ <p
252
+ className="font-sans text-[var(--color-text-muted)]"
253
+ style={{
254
+ fontSize: 'var(--font-size-sm)',
255
+ lineHeight: 'var(--line-height-snug)',
256
+ letterSpacing: '0.02em',
257
+ }}
258
+ >
259
+ Can't login? You can delete your current wallet and create a new one
260
+ </p>
261
+ <button
262
+ onClick={handleResetWallet}
263
+ className="font-sans font-medium text-[var(--color-text-primary)] underline hover:opacity-80"
264
+ style={{
265
+ fontSize: 'var(--font-size-base)',
266
+ lineHeight: 'var(--line-height-snug)',
267
+ letterSpacing: '0.01em',
268
+ }}
269
+ >
270
+ Reset wallet
271
+ </button>
272
+ </div>
273
+ </div>
274
+
275
+ {/* Reset Confirmation Modal */}
276
+ <ConfirmModal
277
+ isOpen={showResetConfirm}
278
+ title="Reset wallet"
279
+ message="This will delete your current wallet and all data. You will need to create a new wallet or import an existing one."
280
+ confirmText="Reset"
281
+ cancelText="Cancel"
282
+ onConfirm={confirmResetWallet}
283
+ onCancel={cancelResetWallet}
284
+ variant="danger"
285
+ />
286
+ </div>
287
+ );
288
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Receive Screen - Display address for receiving NOCK
3
+ */
4
+
5
+ import { useStore } from '../../store';
6
+ import { ScreenContainer } from '../../components/ScreenContainer';
7
+ import { ChevronLeftIcon } from '../../components/icons/ChevronLeftIcon';
8
+ import { CopyIcon } from '../../components/icons/CopyIcon';
9
+ import { useCopyToClipboard } from '../../hooks/useCopyToClipboard';
10
+
11
+ export function ReceiveScreen() {
12
+ const { navigate, wallet } = useStore();
13
+ const { copied, copyToClipboard } = useCopyToClipboard();
14
+
15
+ const address = wallet.currentAccount?.address || '';
16
+
17
+ return (
18
+ <ScreenContainer className="flex flex-col">
19
+ {/* Header with back button */}
20
+ <div className="flex items-center gap-3 mb-6">
21
+ <button
22
+ onClick={() => navigate('home')}
23
+ className="transition-colors"
24
+ style={{ color: 'var(--color-text-primary)' }}
25
+ >
26
+ <ChevronLeftIcon />
27
+ </button>
28
+ <h2 className="text-xl font-semibold" style={{ color: 'var(--color-text-primary)' }}>
29
+ Receive NOCK
30
+ </h2>
31
+ </div>
32
+
33
+ {/* Address section */}
34
+ <div className="mb-6">
35
+ <h3 className="text-center mb-4" style={{ color: 'var(--color-text-primary)' }}>
36
+ Your Address
37
+ </h3>
38
+ <div
39
+ className="rounded-lg p-4 mb-4"
40
+ style={{ backgroundColor: 'var(--color-surface-800)' }}
41
+ >
42
+ <p className="text-sm font-mono break-all" style={{ color: 'var(--color-text-primary)' }}>
43
+ {address}
44
+ </p>
45
+ </div>
46
+
47
+ {/* Copy button */}
48
+ <button
49
+ onClick={() => copyToClipboard(address)}
50
+ className="w-full font-semibold py-3 px-4 rounded-lg transition-colors flex items-center justify-center gap-2"
51
+ style={{
52
+ backgroundColor: 'var(--color-primary)',
53
+ color: '#000',
54
+ }}
55
+ onMouseEnter={e => {
56
+ e.currentTarget.style.opacity = '0.9';
57
+ }}
58
+ onMouseLeave={e => {
59
+ e.currentTarget.style.opacity = '1';
60
+ }}
61
+ >
62
+ <CopyIcon />
63
+ {copied ? 'Copied!' : 'Copy Address'}
64
+ </button>
65
+ </div>
66
+
67
+ {/* Instructions */}
68
+ <div className="rounded-lg p-4 mb-6" style={{ backgroundColor: 'var(--color-surface-900)' }}>
69
+ <h4 className="text-sm font-semibold mb-2" style={{ color: 'var(--color-text-primary)' }}>
70
+ How to receive NOCK:
71
+ </h4>
72
+ <ul className="text-sm space-y-1" style={{ color: 'var(--color-text-muted)' }}>
73
+ <li>• Share this address with the sender</li>
74
+ <li>• Transactions will appear in your wallet</li>
75
+ </ul>
76
+ </div>
77
+
78
+ {/* Done button */}
79
+ <button onClick={() => navigate('home')} className="w-full btn-secondary mt-auto">
80
+ Done
81
+ </button>
82
+ </ScreenContainer>
83
+ );
84
+ }
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Sent Screen - Transaction confirmation after successful send
3
+ */
4
+
5
+ import { useStore } from '../../store';
6
+ import { ScreenContainer } from '../../components/ScreenContainer';
7
+ import { ChevronLeftIcon } from '../../components/icons/ChevronLeftIcon';
8
+ import { CheckIcon } from '../../components/icons/CheckIcon';
9
+ import { ArrowUpRightIcon } from '../../components/icons/ArrowUpRightIcon';
10
+ import { useCopyToClipboard } from '../../hooks/useCopyToClipboard';
11
+
12
+ export function SentScreen() {
13
+ const { navigate, lastTransaction } = useStore();
14
+ const { copied, copyToClipboard } = useCopyToClipboard();
15
+
16
+ if (!lastTransaction) {
17
+ // If no transaction data, redirect to home
18
+ navigate('home');
19
+ return null;
20
+ }
21
+
22
+ const { txid, amount, fee } = lastTransaction;
23
+ const total = amount + fee;
24
+
25
+ function handleViewDetails() {
26
+ // TODO: Navigate to transaction details screen
27
+ // For now, just navigate home
28
+ navigate('home');
29
+ }
30
+
31
+ return (
32
+ <ScreenContainer className="flex flex-col">
33
+ {/* Header */}
34
+ <div className="flex items-center gap-3 mb-6">
35
+ <button
36
+ onClick={() => navigate('home')}
37
+ className="transition-colors"
38
+ style={{ color: 'var(--color-text-primary)' }}
39
+ >
40
+ <ChevronLeftIcon />
41
+ </button>
42
+ <h2 className="text-xl font-semibold" style={{ color: 'var(--color-text-primary)' }}>
43
+ Send NOCK
44
+ </h2>
45
+ </div>
46
+
47
+ {/* Success icon */}
48
+ <div className="flex justify-center mb-6">
49
+ <div
50
+ className="w-24 h-24 rounded-full flex items-center justify-center"
51
+ style={{ backgroundColor: 'var(--color-green-light)' }}
52
+ >
53
+ <CheckIcon className="w-12 h-12" style={{ color: 'var(--color-green)' }} />
54
+ </div>
55
+ </div>
56
+
57
+ {/* Success message */}
58
+ <h3
59
+ className="text-2xl font-semibold text-center mb-2"
60
+ style={{ color: 'var(--color-text-primary)' }}
61
+ >
62
+ Sent!
63
+ </h3>
64
+ <p className="text-center mb-8" style={{ color: 'var(--color-text-muted)' }}>
65
+ Your transaction has been broadcast to the network
66
+ </p>
67
+
68
+ {/* Transaction details */}
69
+ <div
70
+ className="rounded-lg p-4 mb-4 space-y-3"
71
+ style={{ backgroundColor: 'var(--color-surface-800)' }}
72
+ >
73
+ <div className="flex justify-between items-center">
74
+ <span className="text-sm" style={{ color: 'var(--color-text-muted)' }}>
75
+ Amount
76
+ </span>
77
+ <span className="font-mono" style={{ color: 'var(--color-text-primary)' }}>
78
+ {amount} NOCK
79
+ </span>
80
+ </div>
81
+ <div className="flex justify-between items-center">
82
+ <span className="text-sm" style={{ color: 'var(--color-text-muted)' }}>
83
+ Fee
84
+ </span>
85
+ <span className="font-mono" style={{ color: 'var(--color-text-primary)' }}>
86
+ {fee} NOCK
87
+ </span>
88
+ </div>
89
+ <div
90
+ className="pt-3 flex justify-between items-center"
91
+ style={{ borderTop: '1px solid var(--color-divider)' }}
92
+ >
93
+ <span className="text-sm" style={{ color: 'var(--color-text-muted)' }}>
94
+ Total
95
+ </span>
96
+ <span className="font-mono font-semibold" style={{ color: 'var(--color-text-primary)' }}>
97
+ {total.toFixed(2)} NOCK
98
+ </span>
99
+ </div>
100
+ </div>
101
+
102
+ {/* Transaction ID */}
103
+ <div className="rounded-lg p-4 mb-6" style={{ backgroundColor: 'var(--color-surface-800)' }}>
104
+ <p className="text-sm mb-2" style={{ color: 'var(--color-text-muted)' }}>
105
+ Transaction ID:
106
+ </p>
107
+ <button onClick={() => copyToClipboard(txid)} className="w-full text-left">
108
+ <p
109
+ className="text-sm font-mono break-all mb-2"
110
+ style={{ color: 'var(--color-text-primary)' }}
111
+ >
112
+ {txid}
113
+ </p>
114
+ </button>
115
+ {copied && (
116
+ <p className="text-xs" style={{ color: 'var(--color-green)' }}>
117
+ Copied to clipboard!
118
+ </p>
119
+ )}
120
+ <button
121
+ onClick={handleViewDetails}
122
+ className="flex items-center gap-2 text-sm transition-colors mt-2"
123
+ style={{ color: 'var(--color-text-muted)' }}
124
+ onMouseEnter={e => (e.currentTarget.style.color = 'var(--color-text-primary)')}
125
+ onMouseLeave={e => (e.currentTarget.style.color = 'var(--color-text-muted)')}
126
+ >
127
+ <ArrowUpRightIcon className="w-4 h-4" />
128
+ View Details
129
+ </button>
130
+ </div>
131
+
132
+ {/* Action button */}
133
+ <button onClick={() => navigate('home')} className="btn-primary">
134
+ View Details
135
+ </button>
136
+ </ScreenContainer>
137
+ );
138
+ }