Generate wallet resolver from fields
This commit is contained in:
parent
00f78daadc
commit
ba00c3d9fa
|
@ -6,7 +6,7 @@ import { decodeCursor, LIMIT, nextCursorEncoded } from '@/lib/cursor'
|
|||
import { SELECT, itemQueryWithMeta } from './item'
|
||||
import { lnAddrOptions } from '@/lib/lnurl'
|
||||
import { msatsToSats, msatsToSatsDecimal, ensureB64 } from '@/lib/format'
|
||||
import { CLNAutowithdrawSchema, LNDAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema } from '@/lib/validate'
|
||||
import { CLNAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema } from '@/lib/validate'
|
||||
import { ANON_BALANCE_LIMIT_MSATS, ANON_INV_PENDING_LIMIT, USER_ID, BALANCE_LIMIT_MSATS, INVOICE_RETENTION_DAYS, INV_PENDING_LIMIT, USER_IDS_BALANCE_NO_LIMIT, Wallet } from '@/lib/constants'
|
||||
import { datePivot } from '@/lib/time'
|
||||
import assertGofacYourself from './ofac'
|
||||
|
@ -14,6 +14,30 @@ import assertApiKeyNotPermitted from './apiKey'
|
|||
import { createInvoice as createInvoiceCLN } from '@/lib/cln'
|
||||
import { bolt11Tags } from '@/lib/bolt11'
|
||||
import { checkInvoice } from 'worker/wallet'
|
||||
import * as lnd from '@/components/wallet/lnd'
|
||||
|
||||
export const SERVER_WALLET_DEFS = [lnd]
|
||||
|
||||
function walletResolvers () {
|
||||
const resolvers = {}
|
||||
for (const {
|
||||
schema,
|
||||
server: { walletType, walletField, resolverName, testConnect }
|
||||
} of SERVER_WALLET_DEFS) {
|
||||
resolvers[resolverName] = async (parent, { settings, ...data }, { me, models }) => {
|
||||
return await upsertWallet({
|
||||
schema,
|
||||
wallet: { field: walletField, type: walletType },
|
||||
testConnect: (data) =>
|
||||
testConnect(
|
||||
data,
|
||||
{ me, models, addWalletLog, lnService: { authenticatedLndGrpc, createInvoice } }
|
||||
)
|
||||
}, { settings, data }, { me, models })
|
||||
}
|
||||
}
|
||||
return resolvers
|
||||
}
|
||||
|
||||
export async function getInvoice (parent, { id }, { me, models, lnd }) {
|
||||
const inv = await models.invoice.findUnique({
|
||||
|
@ -424,41 +448,7 @@ export default {
|
|||
}
|
||||
return { id }
|
||||
},
|
||||
upsertWalletLND: async (parent, { settings, ...data }, { me, models }) => {
|
||||
// make sure inputs are base64
|
||||
data.macaroon = ensureB64(data.macaroon)
|
||||
data.cert = ensureB64(data.cert)
|
||||
|
||||
const wallet = Wallet.LND
|
||||
return await upsertWallet(
|
||||
{
|
||||
schema: LNDAutowithdrawSchema,
|
||||
wallet,
|
||||
testConnect: async ({ cert, macaroon, socket }) => {
|
||||
try {
|
||||
const { lnd } = await authenticatedLndGrpc({
|
||||
cert,
|
||||
macaroon,
|
||||
socket
|
||||
})
|
||||
const inv = await createInvoice({
|
||||
description: 'SN connection test',
|
||||
lnd,
|
||||
tokens: 0,
|
||||
expires_at: new Date()
|
||||
})
|
||||
// we wrap both calls in one try/catch since connection attempts happen on RPC calls
|
||||
await addWalletLog({ wallet, level: 'SUCCESS', message: 'connected to LND' }, { me, models })
|
||||
return inv
|
||||
} catch (err) {
|
||||
// LND errors are in this shape: [code, type, { err: { code, details, metadata } }]
|
||||
const details = err[2]?.err?.details || err.message || err.toString?.()
|
||||
throw new Error(details)
|
||||
}
|
||||
}
|
||||
},
|
||||
{ settings, data }, { me, models })
|
||||
},
|
||||
...walletResolvers(),
|
||||
upsertWalletCLN: async (parent, { settings, ...data }, { me, models }) => {
|
||||
data.cert = ensureB64(data.cert)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { gql } from 'graphql-tag'
|
||||
import { SERVER_WALLET_DEFS } from '@/components/wallet'
|
||||
import { SERVER_WALLET_DEFS } from '@/api/resolvers/wallet'
|
||||
|
||||
function walletTypeDefs () {
|
||||
const typeDefs = SERVER_WALLET_DEFS.map(
|
||||
|
|
|
@ -16,8 +16,6 @@ import { autowithdrawInitial } from '../autowithdraw-shared'
|
|||
// wallet definitions
|
||||
export const WALLET_DEFS = [lnbits, nwc, lnc, lnd]
|
||||
|
||||
export const SERVER_WALLET_DEFS = WALLET_DEFS.filter(w => w.server)
|
||||
|
||||
export const Status = {
|
||||
Initialized: 'Initialized',
|
||||
Enabled: 'Enabled',
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import React from 'react'
|
||||
|
||||
import { ensureB64 } from '@/lib/format'
|
||||
import { datePivot } from '@/lib/time'
|
||||
import { LNDAutowithdrawSchema } from '@/lib/validate'
|
||||
|
||||
export const name = 'lnd'
|
||||
|
@ -28,7 +32,13 @@ export const fields = [
|
|||
label: 'cert',
|
||||
type: 'text',
|
||||
placeholder: 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNNVENDQWRpZ0F3SUJBZ0lRSHBFdFdrcGJwZHV4RVF2eVBPc3NWVEFLQmdncWhrak9QUVFEQWpBdk1SOHcKSFFZRFZRUUtFeFpzYm1RZ1lYVjBiMmRsYm1WeVlYUmxaQ0JqWlhKME1Rd3dDZ1lEVlFRREV3TmliMkl3SGhjTgpNalF3TVRBM01qQXhORE0wV2hjTk1qVXdNekF6TWpBeE5ETTBXakF2TVI4d0hRWURWUVFLRXhac2JtUWdZWFYwCmIyZGxibVZ5WVhSbFpDQmpaWEowTVF3d0NnWURWUVFERXdOaWIySXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak8KUFFNQkJ3TkNBQVJUS3NMVk5oZnhqb1FLVDlkVVdDbzUzSmQwTnBuL1BtYi9LUE02M1JxbU52dFYvdFk4NjJJZwpSbE41cmNHRnBEajhUeFc2OVhIK0pTcHpjWDdlN3N0Um80SFZNSUhTTUE0R0ExVWREd0VCL3dRRUF3SUNwREFUCkJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREFUQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVDAKMnh3V25GeHRUNzI0MWxwZlNoNm9FWi9UMWpCN0JnTlZIUkVFZERCeWdnTmliMktDQ1d4dlkyRnNhRzl6ZElJRApZbTlpZ2d4d2IyeGhjaTF1TVMxaWIyS0NGR2h2YzNRdVpHOWphMlZ5TG1sdWRHVnlibUZzZ2dSMWJtbDRnZ3AxCmJtbDRjR0ZqYTJWMGdnZGlkV1pqYjI1dWh3Ui9BQUFCaHhBQUFBQUFBQUFBQUFBQUFBQUFBQUFCaHdTc0VnQUQKTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUEwUTlkRXdoNXpPRnpwL3hYeHNpemh5SkxNVG5yazU1VWx1NHJPRwo4WW52QWlBVGt4U3p3Y3hZZnFscGx0UlNIbmd0NUJFcDBzcXlHL05nenBzb2pmMGNqQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K',
|
||||
optional: <>optional if from <a href='https://en.wikipedia.org/wiki/Certificate_authority' target='_blank' rel='noreferrer'>CA</a> (e.g. voltage)</>,
|
||||
// worker does not support JSX syntax
|
||||
optional: React.createElement(
|
||||
React.Fragment,
|
||||
{},
|
||||
'optional if from ',
|
||||
React.createElement('a', { href: 'https://en.wikipedia.org/wiki/Certificate_authority', target: '_blank', rel: 'noreferrer' }, 'CA'),
|
||||
' (e.g. voltage)'),
|
||||
clear: true
|
||||
}
|
||||
]
|
||||
|
@ -43,5 +53,58 @@ export const schema = LNDAutowithdrawSchema
|
|||
|
||||
export const server = {
|
||||
walletType: 'LND',
|
||||
resolverName: 'upsertWalletLND'
|
||||
walletField: 'walletLND',
|
||||
resolverName: 'upsertWalletLND',
|
||||
testConnect: async (
|
||||
{ cert, macaroon, socket },
|
||||
{ me, models, addWalletLog, lnService: { authenticatedLndGrpc, createInvoice } }
|
||||
) => {
|
||||
try {
|
||||
cert = ensureB64(cert)
|
||||
macaroon = ensureB64(macaroon)
|
||||
|
||||
const { lnd } = await authenticatedLndGrpc({
|
||||
cert,
|
||||
macaroon,
|
||||
socket
|
||||
})
|
||||
|
||||
const inv = await createInvoice({
|
||||
description: 'SN connection test',
|
||||
lnd,
|
||||
tokens: 0,
|
||||
expires_at: new Date()
|
||||
})
|
||||
|
||||
// we wrap both calls in one try/catch since connection attempts happen on RPC calls
|
||||
await addWalletLog({ wallet: { type: 'LND' }, level: 'SUCCESS', message: 'connected to LND' }, { me, models })
|
||||
|
||||
return inv
|
||||
} catch (err) {
|
||||
// LND errors are in this shape: [code, type, { err: { code, details, metadata } }]
|
||||
const details = err[2]?.err?.details || err.message || err.toString?.()
|
||||
throw new Error(details)
|
||||
}
|
||||
},
|
||||
// TODO: use this instead of `autowithdrawLND` in worker/autowithdraw.js
|
||||
createInvoice: async (
|
||||
amount,
|
||||
{ cert, macaroon, socket },
|
||||
{ me, models, addWalletLog, lnService: { authenticatedLndGrpc, createInvoice } }
|
||||
) => {
|
||||
const { lnd } = await authenticatedLndGrpc({
|
||||
cert,
|
||||
macaroon,
|
||||
socket
|
||||
})
|
||||
|
||||
const invoice = await createInvoice({
|
||||
description: me.hideInvoiceDesc ? undefined : 'autowithdraw to LND from SN',
|
||||
lnd,
|
||||
tokens: amount,
|
||||
expires_at: datePivot(new Date(), { seconds: 360 })
|
||||
})
|
||||
|
||||
return invoice.request
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue