@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.
- package/.github/workflows/artifacts.yml +33 -0
- package/.github/workflows/ci.yml +68 -0
- package/.github/workflows/publish-sdk.yml +35 -0
- package/.nvmrc +1 -0
- package/.prettierignore +5 -0
- package/.prettierrc +8 -0
- package/LICENSE +22 -0
- package/README.md +117 -0
- package/extension/background/index.ts +1500 -0
- package/extension/content/index.ts +59 -0
- package/extension/icons/rose.svg +27 -0
- package/extension/icons/rose128.png +0 -0
- package/extension/icons/rose16.png +0 -0
- package/extension/icons/rose256.png +0 -0
- package/extension/icons/rose32.png +0 -0
- package/extension/icons/rose48.png +0 -0
- package/extension/icons/rose512.png +0 -0
- package/extension/inpage/index.ts +86 -0
- package/extension/manifest.json +48 -0
- package/extension/popup/Popup.tsx +94 -0
- package/extension/popup/Router.tsx +121 -0
- package/extension/popup/assets/arrow-down-icon.svg +3 -0
- package/extension/popup/assets/arrow-left-icon.svg +3 -0
- package/extension/popup/assets/arrow-right-icon.svg +3 -0
- package/extension/popup/assets/arrow-up-icon.svg +3 -0
- package/extension/popup/assets/arrow-up-right-icon.svg +3 -0
- package/extension/popup/assets/checkmark-icon.svg +3 -0
- package/extension/popup/assets/checkmark-pencil-icon.svg +3 -0
- package/extension/popup/assets/checkmark-success-icon.svg +3 -0
- package/extension/popup/assets/clock-icon.svg +3 -0
- package/extension/popup/assets/close-x-icon.svg +3 -0
- package/extension/popup/assets/copy-icon.svg +6 -0
- package/extension/popup/assets/explorer-icon.svg +3 -0
- package/extension/popup/assets/eye-off-icon.svg +3 -0
- package/extension/popup/assets/eye-open-icon.svg +4 -0
- package/extension/popup/assets/feedback-icon.svg +3 -0
- package/extension/popup/assets/green-status-dot.svg +3 -0
- package/extension/popup/assets/info-icon.svg +3 -0
- package/extension/popup/assets/iris-logo-40.svg +27 -0
- package/extension/popup/assets/iris-logo-96.svg +27 -0
- package/extension/popup/assets/iris-logo-blue.svg +27 -0
- package/extension/popup/assets/iris-logo-no-eye.svg +27 -0
- package/extension/popup/assets/iris-logo-orange.svg +27 -0
- package/extension/popup/assets/iris-logo.svg +27 -0
- package/extension/popup/assets/key-icon.svg +3 -0
- package/extension/popup/assets/lock-icon-yellow.svg +3 -0
- package/extension/popup/assets/lock-icon.svg +3 -0
- package/extension/popup/assets/pencil-edit-icon.svg +3 -0
- package/extension/popup/assets/permissions-icon.svg +3 -0
- package/extension/popup/assets/receipt-icon.svg +5 -0
- package/extension/popup/assets/refresh-icon.svg +3 -0
- package/extension/popup/assets/settings-gear-icon.svg +8 -0
- package/extension/popup/assets/settings-icon.svg +3 -0
- package/extension/popup/assets/theme-icon.svg +3 -0
- package/extension/popup/assets/trash-bin-icon.svg +3 -0
- package/extension/popup/assets/trend-down-arrow.svg +5 -0
- package/extension/popup/assets/trend-up-arrow.svg +5 -0
- package/extension/popup/assets/user-account-icon.svg +3 -0
- package/extension/popup/assets/vector-bottom-left.svg +9 -0
- package/extension/popup/assets/vector-left.svg +9 -0
- package/extension/popup/assets/vector-right.svg +9 -0
- package/extension/popup/assets/vector-top-right-rotated.svg +8 -0
- package/extension/popup/assets/vector-top-right.svg +9 -0
- package/extension/popup/assets/wallet-dropdown-arrow.svg +5 -0
- package/extension/popup/assets/wallet-icon-style-1.svg +6 -0
- package/extension/popup/assets/wallet-icon-style-10.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-11.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-12.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-13.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-14.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-15.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-2.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-3.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-4.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-5.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-6.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-7.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-8.svg +8 -0
- package/extension/popup/assets/wallet-icon-style-9.svg +8 -0
- package/extension/popup/components/AccountIcon.tsx +78 -0
- package/extension/popup/components/AccountSelector.tsx +246 -0
- package/extension/popup/components/Alert.tsx +48 -0
- package/extension/popup/components/ConfirmModal.tsx +81 -0
- package/extension/popup/components/PasswordInput.tsx +49 -0
- package/extension/popup/components/ScreenContainer.tsx +17 -0
- package/extension/popup/components/SiteIcon.tsx +60 -0
- package/extension/popup/components/ThemeToggle.tsx +44 -0
- package/extension/popup/components/icons/ArrowDownLeftIcon.tsx +20 -0
- package/extension/popup/components/icons/ArrowUpRightIcon.tsx +20 -0
- package/extension/popup/components/icons/CheckIcon.tsx +20 -0
- package/extension/popup/components/icons/ChevronDownIcon.tsx +15 -0
- package/extension/popup/components/icons/ChevronLeftIcon.tsx +15 -0
- package/extension/popup/components/icons/ChevronRightIcon.tsx +15 -0
- package/extension/popup/components/icons/ChevronUpIcon.tsx +15 -0
- package/extension/popup/components/icons/CloseIcon.tsx +26 -0
- package/extension/popup/components/icons/CopyIcon.tsx +20 -0
- package/extension/popup/components/icons/EditIcon.tsx +20 -0
- package/extension/popup/components/icons/EyeIcon.tsx +13 -0
- package/extension/popup/components/icons/EyeOffIcon.tsx +13 -0
- package/extension/popup/components/icons/InfoIcon.tsx +20 -0
- package/extension/popup/components/icons/LockIcon.tsx +20 -0
- package/extension/popup/components/icons/PlusIcon.tsx +15 -0
- package/extension/popup/components/icons/ReceiveArrowIcon.tsx +14 -0
- package/extension/popup/components/icons/ReceiveCircleIcon.tsx +20 -0
- package/extension/popup/components/icons/SendPaperPlaneIcon.tsx +18 -0
- package/extension/popup/components/icons/SentArrowIcon.tsx +21 -0
- package/extension/popup/components/icons/SettingsIcon.tsx +26 -0
- package/extension/popup/components/icons/ShieldIcon.tsx +20 -0
- package/extension/popup/components/icons/UploadIcon.tsx +20 -0
- package/extension/popup/components/icons/WalletIcon.tsx +20 -0
- package/extension/popup/contexts/ThemeContext.tsx +105 -0
- package/extension/popup/hooks/useApprovalDetection.ts +128 -0
- package/extension/popup/hooks/useAutoFocus.ts +36 -0
- package/extension/popup/hooks/useAutoRejectOnClose.ts +25 -0
- package/extension/popup/hooks/useClickOutside.ts +33 -0
- package/extension/popup/hooks/useCopyToClipboard.ts +33 -0
- package/extension/popup/hooks/useFavicon.ts +64 -0
- package/extension/popup/hooks/useNumericInput.ts +93 -0
- package/extension/popup/index.html +13 -0
- package/extension/popup/index.tsx +24 -0
- package/extension/popup/screens/AboutScreen.tsx +118 -0
- package/extension/popup/screens/HomeScreen.tailwind.css +85 -0
- package/extension/popup/screens/HomeScreen.tsx +902 -0
- package/extension/popup/screens/KeySettingsPasswordScreen.tsx +164 -0
- package/extension/popup/screens/LockTimeScreen.tsx +155 -0
- package/extension/popup/screens/ReceiveScreen.tsx +149 -0
- package/extension/popup/screens/RecoveryPhraseScreen.tsx +183 -0
- package/extension/popup/screens/SendReviewScreen.tsx +308 -0
- package/extension/popup/screens/SendScreen.tsx +825 -0
- package/extension/popup/screens/SendSubmittedScreen.tsx +193 -0
- package/extension/popup/screens/SettingsScreen.tsx +116 -0
- package/extension/popup/screens/ThemeSettingsScreen.tsx +107 -0
- package/extension/popup/screens/TransactionDetailsScreen.tsx +346 -0
- package/extension/popup/screens/ViewSecretPhraseScreen.tsx +212 -0
- package/extension/popup/screens/WalletPermissionsScreen.tsx +123 -0
- package/extension/popup/screens/WalletSettingsScreen.tsx +381 -0
- package/extension/popup/screens/WalletStylingScreen.tsx +306 -0
- package/extension/popup/screens/approvals/ConnectApprovalScreen.tsx +136 -0
- package/extension/popup/screens/approvals/SignMessageScreen.tsx +140 -0
- package/extension/popup/screens/approvals/SignRawTxScreen.tsx +320 -0
- package/extension/popup/screens/approvals/TransactionApprovalScreen.tsx +167 -0
- package/extension/popup/screens/onboarding/BackupScreen.tsx +254 -0
- package/extension/popup/screens/onboarding/CreateScreen.tsx +273 -0
- package/extension/popup/screens/onboarding/ImportScreen.tsx +676 -0
- package/extension/popup/screens/onboarding/ImportScreenV0.tsx +678 -0
- package/extension/popup/screens/onboarding/ImportSuccessScreen.tsx +236 -0
- package/extension/popup/screens/onboarding/ResumeBackupScreen.tsx +166 -0
- package/extension/popup/screens/onboarding/StartScreen.tsx +142 -0
- package/extension/popup/screens/onboarding/SuccessScreen.tsx +193 -0
- package/extension/popup/screens/onboarding/VerifyScreen.tsx +220 -0
- package/extension/popup/screens/system/LockedScreen.tsx +288 -0
- package/extension/popup/screens/transactions/ReceiveScreen.tsx +84 -0
- package/extension/popup/screens/transactions/SentScreen.tsx +138 -0
- package/extension/popup/store.ts +482 -0
- package/extension/popup/styles.css +246 -0
- package/extension/popup/utils/format.ts +58 -0
- package/extension/popup/utils/formatWalletError.ts +36 -0
- package/extension/popup/utils/memo.ts +299 -0
- package/extension/popup/utils/messaging.ts +16 -0
- package/extension/shared/address-encoding.ts +69 -0
- package/extension/shared/balance-query.ts +123 -0
- package/extension/shared/constants.ts +386 -0
- package/extension/shared/currency.ts +128 -0
- package/extension/shared/first-name-derivation.ts +128 -0
- package/extension/shared/keyfile.ts +58 -0
- package/extension/shared/onboarding.ts +78 -0
- package/extension/shared/price-api.ts +79 -0
- package/extension/shared/rpc-client-browser.ts +315 -0
- package/extension/shared/transaction-builder.ts +443 -0
- package/extension/shared/types.ts +450 -0
- package/extension/shared/utxo-diff.ts +212 -0
- package/extension/shared/utxo-store.ts +548 -0
- package/extension/shared/utxo-sync.ts +343 -0
- package/extension/shared/validators.ts +26 -0
- package/extension/shared/vault.ts +1580 -0
- package/extension/shared/wallet-crypto.ts +77 -0
- package/extension/shared/wasm-utils.ts +76 -0
- package/extension/shared/webcrypto.ts +67 -0
- package/extension/types/wasm.d.ts +13 -0
- package/package.json +39 -0
- package/postcss.config.js +6 -0
- package/rose-extension-dist.zip +0 -0
- package/sdk/README.md +88 -0
- package/sdk/examples/app.ts +166 -0
- package/sdk/examples/index.html +51 -0
- package/sdk/examples/tsconfig.json +15 -0
- package/sdk/examples/tx-builder.html +532 -0
- package/sdk/examples/tx-builder.ts +1766 -0
- package/sdk/package-lock.json +424 -0
- package/sdk/package.json +68 -0
- package/sdk/src/constants.ts +28 -0
- package/sdk/src/errors.ts +74 -0
- package/sdk/src/hooks/index.ts +1 -0
- package/sdk/src/hooks/use-rose.ts +94 -0
- package/sdk/src/index.ts +12 -0
- package/sdk/src/provider.ts +396 -0
- package/sdk/src/transaction.ts +163 -0
- package/sdk/src/types/rose-wasm.d.ts +14 -0
- package/sdk/src/types.ts +97 -0
- package/sdk/src/wasm.ts +13 -0
- package/sdk/tsconfig.json +20 -0
- package/sdk/vite.config.examples.ts +32 -0
- package/tailwind.config.ts +38 -0
- package/tsconfig.json +20 -0
- 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
|
+
}
|