remove multiple wallets + monero auto-open + agents rules
This commit is contained in:
@@ -2,3 +2,5 @@
|
|||||||
|
|
||||||
- Never commit changes unless explicitly told to do so. Always ask first or wait for the user's command.
|
- Never commit changes unless explicitly told to do so. Always ask first or wait for the user's command.
|
||||||
- Never manually edit `.router/router.ts` — sv-router auto-generates it from the filesystem. Just create the route file in the correct filesystem location.
|
- Never manually edit `.router/router.ts` — sv-router auto-generates it from the filesystem. Just create the route file in the correct filesystem location.
|
||||||
|
- Only commit when explicitly told to do so. When asked to commit, always write a single simple line commit message.
|
||||||
|
- At the end of every response, always surface a "Pending from you" section listing anything you need from the user (decisions, permissions, credentials, confirming a plan, etc.). If nothing is pending, say "Nothing pending."
|
||||||
|
|||||||
@@ -82,6 +82,10 @@ export const MoneroWallet = () => {
|
|||||||
await checkStatus()
|
await checkStatus()
|
||||||
}
|
}
|
||||||
await listWallets()
|
await listWallets()
|
||||||
|
if (wallets.length > 0) {
|
||||||
|
const pw = await moneroGetStoredPassword(wallets[0])
|
||||||
|
if (pw) await openExistingWallet(wallets[0], pw)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const logout = async () => {
|
const logout = async () => {
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export const XrpWallet = () => {
|
|||||||
)
|
)
|
||||||
if (walletList) {
|
if (walletList) {
|
||||||
wallets = walletList
|
wallets = walletList
|
||||||
if (walletList.length === 1 && !currentWalletId) {
|
if (walletList.length > 0 && !currentWalletId) {
|
||||||
currentWalletId = walletList[0].id
|
currentWalletId = walletList[0].id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,40 +269,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if xrpWallet.wallets.length > 1}
|
<div class="flex gap-3">
|
||||||
<Card>
|
|
||||||
<CardHeader class="pb-3">
|
|
||||||
<CardTitle class="text-sm">XRP Wallets</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div class="space-y-1">
|
|
||||||
{#each xrpWallet.wallets as wal}
|
|
||||||
<button
|
|
||||||
onclick={() => {
|
|
||||||
xrpWallet.selectAndUnlockWallet(wal.id)
|
|
||||||
navigate('/xrp')
|
|
||||||
}}
|
|
||||||
class="flex w-full items-center gap-3 rounded-lg p-2 text-left hover:bg-muted transition-colors">
|
|
||||||
<WalletIcon size={16} class="shrink-0 text-muted-foreground" />
|
|
||||||
<div class="flex-1 min-w-0">
|
|
||||||
<p class="text-sm font-medium">{wal.name}</p>
|
|
||||||
<p class="text-xs text-muted-foreground truncate font-mono">{wal.address}</p>
|
|
||||||
</div>
|
|
||||||
{#if xrpBalances[wal.address]?.funded === false}
|
|
||||||
<span class="text-xs text-muted-foreground">unfunded</span>
|
|
||||||
{:else if xrpBalances[wal.address]}
|
|
||||||
<span class="font-mono text-sm tabular-nums">
|
|
||||||
{fmtBal(xrpBalances[wal.address].balance)}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="flex gap-3">
|
|
||||||
<Button
|
<Button
|
||||||
onclick={() => navigate('/xrp')}
|
onclick={() => navigate('/xrp')}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { moneroWallet } from '$lib/states/monero-wallet.svelte.js'
|
import { moneroWallet } from '$lib/states/monero-wallet.svelte.js'
|
||||||
import { session } from '$lib/states/session.svelte.js'
|
|
||||||
import { Button } from '$lib/components/ui/button/index.js'
|
import { Button } from '$lib/components/ui/button/index.js'
|
||||||
import { Textarea } from '$lib/components/ui/textarea/index.js'
|
import { Textarea } from '$lib/components/ui/textarea/index.js'
|
||||||
import { Input } from '$lib/components/ui/input/index.js'
|
import { Input } from '$lib/components/ui/input/index.js'
|
||||||
@@ -11,28 +10,21 @@
|
|||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from '$lib/components/ui/card/index.js'
|
} from '$lib/components/ui/card/index.js'
|
||||||
import Fingerprint from '@lucide/svelte/icons/fingerprint'
|
|
||||||
import Loader from '$lib/components/loader.svelte'
|
import Loader from '$lib/components/loader.svelte'
|
||||||
import { navigate } from 'sv-router/generated'
|
import { navigate } from 'sv-router/generated'
|
||||||
|
|
||||||
const w = moneroWallet
|
const w = moneroWallet
|
||||||
|
|
||||||
let moneroWalletName = $state('')
|
let moneroWalletName = $state('')
|
||||||
let moneroWalletPass = $state('')
|
|
||||||
let moneroMnemonic = $state('')
|
let moneroMnemonic = $state('')
|
||||||
let moneroRestoreHeight = $state<number | undefined>(undefined)
|
let moneroRestoreHeight = $state<number | undefined>(undefined)
|
||||||
let moneroSelectedWallet = $state('')
|
|
||||||
let moneroSelectedWalletPass = $state('')
|
|
||||||
let moneroUseBiometric = $state(false)
|
|
||||||
|
|
||||||
let initStarted = false
|
let initStarted = false
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (w.walletOpen && w.walletName) {
|
if (w.walletOpen && w.walletName) {
|
||||||
navigate('/monero/wallet/:name', {
|
navigate('/monero/wallet/:name', {
|
||||||
params: {
|
params: { name: w.walletName },
|
||||||
name: w.walletName,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -46,6 +38,12 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (w.running && !w.walletOpen && w.wallets.length > 0 && !w.loading) {
|
||||||
|
w.autoUnlock(w.wallets[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="mx-auto max-w-xl">
|
<div class="mx-auto max-w-xl">
|
||||||
@@ -101,162 +99,71 @@
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
{:else if !w.walletOpen}
|
{:else if !w.walletOpen}
|
||||||
<Card>
|
{#if w.wallets.length > 0}
|
||||||
<CardHeader>
|
<Card>
|
||||||
<CardTitle>Monero Wallet</CardTitle>
|
<CardContent class="flex items-center justify-center py-8">
|
||||||
<CardDescription>
|
<Loader />
|
||||||
{w.wallets.length > 0
|
<span class="ml-2 text-sm text-muted-foreground">
|
||||||
? `${w.wallets.length} wallet${w.wallets.length > 1 ? 's' : ''} found on disk`
|
Opening wallet...
|
||||||
: 'No existing wallets found'}
|
</span>
|
||||||
</CardDescription>
|
</CardContent>
|
||||||
</CardHeader>
|
</Card>
|
||||||
<CardContent>
|
{:else}
|
||||||
<div class="flex flex-col gap-3">
|
<Card>
|
||||||
{#if w.wallets.length > 0}
|
<CardHeader>
|
||||||
<p class="text-xs font-medium">
|
<CardTitle>Monero Wallet</CardTitle>
|
||||||
Select a wallet to open:
|
<CardDescription>
|
||||||
|
Create a new wallet or restore from seed
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<p class="text-xs text-muted-foreground">
|
||||||
|
Create a new wallet:
|
||||||
</p>
|
</p>
|
||||||
<div class="flex flex-wrap gap-2">
|
|
||||||
{#each w.wallets as name}
|
|
||||||
<Button
|
|
||||||
variant={moneroSelectedWallet === name
|
|
||||||
? 'default'
|
|
||||||
: 'outline'}
|
|
||||||
onclick={() => {
|
|
||||||
moneroSelectedWallet = name
|
|
||||||
moneroSelectedWalletPass = ''
|
|
||||||
}}>
|
|
||||||
{name}
|
|
||||||
</Button>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
{#if moneroSelectedWallet}
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
{#if session.unlocked}
|
|
||||||
<Button
|
|
||||||
onclick={() =>
|
|
||||||
w.autoUnlock(
|
|
||||||
moneroSelectedWallet,
|
|
||||||
)}
|
|
||||||
disabled={w.loading}>
|
|
||||||
{#if w.loading}
|
|
||||||
<Loader />
|
|
||||||
{/if}
|
|
||||||
Open
|
|
||||||
</Button>
|
|
||||||
{:else if w.biometricAvailable}
|
|
||||||
<Button
|
|
||||||
onclick={async () => {
|
|
||||||
const ok = await w.biometricAuth()
|
|
||||||
if (ok) {
|
|
||||||
await w.openExistingWallet(
|
|
||||||
moneroSelectedWallet,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
disabled={w.loading}>
|
|
||||||
<Fingerprint size={14} />
|
|
||||||
Open with Touch ID
|
|
||||||
</Button>
|
|
||||||
{/if}
|
|
||||||
<div class="flex gap-2 items-end">
|
|
||||||
<Input
|
|
||||||
type="password"
|
|
||||||
placeholder="Enter password"
|
|
||||||
bind:value={moneroSelectedWalletPass} />
|
|
||||||
<Button
|
|
||||||
onclick={() =>
|
|
||||||
w.openExistingWallet(
|
|
||||||
moneroSelectedWallet,
|
|
||||||
moneroSelectedWalletPass,
|
|
||||||
)}
|
|
||||||
disabled={w.loading ||
|
|
||||||
!moneroSelectedWalletPass}>
|
|
||||||
Open
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<hr class="border-muted" />
|
|
||||||
{/if}
|
|
||||||
<p class="text-xs text-muted-foreground">
|
|
||||||
Or create a new wallet:
|
|
||||||
</p>
|
|
||||||
<Input
|
|
||||||
placeholder="Wallet name"
|
|
||||||
bind:value={moneroWalletName} />
|
|
||||||
{#if w.biometricAvailable}
|
|
||||||
<label
|
|
||||||
class="flex items-center gap-2 text-xs cursor-pointer">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
bind:checked={moneroUseBiometric} />
|
|
||||||
Save password with Touch ID
|
|
||||||
</label>
|
|
||||||
{/if}
|
|
||||||
{#if !moneroUseBiometric}
|
|
||||||
<Input
|
<Input
|
||||||
type="password"
|
placeholder="Wallet name"
|
||||||
placeholder="Password"
|
bind:value={moneroWalletName} />
|
||||||
bind:value={moneroWalletPass} />
|
|
||||||
{/if}
|
|
||||||
<div class="flex gap-2">
|
|
||||||
<Button
|
<Button
|
||||||
onclick={async () => {
|
onclick={() =>
|
||||||
const pw = moneroUseBiometric
|
w.createWallet(
|
||||||
? crypto.randomUUID()
|
|
||||||
: moneroWalletPass
|
|
||||||
await w.createWallet(
|
|
||||||
moneroWalletName,
|
moneroWalletName,
|
||||||
pw,
|
crypto.randomUUID(),
|
||||||
moneroUseBiometric,
|
true,
|
||||||
)
|
)}
|
||||||
}}
|
disabled={w.loading || !moneroWalletName}>
|
||||||
disabled={w.loading ||
|
|
||||||
!moneroWalletName ||
|
|
||||||
(!moneroUseBiometric && !moneroWalletPass)}>
|
|
||||||
Create Wallet
|
Create Wallet
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
<hr class="border-muted" />
|
||||||
<hr class="border-muted" />
|
<p class="text-xs text-muted-foreground">
|
||||||
<p class="text-xs text-muted-foreground">
|
Restore from seed
|
||||||
Restore from seed
|
</p>
|
||||||
</p>
|
<Textarea
|
||||||
<Textarea
|
placeholder="Enter your Monero seed phrase (16 or 25 words)"
|
||||||
placeholder="Enter your Monero seed phrase (16 or 25 words)"
|
bind:value={moneroMnemonic} />
|
||||||
bind:value={moneroMnemonic} />
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
placeholder="Restore height (optional)"
|
|
||||||
bind:value={moneroRestoreHeight} />
|
|
||||||
{#if !moneroUseBiometric}
|
|
||||||
<Input
|
<Input
|
||||||
type="password"
|
type="number"
|
||||||
placeholder="Password"
|
placeholder="Restore height (optional)"
|
||||||
bind:value={moneroWalletPass} />
|
bind:value={moneroRestoreHeight} />
|
||||||
{/if}
|
<Button
|
||||||
<Button
|
onclick={() =>
|
||||||
onclick={async () => {
|
w.restoreWallet(
|
||||||
await w.restoreWallet(
|
moneroWalletName,
|
||||||
moneroWalletName,
|
crypto.randomUUID(),
|
||||||
moneroUseBiometric
|
moneroMnemonic,
|
||||||
? crypto.randomUUID()
|
moneroRestoreHeight,
|
||||||
: moneroWalletPass,
|
true,
|
||||||
moneroMnemonic,
|
)}
|
||||||
moneroRestoreHeight,
|
disabled={w.loading ||
|
||||||
moneroUseBiometric,
|
!moneroWalletName ||
|
||||||
)
|
!moneroMnemonic.trim()}>
|
||||||
}}
|
Restore Wallet
|
||||||
disabled={w.loading ||
|
</Button>
|
||||||
!moneroWalletName ||
|
</div>
|
||||||
(!moneroUseBiometric && !moneroWalletPass) ||
|
</CardContent>
|
||||||
!moneroMnemonic.trim()}>
|
</Card>
|
||||||
Restore Wallet
|
{/if}
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -9,14 +9,10 @@
|
|||||||
CardTitle,
|
CardTitle,
|
||||||
} from '$lib/components/ui/card/index.js'
|
} from '$lib/components/ui/card/index.js'
|
||||||
import { navigate } from 'sv-router/generated'
|
import { navigate } from 'sv-router/generated'
|
||||||
import ArrowLeft from '@lucide/svelte/icons/arrow-left'
|
|
||||||
import Trash2 from '@lucide/svelte/icons/trash-2'
|
|
||||||
import WalletIcon from '@lucide/svelte/icons/wallet'
|
|
||||||
|
|
||||||
const w = xrpWallet
|
const w = xrpWallet
|
||||||
let confirm = $state(false)
|
let confirm = $state(false)
|
||||||
let resetting = $state(false)
|
let resetting = $state(false)
|
||||||
let deletingWalletId = $state<string | null>(null)
|
|
||||||
|
|
||||||
async function handleReset() {
|
async function handleReset() {
|
||||||
resetting = true
|
resetting = true
|
||||||
@@ -25,84 +21,39 @@
|
|||||||
resetting = false
|
resetting = false
|
||||||
confirm = false
|
confirm = false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleDeleteWallet(id: string) {
|
|
||||||
await w.deleteWallet(id)
|
|
||||||
deletingWalletId = null
|
|
||||||
if (w.wallets.length === 0) navigate('/xrp')
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="mx-auto max-w-xl">
|
<div class="mx-auto max-w-xl">
|
||||||
<div class="flex flex-col gap-4">
|
<Card>
|
||||||
{#if w.wallets.length > 0}
|
<CardHeader>
|
||||||
<Card>
|
<CardTitle>Settings</CardTitle>
|
||||||
<CardHeader>
|
<CardDescription>App preferences and data management</CardDescription>
|
||||||
<CardTitle>Wallets</CardTitle>
|
</CardHeader>
|
||||||
<CardDescription>Manage your XRP wallets</CardDescription>
|
<CardContent class="space-y-4">
|
||||||
</CardHeader>
|
<div>
|
||||||
<CardContent>
|
<p class="font-medium text-xs">Reset App</p>
|
||||||
<div class="flex flex-col gap-2">
|
<p class="text-muted-foreground text-xs mt-1">
|
||||||
{#each w.wallets as wal}
|
Removes all wallets and seeds from the keychain. You can
|
||||||
<div class="flex items-center gap-3 rounded-md border border-input p-3">
|
then set up the wallet fresh.
|
||||||
<WalletIcon size={18} class="shrink-0 text-muted-foreground" />
|
</p>
|
||||||
<div class="flex-1 min-w-0">
|
<div class="mt-3">
|
||||||
<p class="font-medium text-sm">{wal.name}</p>
|
{#if confirm}
|
||||||
<p class="text-xs text-muted-foreground truncate font-mono">
|
<div class="flex gap-2 items-center">
|
||||||
{wal.address}
|
<p class="text-xs text-red-500">Are you sure?</p>
|
||||||
</p>
|
<Button size="sm" variant="destructive" onclick={handleReset} disabled={resetting}>
|
||||||
</div>
|
{resetting ? 'Resetting...' : 'Yes, reset everything'}
|
||||||
{#if deletingWalletId === wal.id}
|
|
||||||
<div class="flex items-center gap-1.5">
|
|
||||||
<Button size="sm" variant="destructive" onclick={() => handleDeleteWallet(wal.id)}>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
<Button size="sm" variant="outline" onclick={() => (deletingWalletId = null)}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<Button size="sm" variant="outline" onclick={() => (deletingWalletId = wal.id)}>
|
|
||||||
<Trash2 size={14} />
|
|
||||||
</Button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
{/if}
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Settings</CardTitle>
|
|
||||||
<CardDescription>App preferences and data management</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent class="space-y-4">
|
|
||||||
<div>
|
|
||||||
<p class="font-medium text-xs">Reset App</p>
|
|
||||||
<p class="text-muted-foreground text-xs mt-1">
|
|
||||||
Removes all XRP wallets and seeds from the keychain. You
|
|
||||||
can then set up the wallet fresh.
|
|
||||||
</p>
|
|
||||||
<div class="mt-3">
|
|
||||||
{#if confirm}
|
|
||||||
<div class="flex gap-2 items-center">
|
|
||||||
<p class="text-xs text-red-500">Are you sure?</p>
|
|
||||||
<Button size="sm" variant="destructive" onclick={handleReset} disabled={resetting}>
|
|
||||||
{resetting ? 'Resetting...' : 'Yes, reset everything'}
|
|
||||||
</Button>
|
|
||||||
<Button size="sm" variant="outline" onclick={() => (confirm = false)}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<Button variant="outline" onclick={() => (confirm = true)}>
|
|
||||||
Reset App
|
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
<Button size="sm" variant="outline" onclick={() => (confirm = false)}>
|
||||||
</div>
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<Button variant="outline" onclick={() => (confirm = true)}>
|
||||||
|
Reset App
|
||||||
|
</Button>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</div>
|
||||||
</Card>
|
</CardContent>
|
||||||
</div>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { xrpWallet } from '$lib/states/xrp-wallet.svelte.js'
|
import { xrpWallet } from '$lib/states/xrp-wallet.svelte.js'
|
||||||
import { session } from '$lib/states/session.svelte.js'
|
|
||||||
import { Button } from '$lib/components/ui/button/index.js'
|
import { Button } from '$lib/components/ui/button/index.js'
|
||||||
import { Input } from '$lib/components/ui/input/index.js'
|
import { Input } from '$lib/components/ui/input/index.js'
|
||||||
import { Textarea } from '$lib/components/ui/textarea/index.js'
|
import { Textarea } from '$lib/components/ui/textarea/index.js'
|
||||||
@@ -12,9 +11,6 @@
|
|||||||
CardTitle,
|
CardTitle,
|
||||||
} from '$lib/components/ui/card/index.js'
|
} from '$lib/components/ui/card/index.js'
|
||||||
import Fingerprint from '@lucide/svelte/icons/fingerprint'
|
import Fingerprint from '@lucide/svelte/icons/fingerprint'
|
||||||
import LockKeyhole from '@lucide/svelte/icons/lock-keyhole'
|
|
||||||
import Plus from '@lucide/svelte/icons/plus'
|
|
||||||
import WalletIcon from '@lucide/svelte/icons/wallet'
|
|
||||||
import Loader from '$lib/components/loader.svelte'
|
import Loader from '$lib/components/loader.svelte'
|
||||||
import { navigate } from 'sv-router/generated'
|
import { navigate } from 'sv-router/generated'
|
||||||
|
|
||||||
@@ -24,7 +20,6 @@
|
|||||||
let inputSeed = $state('')
|
let inputSeed = $state('')
|
||||||
let inputPassword = $state('')
|
let inputPassword = $state('')
|
||||||
let inputUnlockPassword = $state('')
|
let inputUnlockPassword = $state('')
|
||||||
let showCreateForm = $state(false)
|
|
||||||
let newSeed = $state<string | null>(null)
|
let newSeed = $state<string | null>(null)
|
||||||
|
|
||||||
let initStarted = false
|
let initStarted = false
|
||||||
@@ -108,12 +103,10 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
{:else if w.wallets.length === 0 || showCreateForm}
|
{:else if w.wallets.length === 0}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>
|
<CardTitle>Create / Import Wallet</CardTitle>
|
||||||
{showCreateForm ? 'Add Another Wallet' : 'Create / Import Wallet'}
|
|
||||||
</CardTitle>
|
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Generate a new XRP wallet or import an existing seed
|
Generate a new XRP wallet or import an existing seed
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
@@ -139,77 +132,20 @@
|
|||||||
type="password"
|
type="password"
|
||||||
placeholder="Set a password (optional)"
|
placeholder="Set a password (optional)"
|
||||||
bind:value={inputPassword} />
|
bind:value={inputPassword} />
|
||||||
<div class="flex gap-2">
|
<Button
|
||||||
<Button
|
variant="outline"
|
||||||
variant="outline"
|
onclick={handleImport}
|
||||||
onclick={handleImport}
|
disabled={w.loading ||
|
||||||
disabled={w.loading ||
|
!inputSeed.trim() ||
|
||||||
!inputSeed.trim() ||
|
!inputWalletName.trim()}>
|
||||||
!inputWalletName.trim()}>
|
{w.loading ? 'Importing...' : 'Import Wallet'}
|
||||||
{w.loading ? 'Importing...' : 'Import Wallet'}
|
</Button>
|
||||||
</Button>
|
|
||||||
{#if showCreateForm}
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
onclick={() => (showCreateForm = false)}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{#if w.error}
|
{#if w.error}
|
||||||
<p class="mt-3 text-xs text-red-500">{w.error}</p>
|
<p class="mt-3 text-xs text-red-500">{w.error}</p>
|
||||||
{/if}
|
{/if}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
{:else if !w.currentWalletId}
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle>Wallets</CardTitle>
|
|
||||||
<CardDescription>Select a wallet to use</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
{#each w.wallets as wal}
|
|
||||||
<button
|
|
||||||
onclick={async () => {
|
|
||||||
if (session.unlocked) {
|
|
||||||
await w.autoUnlock(wal.id)
|
|
||||||
} else if (wal.hasPassword) {
|
|
||||||
await w.selectWallet(wal.id)
|
|
||||||
} else {
|
|
||||||
await w.selectAndUnlockWallet(wal.id)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
class="flex w-full cursor-pointer items-center gap-3 rounded-md border border-input p-3 text-left hover:bg-muted transition-colors">
|
|
||||||
<WalletIcon
|
|
||||||
size={20}
|
|
||||||
class="shrink-0 text-muted-foreground" />
|
|
||||||
<div class="flex-1 min-w-0">
|
|
||||||
<p class="font-medium text-sm">{wal.name}</p>
|
|
||||||
<p class="text-xs text-muted-foreground truncate font-mono">
|
|
||||||
{wal.address}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
{#if wal.hasPassword}
|
|
||||||
<LockKeyhole
|
|
||||||
size={14}
|
|
||||||
class="text-muted-foreground" />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
{/each}
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
onclick={() => (showCreateForm = true)}
|
|
||||||
class="mt-2">
|
|
||||||
<Plus size={16} />
|
|
||||||
Add Wallet
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
{:else if w.isLocked}
|
{:else if w.isLocked}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
@@ -254,11 +190,6 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
onclick={() => w.clearSelection()}>
|
|
||||||
Pick another wallet
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
{#if w.error}
|
{#if w.error}
|
||||||
<p class="mt-3 text-xs text-red-500">{w.error}</p>
|
<p class="mt-3 text-xs text-red-500">{w.error}</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user