This commit is contained in:
ekzyis 2024-06-17 02:59:51 -05:00
parent bb8c1ccffc
commit 34bfa89e74
4 changed files with 159 additions and 80 deletions

View File

@ -9,7 +9,7 @@ import { Status } from './webln'
export const isConfigured = status => [Status.Enabled, Status.Locked, Status.Error, true].includes(status) export const isConfigured = status => [Status.Enabled, Status.Locked, Status.Error, true].includes(status)
export function WalletCard ({ title, badges, provider, status }) { export function WalletCard ({ title, badges, provider, status, href }) {
const configured = isConfigured(status) const configured = isConfigured(status)
let indicator = styles.disabled let indicator = styles.disabled
switch (status) { switch (status) {
@ -42,14 +42,13 @@ export function WalletCard ({ title, badges, provider, status }) {
</Badge>)} </Badge>)}
</Card.Subtitle> </Card.Subtitle>
</Card.Body> </Card.Body>
{provider && <Link href={href}>
<Link href={`/settings/wallets/${provider}`}>
<Card.Footer className={styles.attach}> <Card.Footer className={styles.attach}>
{configured {configured
? <>configure<Gear width={14} height={14} /></> ? <>configure<Gear width={14} height={14} /></>
: <>attach<Plug width={14} height={14} /></>} : <>attach<Plug width={14} height={14} /></>}
</Card.Footer> </Card.Footer>
</Link>} </Link>
</Card> </Card>
) )
} }

View File

@ -0,0 +1,70 @@
import { WalletSecurityBanner } from './banners'
import { Form } from './form'
import { CenterLayout } from './layout'
export default function WalletConfigurator ({ config }) {
const initial = config.provider
return (
<CenterLayout>
<h2 className='pb-2'>{config.title}</h2>
<h6 className='text-muted text-center pb-3'>use {config.title} for payments</h6>
<WalletSecurityBanner />
<Form
initial={{
url: url || '',
adminKey: adminKey || '',
isDefault: isDefault || false
}}
schema={lnbitsSchema}
onSubmit={async ({ isDefault, ...values }) => {
try {
await saveConfig(values)
if (isDefault) setProvider(lnbits)
toaster.success('saved settings')
router.push('/settings/wallets')
} catch (err) {
console.error(err)
toaster.danger('failed to attach: ' + err.message || err.toString?.())
}
}}
>
<ClientInput
initialValue={url}
label='lnbits url'
name='url'
required
autoFocus
/>
<PasswordInput
initialValue={adminKey}
label='admin key'
name='adminKey'
newPass
required
/>
<ClientCheckbox
disabled={!configured || isDefault || enabledProviders.length === 1}
initialValue={isDefault}
label='default payment method'
name='isDefault'
/>
<WalletButtonBar
status={status} onDelete={async () => {
try {
await clearConfig()
toaster.success('saved settings')
router.push('/settings/wallets')
} catch (err) {
console.error(err)
toaster.danger('failed to detach: ' + err.message || err.toString?.())
}
}}
/>
</Form>
<div className='mt-3 w-100'>
<WalletLogs wallet={Wallet.LNbits} embedded />
</div>
</CenterLayout>
)
}

View File

