Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion extension/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
req.notes.forEach(assertNativeNote);
const forPopup = {
...req,
notes: req.notes.map((n) => noteToProtobuf(n as Note)),
notes: req.notes.map(n => noteToProtobuf(n as Note)),
};
sendResponse(forPopup);
} else {
Expand Down
2 changes: 1 addition & 1 deletion extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"permissions": ["storage", "alarms"],
"content_security_policy": {
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'"
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'; font-src 'self' https://cdn.jsdelivr.net"
},
"content_scripts": [
{
Expand Down
5 changes: 3 additions & 2 deletions extension/popup/components/icons/ChevronDownIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

interface IconProps {
className?: string;
style?: React.CSSProperties;
}

export function ChevronDownIcon({ className = 'w-5 h-5' }: IconProps) {
export function ChevronDownIcon({ className = 'w-5 h-5', style }: IconProps) {
return (
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg className={className} style={style} fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
);
Expand Down
5 changes: 1 addition & 4 deletions extension/popup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ import { createRoot } from 'react-dom/client';
import { Popup } from './Popup';
import { ThemeProvider } from './contexts/ThemeContext';

import './styles.css';

import '@fontsource/lora/400.css';
import '@fontsource/lora/500.css';
import '@fontsource/lora/600.css';
import '@fontsource/inter/400.css';
import '@fontsource/inter/500.css';
import './styles.css';

const root = document.getElementById('root');
if (root) {
Expand Down
6 changes: 3 additions & 3 deletions extension/popup/screens/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ReceiveArrowIcon } from '../components/icons/ReceiveArrowIcon';
import { SentArrowIcon } from '../components/icons/SentArrowIcon';
import { ArrowUpRightIcon } from '../components/icons/ArrowUpRightIcon';

import WalletDropdownArrow from '../assets/wallet-dropdown-arrow.svg';
import { ChevronDownIcon } from '../components/icons/ChevronDownIcon';
import LockIconAsset from '../assets/lock-icon.svg';
import SettingsIconAsset from '../assets/settings-icon.svg';
import TrendUpArrow from '../assets/trend-up-arrow.svg';
Expand Down Expand Up @@ -368,7 +368,7 @@ export function HomeScreen() {
style={{ color: 'var(--color-text-primary)' }}
>
{walletName}
<img src={WalletDropdownArrow} alt="" className="h-3 w-3" />
<ChevronDownIcon className="h-3 w-3 shrink-0" />
</div>
<div
className="font-sans text-[13px] leading-[18px] tracking-[0.26px] flex items-center gap-2"
Expand Down Expand Up @@ -750,7 +750,7 @@ export function HomeScreen() {
{group.items.map((t, i) => (
<button
key={i}
className="w-full flex items-start gap-3 py-3 rounded-lg px-0 -mx-0 overflow-hidden"
className="w-full flex items-center gap-3 py-3 rounded-lg px-0 -mx-0 overflow-hidden"
onClick={() => {
setSelectedTransaction(t.originalTx);
navigate('tx-details');
Expand Down
242 changes: 124 additions & 118 deletions extension/popup/screens/SendReviewScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { truncateAddress } from '../utils/format';
import { AccountIcon } from '../components/AccountIcon';
import { send } from '../utils/messaging';
import { INTERNAL_METHODS } from '../../shared/constants';
import { nockToNick, formatNock, formatNick } from '../../shared/currency';
import { formatNock, nockToNick } from '../../shared/currency';
import { ChevronLeftIcon } from '../components/icons/ChevronLeftIcon';
import { ChevronRightIcon } from '../components/icons/ChevronRightIcon';
import IrisLogo40 from '../assets/iris-logo-40.svg';
import IrisLogoBlue from '../assets/iris-logo-blue.svg';

export function SendReviewScreen() {
const { navigate, wallet, lastTransaction, priceUsd } = useStore();
Expand All @@ -21,17 +23,18 @@ export function SendReviewScreen() {

// Format amounts for display
const amount = formatNock(lastTransaction.amount);
const amountInNicks = nockToNick(lastTransaction.amount);
const feeInNocks = formatNock(lastTransaction.fee);
const feeInNicks = nockToNick(lastTransaction.fee);
const total = formatNock(lastTransaction.amount + lastTransaction.fee);
const totalInNicks = nockToNick(lastTransaction.amount + lastTransaction.fee);
const remainingBalance = formatNock(
wallet.balance - lastTransaction.amount - lastTransaction.fee
);
const fromAddress = truncateAddress(lastTransaction.from);
const toAddress = truncateAddress(lastTransaction.to);

// Resolve recipient: internal account name or "Receiving address"
const recipientAccount = wallet.accounts?.find(
acc => acc.address.toLowerCase() === (lastTransaction.to || '').toLowerCase()
);
const recipientLabel = recipientAccount?.name ?? 'Receiving address';

const usdValue = lastTransaction.amount * (priceUsd || 0);

const [isSending, setIsSending] = useState(false);
const [error, setError] = useState('');

Expand Down Expand Up @@ -116,7 +119,9 @@ export function SendReviewScreen() {
>
<ChevronLeftIcon className="w-5 h-5" />
</button>
<h1 className="m-0 text-base font-medium leading-[22px] tracking-[0.16px]">Review</h1>
<h1 className="m-0 text-base font-medium leading-[22px] tracking-[0.16px]">
Review Transfer
</h1>
<div className="w-8 h-8" />
</header>

Expand All @@ -126,114 +131,117 @@ export function SendReviewScreen() {
style={{ backgroundColor: 'var(--color-bg)' }}
>
<div className="flex flex-col gap-8 px-4 py-2">
{/* Amount Section */}
{/* Amount Section - Figma: logo, amount, USD */}
<div className="flex flex-col items-center gap-3 w-full">
<div
className="w-10 h-10 rounded-lg grid place-items-center"
style={{ backgroundColor: 'var(--color-surface-800)' }}
>
<AccountIcon
styleId={currentAccount?.iconStyleId}
color={currentAccount?.iconColor}
className="w-6 h-6"
/>
</div>
<img src={IrisLogo40} alt="" className="w-10 h-10 shrink-0" />
<div className="flex flex-col items-center gap-0.5 w-full text-center">
<h2 className="m-0 font-[Lora] text-[36px] font-semibold leading-10 tracking-[-0.72px]">
<h2 className="m-0 font-display text-[36px] font-semibold leading-10 tracking-[-0.72px]">
{amount} <span style={{ color: 'var(--color-text-muted)' }}>NOCK</span>
</h2>
<p
className="m-0 text-[10px] leading-3 tracking-[0.02em]"
style={{ color: 'var(--color-text-muted)' }}
className="m-0 text-[13px] leading-[18px] tracking-[0.26px]"
style={{ color: 'var(--color-text-primary)' }}
>
{formatNick(amountInNicks)} nicks
{usdValue > 0
? `$${usdValue.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
: '—'}
</p>
</div>
</div>

{/* Details */}
{/* Wallet cards with circular middle - Figma layout */}
<div className="flex flex-col gap-2 w-full">
{/* From/To */}
<div
className="rounded-lg p-3 flex items-center gap-2.5"
style={{ backgroundColor: 'var(--color-surface-800)' }}
>
<div className="flex-1 flex flex-col gap-1 min-w-0">
<div className="text-sm font-medium leading-[18px] tracking-[0.14px]">From</div>
<div
className="text-[13px] leading-[18px] tracking-[0.26px] truncate"
style={{ color: 'var(--color-text-muted)' }}
>
{fromAddress}
</div>
</div>
<div className="p-1 shrink-0">
<ChevronRightIcon className="w-4 h-4" />
</div>
<div className="flex-1 flex flex-col gap-1 min-w-0">
<div className="text-sm font-medium leading-[18px] tracking-[0.14px]">To</div>
<div className="relative flex gap-2 items-stretch w-full">
{/* Sender card */}
<div
className="flex-1 min-w-0 self-stretch p-3 rounded-xl flex flex-col justify-center items-start gap-2.5"
style={{ backgroundColor: 'var(--color-surface-900)' }}
>
<div
className="text-[13px] leading-[18px] tracking-[0.26px] truncate"
style={{ color: 'var(--color-text-muted)' }}
className="w-10 h-10 relative rounded-[32px] flex items-center justify-center shrink-0 overflow-hidden"
style={{ backgroundColor: 'var(--color-bg)' }}
>
{toAddress}
<AccountIcon
styleId={currentAccount?.iconStyleId}
color={currentAccount?.iconColor}
className="w-6 h-6"
/>
</div>
</div>
</div>

{/* Network fee & Total */}
<div className="rounded-lg p-3" style={{ backgroundColor: 'var(--color-surface-800)' }}>
<div className="flex flex-col gap-2.5 w-full">
{/* Fee row */}
<div className="flex items-center justify-between w-full">
<div className="text-sm font-medium leading-[18px] tracking-[0.14px]">
Network fee
<div className="self-stretch flex flex-col justify-center items-start gap-0.5 min-w-0">
<div
className="text-sm font-medium leading-4 tracking-tight truncate"
style={{ color: 'var(--color-text-primary)' }}
>
{currentAccount?.name ?? 'Wallet'}
</div>
<div className="flex flex-col items-end">
<div className="text-sm font-medium leading-[18px] tracking-[0.14px]">
{feeInNocks} NOCK
</div>
<div
className="text-[10px] leading-3 tracking-[0.02em]"
style={{ color: 'var(--color-text-muted)' }}
>
{formatNick(feeInNicks)} nicks
</div>
<div
className="text-xs font-normal leading-4 tracking-tight truncate"
style={{ color: 'var(--color-text-muted)' }}
>
{fromAddress}
</div>
</div>
</div>

{/* Divider */}
<div
className="w-full h-px"
style={{ backgroundColor: 'var(--color-surface-700)' }}
/>
{/* Circular middle element - "weird circle" from Figma */}
<div
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10 w-14 h-14 rounded-full flex items-center justify-center shrink-0 p-2"
style={{
backgroundColor: 'var(--color-bg)',
border: '8px solid var(--color-surface-900)',
color: 'var(--color-text-primary)',
}}
>
<ChevronRightIcon className="w-6 h-6 shrink-0" />
</div>

{/* Total row */}
<div className="flex items-center justify-between w-full">
<div className="text-sm font-semibold leading-[18px] tracking-[0.14px]">
Total
{/* Receiver card */}
<div
className="flex-1 min-w-0 self-stretch p-3 rounded-xl flex flex-col justify-center items-end gap-2.5"
style={{ backgroundColor: 'var(--color-surface-900)' }}
>
<div
className="w-10 h-10 relative rounded-[32px] flex items-center justify-center shrink-0 overflow-hidden"
style={{ backgroundColor: 'var(--color-bg)' }}
>
{recipientAccount ? (
<AccountIcon
styleId={recipientAccount.iconStyleId}
color={recipientAccount.iconColor}
className="w-6 h-6"
/>
) : (
<img src={IrisLogoBlue} alt="" className="w-6 h-6" />
)}
</div>
<div className="self-stretch flex flex-col justify-center items-end gap-0.5 min-w-0">
<div
className="text-sm font-medium leading-4 tracking-tight truncate"
style={{ color: 'var(--color-text-primary)' }}
>
{recipientLabel}
</div>
<div className="flex flex-col items-end">
<div className="text-sm font-semibold leading-[18px] tracking-[0.14px]">
{total} NOCK
</div>
<div
className="text-[10px] leading-3 tracking-[0.02em]"
style={{ color: 'var(--color-text-muted)' }}
>
{formatNick(totalInNicks)} nicks
</div>
<div
className="text-xs font-normal leading-4 tracking-tight truncate"
style={{ color: 'var(--color-text-muted)' }}
>
{toAddress}
</div>
</div>
</div>
</div>

{/* Remaining balance */}
{/* Network fee - single row per Figma */}
<div
className="text-center text-[12px] leading-4 font-medium tracking-[0.02em] mt-3"
style={{ color: 'var(--color-text-muted)' }}
className="rounded-lg px-3 py-5 flex items-center justify-between w-full"
style={{ backgroundColor: 'var(--color-surface-900)' }}
>
Balance after: {remainingBalance} NOCK
<div className="text-sm font-medium leading-[18px] tracking-[0.14px]">
Network fee
</div>
<div className="text-sm font-medium leading-[18px] tracking-[0.14px]">
{feeInNocks} NOCK
</div>
</div>
</div>

Expand Down Expand Up @@ -269,37 +277,35 @@ export function SendReviewScreen() {
</div>
)} */}

{/* Actions */}
{/* Actions - Figma: gap-12, rounded-8 */}
<div
className="flex flex-col gap-2 px-4 py-3"
className="flex gap-3 px-4 py-3 shrink-0"
style={{ borderTop: '1px solid var(--color-divider)' }}
>
<div className="flex gap-3">
<button
type="button"
onClick={handleCancel}
className="flex-1 h-12 inline-flex items-center justify-center rounded-lg text-sm font-medium leading-[18px] tracking-[0.14px] transition-opacity focus:outline-none focus-visible:ring-2"
style={{
backgroundColor: 'var(--color-surface-800)',
color: 'var(--color-text-primary)',
}}
onMouseEnter={e => (e.currentTarget.style.opacity = '0.9')}
onMouseLeave={e => (e.currentTarget.style.opacity = '1')}
>
Cancel
</button>
<button
type="button"
onClick={handleSend}
disabled={isSending}
className="flex-1 h-12 inline-flex items-center justify-center rounded-lg text-sm font-medium leading-[18px] tracking-[0.14px] transition-opacity focus:outline-none focus-visible:ring-2"
style={{ backgroundColor: 'var(--color-primary)', color: '#000' }}
onMouseEnter={e => (e.currentTarget.style.opacity = '0.9')}
onMouseLeave={e => (e.currentTarget.style.opacity = '1')}
>
{isSending ? 'Sending...' : 'Send'}
</button>
</div>
<button
type="button"
onClick={handleCancel}
className="flex-1 h-12 inline-flex items-center justify-center rounded-lg text-sm font-medium leading-[18px] tracking-[0.14px] transition-opacity focus:outline-none focus-visible:ring-2"
style={{
backgroundColor: 'var(--color-surface-800)',
color: 'var(--color-text-primary)',
}}
onMouseEnter={e => (e.currentTarget.style.opacity = '0.9')}
onMouseLeave={e => (e.currentTarget.style.opacity = '1')}
>
Cancel
</button>
<button
type="button"
onClick={handleSend}
disabled={isSending}
className="flex-1 h-12 inline-flex items-center justify-center rounded-lg text-sm font-medium leading-[18px] tracking-[0.14px] transition-opacity focus:outline-none focus-visible:ring-2"
style={{ backgroundColor: 'var(--color-primary)', color: '#000' }}
onMouseEnter={e => (e.currentTarget.style.opacity = '0.9')}
onMouseLeave={e => (e.currentTarget.style.opacity = '1')}
>
{isSending ? 'Sending...' : 'Send'}
</button>
</div>
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion extension/popup/screens/SendScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,8 @@ export function SendScreen() {
</div>
{accounts.length > 1 && (
<ChevronDownIcon
className={`w-4 h-4 transition-transform ${walletDropdownOpen ? 'rotate-180' : ''}`}
className={`w-4 h-4 shrink-0 transition-transform ${walletDropdownOpen ? 'rotate-180' : ''}`}
style={{ color: 'var(--color-text-primary)' }}
/>
)}
</button>
Expand Down
Loading