diff --git a/app/vibenet/faucet/page.tsx b/app/vibenet/faucet/page.tsx index 1dce1f8..4302946 100644 --- a/app/vibenet/faucet/page.tsx +++ b/app/vibenet/faucet/page.tsx @@ -1,7 +1,7 @@ 'use client'; -import { useCallback, useEffect, useState } from 'react'; -import type { ChangeEvent, FormEvent, MouseEvent, ReactNode } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import type { FormEvent, MouseEvent, ReactNode } from 'react'; import Link from 'next/link'; @@ -14,11 +14,14 @@ import { cn } from '../../components/ui/cn'; import { Text } from '../../components/ui/Text'; import { ExplorerLink } from '../components/ExplorerLink'; import { FAUCET_TOKENS, faucetTokenLabel } from '../data/faucetTokens'; +import { AddressAutocomplete } from '../demos/_shared/AddressAutocomplete'; +import { useAccounts } from '../demos/account/useAccounts'; import type { FaucetStatusResponse } from '../library/api-types'; import { vibenetApi, VibenetApiError } from '../library/client'; import { VIBENET_EXPLORER_PATH } from '../library/config'; import { isAddress, shortAddress } from '../library/format'; import type { DripState, FaucetTokenId } from '../library/types'; +import { defaultFaucetRecipient } from './recipient'; const RESULT_CLASSES: Record = { idle: '', @@ -38,12 +41,24 @@ function dripErrorMessage(err: unknown): string { } export default function FaucetPage() { + const { accounts, activeAccountId, hydrated } = useAccounts(); const [status, setStatus] = useState(null); const [statusError, setStatusError] = useState(null); - const [address, setAddress] = useState(''); + const [addressOverride, setAddressOverride] = useState(null); const [busy, setBusy] = useState(false); const [drip, setDrip] = useState({ phase: 'idle' }); + const addressBook = useMemo( + () => accounts.map(({ label, address }) => ({ label, address })), + [accounts], + ); + + // Start with the selected local demo account when one is available. Once the + // visitor types or pastes anything, their input takes precedence (including + // an intentionally blank field). + const address = + addressOverride ?? (hydrated ? defaultFaucetRecipient(accounts, activeAccountId) : null) ?? ''; + useEffect(() => { let cancelled = false; function load() { @@ -117,10 +132,6 @@ export default function FaucetPage() { [runDrip], ); - const handleAddressChange = useCallback((event: ChangeEvent) => { - setAddress(event.target.value); - }, []); - const validAddress = isAddress(address); let summaryBody: ReactNode; @@ -225,17 +236,14 @@ export default function FaucetPage() {
-
diff --git a/app/vibenet/faucet/recipient.test.ts b/app/vibenet/faucet/recipient.test.ts new file mode 100644 index 0000000..ea29985 --- /dev/null +++ b/app/vibenet/faucet/recipient.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from 'vitest'; + +import { defaultFaucetRecipient } from './recipient'; + +const accounts = [ + { id: 'first', address: '0x1111111111111111111111111111111111111111' }, + { id: 'active', address: '0x2222222222222222222222222222222222222222' }, +]; + +describe('defaultFaucetRecipient', () => { + it('uses the active saved account', () => { + expect(defaultFaucetRecipient(accounts, 'active')).toBe(accounts[1].address); + }); + + it('falls back to the first saved account when the active account is unavailable', () => { + expect(defaultFaucetRecipient(accounts, 'missing')).toBe(accounts[0].address); + }); + + it('returns null when there are no saved accounts', () => { + expect(defaultFaucetRecipient([], null)).toBeNull(); + }); +}); diff --git a/app/vibenet/faucet/recipient.ts b/app/vibenet/faucet/recipient.ts new file mode 100644 index 0000000..ccd000c --- /dev/null +++ b/app/vibenet/faucet/recipient.ts @@ -0,0 +1,9 @@ +import type { StoredAccount } from '../demos/account/library/model'; + +/** Prefer the account currently selected in the demos, then any saved account. */ +export function defaultFaucetRecipient( + accounts: Pick[], + activeAccountId: string | null, +): string | null { + return accounts.find((account) => account.id === activeAccountId)?.address ?? accounts[0]?.address ?? null; +}