@ -2,17 +2,26 @@ import { bolt11Tags } from '@/lib/bolt11'
export const name = 'LNbits' export const name = 'LNbits'
let config, logger export const config = {
provider: {
export function setConfig (_config) { url: {
config = _config label: 'lnbits url',
type: 'text'
},
adminKey: {
label: 'admin key',
type: 'password'
}
},
card: {
title: 'LNbits',
badges: ['send only', 'non-custodialish'],
href: '/settings/wallets/lnbits'
}
} }
export function setLogger (_logger) { export function getInfo ({ config, logger }) {
logger = _logger return async function () {
}
export async function getInfo () {
const response = await getWallet(config.url, config.adminKey) const response = await getWallet(config.url, config.adminKey)
return { return {
node: { node: {
@ -27,9 +36,11 @@ export async function getInfo () {
version: '1.0', version: '1.0',
supports: ['lightning'] supports: ['lightning']
} }
}
} }
export async function sendPayment (bolt11) { export function sendPayment ({ config, logger }) {
return async function (bolt11) {
const { url, adminKey } = config const { url, adminKey } = config
const hash = bolt11Tags(bolt11).payment_hash const hash = bolt11Tags(bolt11).payment_hash
@ -50,9 +61,10 @@ export async function sendPayment (bolt11) {
logger.error('payment failed:', `payment_hash=${hash}`, err.message || err.toString?.()) logger.error('payment failed:', `payment_hash=${hash}`, err.message || err.toString?.())
throw err throw err
} }
}
} }
const getWallet = async (baseUrl, adminKey) => { async function getWallet (baseUrl, adminKey) {
const url = baseUrl.replace(/\/+$/, '') const url = baseUrl.replace(/\/+$/, '')
const path = '/api/v1/wallet' const path = '/api/v1/wallet'

View File

@ -2,28 +2,32 @@ import { getGetServerSideProps } from '@/api/ssrApollo'
import Layout from '@/components/layout' import Layout from '@/components/layout'
import styles from '@/styles/wallet.module.css' import styles from '@/styles/wallet.module.css'
import { WalletCard } from '@/components/wallet-card' import { WalletCard } from '@/components/wallet-card'
import { LightningAddressWalletCard } from './lightning-address' // import { LightningAddressWalletCard } from './lightning-address'
import { LNbitsCard } from './lnbits' // import { LNbitsCard } from './lnbits'
import { NWCCard } from './nwc' // import { NWCCard } from './nwc'
import { LNDCard } from './lnd' // import { LNDCard } from './lnd'
import { CLNCard } from './cln' // import { CLNCard } from './cln'
import { WALLETS } from '@/fragments/wallet' import { WALLETS } from '@/fragments/wallet'
import { useQuery } from '@apollo/client' // import { useQuery } from '@apollo/client'
import PageLoading from '@/components/page-loading' // import PageLoading from '@/components/page-loading'
import { LNCCard } from './lnc' // import { LNCCard } from './lnc'
import Link from 'next/link' import Link from 'next/link'
import { Wallet as W } from '@/lib/constants' // import { Wallet as W } from '@/lib/constants'
import { config as lnbitsConfig } from '@/components/webln/lnbits2'
// TODO: load configs without individual imports?
const walletConfigs = [lnbitsConfig]
export const getServerSideProps = getGetServerSideProps({ query: WALLETS, authRequired: true }) export const getServerSideProps = getGetServerSideProps({ query: WALLETS, authRequired: true })
export default function Wallet ({ ssrData }) { export default function Wallet ({ ssrData }) {
const { data } = useQuery(WALLETS) // const { data } = useQuery(WALLETS)
//
if (!data && !ssrData) return <PageLoading /> // if (!data && !ssrData) return <PageLoading />
const { wallets } = data || ssrData // const { wallets } = data || ssrData
const lnd = wallets.find(w => w.type === W.LND.type) // const lnd = wallets.find(w => w.type === W.LND.type)
const lnaddr = wallets.find(w => w.type === W.LnAddr.type) // const lnaddr = wallets.find(w => w.type === W.LnAddr.type)
const cln = wallets.find(w => w.type === W.CLN.type) // const cln = wallets.find(w => w.type === W.CLN.type)
return ( return (
<Layout> <Layout>
@ -36,15 +40,9 @@ export default function Wallet ({ ssrData }) {
</Link> </Link>
</div> </div>
<div className={styles.walletGrid}> <div className={styles.walletGrid}>
<LightningAddressWalletCard wallet={lnaddr} /> {walletConfigs.map((config, i) => (
<LNDCard wallet={lnd} /> <WalletCard key={i} {...config.card} />
<CLNCard wallet={cln} /> ))}
<LNbitsCard />
<NWCCard />
<LNCCard />
<WalletCard title='coming soon' badges={['probably']} />
<WalletCard title='coming soon' badges={['we hope']} />
<WalletCard title='coming soon' badges={['tm']} />
</div> </div>
</div> </div>
</Layout> </Layout>