wip: Add LND autowithdrawals
* receiving wallets need to export 'server' object field * don't print macaroon error stack * fix missing wallet logs order update * mark autowithdrawl settings as required * fix server wallet logs deletion * remove canPay and canReceive since it was confusing where it is available TODO * also use numeric priority for sending wallets to be consistent with how status for receiving wallets is determined * define createInvoice function in wallet definition * consistent wallet logs: sending wallets use 'wallet attached'+'wallet enabled/disabled' whereas receiving wallets use 'wallet created/updated' * see FIXMEs
This commit is contained in:
		
							parent
							
								
									ae0335d537
								
							
						
					
					
						commit
						4082a45618
					
				@ -46,12 +46,14 @@ export function AutowithdrawSettings ({ priority }) {
 | 
				
			|||||||
            }}
 | 
					            }}
 | 
				
			||||||
            hint={isNumber(sendThreshold) ? `will attempt auto-withdraw when your balance exceeds ${sendThreshold * 11} sats` : undefined}
 | 
					            hint={isNumber(sendThreshold) ? `will attempt auto-withdraw when your balance exceeds ${sendThreshold * 11} sats` : undefined}
 | 
				
			||||||
            append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
 | 
					            append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
 | 
				
			||||||
 | 
					            required
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
          <Input
 | 
					          <Input
 | 
				
			||||||
            label='max fee'
 | 
					            label='max fee'
 | 
				
			||||||
            name='autoWithdrawMaxFeePercent'
 | 
					            name='autoWithdrawMaxFeePercent'
 | 
				
			||||||
            hint='max fee as percent of withdrawal amount'
 | 
					            hint='max fee as percent of withdrawal amount'
 | 
				
			||||||
            append={<InputGroup.Text>%</InputGroup.Text>}
 | 
					            append={<InputGroup.Text>%</InputGroup.Text>}
 | 
				
			||||||
 | 
					            required
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ import { Button } from 'react-bootstrap'
 | 
				
			|||||||
import { useToast } from './toast'
 | 
					import { useToast } from './toast'
 | 
				
			||||||
import { useShowModal } from './modal'
 | 
					import { useShowModal } from './modal'
 | 
				
			||||||
import { WALLET_LOGS } from '@/fragments/wallet'
 | 
					import { WALLET_LOGS } from '@/fragments/wallet'
 | 
				
			||||||
import { getWalletByName } from './wallet'
 | 
					import { getServerWallet } from './wallet'
 | 
				
			||||||
import { gql, useMutation, useQuery } from '@apollo/client'
 | 
					import { gql, useMutation, useQuery } from '@apollo/client'
 | 
				
			||||||
import { useMe } from './me'
 | 
					import { useMe } from './me'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -128,12 +128,11 @@ export const WalletLoggerProvider = ({ children }) => {
 | 
				
			|||||||
          .map(({ createdAt, wallet: walletType, ...log }) => {
 | 
					          .map(({ createdAt, wallet: walletType, ...log }) => {
 | 
				
			||||||
            return {
 | 
					            return {
 | 
				
			||||||
              ts: +new Date(createdAt),
 | 
					              ts: +new Date(createdAt),
 | 
				
			||||||
              // TODO: use wallet defs
 | 
					              wallet: getServerWallet(walletType).name,
 | 
				
			||||||
              // wallet: getWalletBy('type', walletType).logTag,
 | 
					 | 
				
			||||||
              ...log
 | 
					              ...log
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          })
 | 
					          })
 | 
				
			||||||
        return [...prevLogs, ...logs].sort((a, b) => a.ts - b.ts)
 | 
					        return [...prevLogs, ...logs].sort((a, b) => b.ts - a.ts)
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -148,7 +147,7 @@ export const WalletLoggerProvider = ({ children }) => {
 | 
				
			|||||||
      onCompleted: (_, { variables: { wallet: walletType } }) => {
 | 
					      onCompleted: (_, { variables: { wallet: walletType } }) => {
 | 
				
			||||||
        setLogs((logs) => {
 | 
					        setLogs((logs) => {
 | 
				
			||||||
          // TODO: use wallet defs
 | 
					          // TODO: use wallet defs
 | 
				
			||||||
          return logs.filter(l => walletType ? l.wallet !== getWalletByName('type', walletType) : false)
 | 
					          return logs.filter(l => walletType ? l.wallet !== getServerWallet(walletType).name : false)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -206,10 +205,10 @@ export const WalletLoggerProvider = ({ children }) => {
 | 
				
			|||||||
  }, [saveLog])
 | 
					  }, [saveLog])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const deleteLogs = useCallback(async (wallet) => {
 | 
					  const deleteLogs = useCallback(async (wallet) => {
 | 
				
			||||||
    if (!wallet || wallet.canReceive) {
 | 
					    if (!wallet || wallet.server) {
 | 
				
			||||||
      await deleteServerWalletLogs({ variables: { wallet: wallet?.type } })
 | 
					      await deleteServerWalletLogs({ variables: { wallet: wallet?.server } })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!wallet || wallet.canPay) {
 | 
					    if (!wallet || wallet.sendPayment) {
 | 
				
			||||||
      const tx = idb.current.transaction(idbStoreName, 'readwrite')
 | 
					      const tx = idb.current.transaction(idbStoreName, 'readwrite')
 | 
				
			||||||
      const objectStore = tx.objectStore(idbStoreName)
 | 
					      const objectStore = tx.objectStore(idbStoreName)
 | 
				
			||||||
      const idx = objectStore.index('wallet_ts')
 | 
					      const idx = objectStore.index('wallet_ts')
 | 
				
			||||||
@ -244,6 +243,10 @@ export function useWalletLogger (wallet) {
 | 
				
			|||||||
      console.error('cannot log: no wallet set')
 | 
					      console.error('cannot log: no wallet set')
 | 
				
			||||||
      return
 | 
					      return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // don't store logs for receiving wallets on client since logs are stored on server
 | 
				
			||||||
 | 
					    if (wallet.server) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO:
 | 
					    // TODO:
 | 
				
			||||||
    //   also send this to us if diagnostics was enabled,
 | 
					    //   also send this to us if diagnostics was enabled,
 | 
				
			||||||
    //   very similar to how the service worker logger works.
 | 
					    //   very similar to how the service worker logger works.
 | 
				
			||||||
 | 
				
			|||||||
@ -8,9 +8,13 @@ import { bolt11Tags } from '@/lib/bolt11'
 | 
				
			|||||||
import * as lnbits from '@/components/wallet/lnbits'
 | 
					import * as lnbits from '@/components/wallet/lnbits'
 | 
				
			||||||
import * as nwc from '@/components/wallet/nwc'
 | 
					import * as nwc from '@/components/wallet/nwc'
 | 
				
			||||||
import * as lnc from '@/components/wallet/lnc'
 | 
					import * as lnc from '@/components/wallet/lnc'
 | 
				
			||||||
 | 
					import * as lnd from '@/components/wallet/lnd'
 | 
				
			||||||
 | 
					import { useApolloClient, useMutation, useQuery } from '@apollo/client'
 | 
				
			||||||
 | 
					import { REMOVE_WALLET, WALLET_BY_TYPE } from '@/fragments/wallet'
 | 
				
			||||||
 | 
					import { autowithdrawInitial } from '../autowithdraw-shared'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// wallet definitions
 | 
					// wallet definitions
 | 
				
			||||||
export const WALLET_DEFS = [lnbits, nwc, lnc]
 | 
					export const WALLET_DEFS = [lnbits, nwc, lnc, lnd]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Status = {
 | 
					export const Status = {
 | 
				
			||||||
  Initialized: 'Initialized',
 | 
					  Initialized: 'Initialized',
 | 
				
			||||||
@ -22,11 +26,12 @@ export const Status = {
 | 
				
			|||||||
export function useWallet (name) {
 | 
					export function useWallet (name) {
 | 
				
			||||||
  const me = useMe()
 | 
					  const me = useMe()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const wallet = name ? getWalletByName(name, me) : getEnabledWallet(me)
 | 
					  const wallet = name ? getWalletByName(name) : getEnabledWallet(me)
 | 
				
			||||||
  const { logger } = useWalletLogger(wallet)
 | 
					  const { logger } = useWalletLogger(wallet)
 | 
				
			||||||
  const storageKey = getStorageKey(wallet?.name, me)
 | 
					 | 
				
			||||||
  const [config, saveConfig, clearConfig] = useLocalState(storageKey)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [config, saveConfig, clearConfig] = useConfig(wallet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // FIXME: This throws 'TypeError: Cannot read properties of undefined (reading 'length')' when I disable LNbits
 | 
				
			||||||
  const sendPayment = useCallback(async (bolt11) => {
 | 
					  const sendPayment = useCallback(async (bolt11) => {
 | 
				
			||||||
    const hash = bolt11Tags(bolt11).payment_hash
 | 
					    const hash = bolt11Tags(bolt11).payment_hash
 | 
				
			||||||
    logger.info('sending payment:', `payment_hash=${hash}`)
 | 
					    logger.info('sending payment:', `payment_hash=${hash}`)
 | 
				
			||||||
@ -53,9 +58,10 @@ export function useWallet (name) {
 | 
				
			|||||||
  const save = useCallback(async (config) => {
 | 
					  const save = useCallback(async (config) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      // validate should log custom INFO and OK message
 | 
					      // validate should log custom INFO and OK message
 | 
				
			||||||
 | 
					      // validate is optional since validation might happen during save on server
 | 
				
			||||||
      // TODO: add timeout
 | 
					      // TODO: add timeout
 | 
				
			||||||
      await wallet.validate({ me, logger, ...config })
 | 
					      await wallet.validate?.({ me, logger, ...config })
 | 
				
			||||||
      saveConfig(config)
 | 
					      await saveConfig(config)
 | 
				
			||||||
      logger.ok('wallet attached')
 | 
					      logger.ok('wallet attached')
 | 
				
			||||||
    } catch (err) {
 | 
					    } catch (err) {
 | 
				
			||||||
      const message = err.message || err.toString?.()
 | 
					      const message = err.message || err.toString?.()
 | 
				
			||||||
@ -85,17 +91,97 @@ export function useWallet (name) {
 | 
				
			|||||||
    enable,
 | 
					    enable,
 | 
				
			||||||
    disable,
 | 
					    disable,
 | 
				
			||||||
    isConfigured: !!config,
 | 
					    isConfigured: !!config,
 | 
				
			||||||
    status: config?.enabled ? Status.Enabled : Status.Initialized,
 | 
					    status: config?.enabled || config?.priority ? Status.Enabled : Status.Initialized,
 | 
				
			||||||
    canPay: !!wallet?.sendPayment,
 | 
					 | 
				
			||||||
    canReceive: !!wallet?.createInvoice,
 | 
					 | 
				
			||||||
    logger
 | 
					    logger
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getWalletByName (name, me) {
 | 
					function useConfig (wallet) {
 | 
				
			||||||
 | 
					  if (!wallet) return []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (wallet.sendPayment) {
 | 
				
			||||||
 | 
					    // FIXME: this throws 'Error: Should have a queue' when I enable LNbits
 | 
				
			||||||
 | 
					    //   probably because of conditional hooks?
 | 
				
			||||||
 | 
					    return useLocalConfig(wallet)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (wallet.server) {
 | 
				
			||||||
 | 
					    return useServerConfig(wallet)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // TODO: if wallets can do both return a merged version that knows which field goes where
 | 
				
			||||||
 | 
					  return []
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function useLocalConfig (wallet) {
 | 
				
			||||||
 | 
					  const me = useMe()
 | 
				
			||||||
 | 
					  const storageKey = getStorageKey(wallet?.name, me)
 | 
				
			||||||
 | 
					  return useLocalState(storageKey)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function useServerConfig (wallet) {
 | 
				
			||||||
 | 
					  const client = useApolloClient()
 | 
				
			||||||
 | 
					  const me = useMe()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const { walletType, mutation } = wallet.server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const { data } = useQuery(WALLET_BY_TYPE, { variables: { type: walletType } })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [upsertWallet] = useMutation(mutation, {
 | 
				
			||||||
 | 
					    refetchQueries: ['WalletLogs'],
 | 
				
			||||||
 | 
					    onError: (err) => {
 | 
				
			||||||
 | 
					      client.refetchQueries({ include: ['WalletLogs'] })
 | 
				
			||||||
 | 
					      throw err
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [removeWallet] = useMutation(REMOVE_WALLET, {
 | 
				
			||||||
 | 
					    refetchQueries: ['WalletLogs'],
 | 
				
			||||||
 | 
					    onError: (err) => {
 | 
				
			||||||
 | 
					      client.refetchQueries({ include: ['WalletLogs'] })
 | 
				
			||||||
 | 
					      throw err
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const walletId = data?.walletByType.id
 | 
				
			||||||
 | 
					  const serverConfig = { id: walletId, priority: data?.walletByType.priority, ...data?.walletByType.wallet }
 | 
				
			||||||
 | 
					  const autowithdrawSettings = autowithdrawInitial({ me, priority: serverConfig?.priority })
 | 
				
			||||||
 | 
					  const config = { ...serverConfig, autowithdrawSettings }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const saveConfig = useCallback(async ({
 | 
				
			||||||
 | 
					    autoWithdrawThreshold,
 | 
				
			||||||
 | 
					    autoWithdrawMaxFeePercent,
 | 
				
			||||||
 | 
					    priority,
 | 
				
			||||||
 | 
					    ...config
 | 
				
			||||||
 | 
					  }) => {
 | 
				
			||||||
 | 
					    await upsertWallet({
 | 
				
			||||||
 | 
					      variables: {
 | 
				
			||||||
 | 
					        id: walletId,
 | 
				
			||||||
 | 
					        ...config,
 | 
				
			||||||
 | 
					        settings: {
 | 
				
			||||||
 | 
					          autoWithdrawThreshold: Number(autoWithdrawThreshold),
 | 
				
			||||||
 | 
					          autoWithdrawMaxFeePercent: Number(autoWithdrawMaxFeePercent),
 | 
				
			||||||
 | 
					          priority: !!priority
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  }, [upsertWallet, walletId])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const clearConfig = useCallback(async () => {
 | 
				
			||||||
 | 
					    await removeWallet({ variables: { id: config?.id } })
 | 
				
			||||||
 | 
					  }, [removeWallet, config?.id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return [config, saveConfig, clearConfig]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getWalletByName (name) {
 | 
				
			||||||
  return WALLET_DEFS.find(def => def.name === name)
 | 
					  return WALLET_DEFS.find(def => def.name === name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getServerWallet (type) {
 | 
				
			||||||
 | 
					  return WALLET_DEFS.find(def => def.server?.walletType === type)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getEnabledWallet (me) {
 | 
					export function getEnabledWallet (me) {
 | 
				
			||||||
  // TODO: handle multiple enabled wallets
 | 
					  // TODO: handle multiple enabled wallets
 | 
				
			||||||
  return WALLET_DEFS
 | 
					  return WALLET_DEFS
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										48
									
								
								components/wallet/lnd.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								components/wallet/lnd.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					import { UPSERT_WALLET_LND } from '@/fragments/wallet'
 | 
				
			||||||
 | 
					import { LNDAutowithdrawSchema } from '@/lib/validate'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const name = 'lnd'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const fields = [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    name: 'socket',
 | 
				
			||||||
 | 
					    label: 'grpc host and port',
 | 
				
			||||||
 | 
					    type: 'text',
 | 
				
			||||||
 | 
					    placeholder: '55.5.555.55:10001',
 | 
				
			||||||
 | 
					    hint: 'tor or clearnet',
 | 
				
			||||||
 | 
					    clear: true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    name: 'macaroon',
 | 
				
			||||||
 | 
					    label: 'invoice macaroon',
 | 
				
			||||||
 | 
					    help: {
 | 
				
			||||||
 | 
					      label: 'privacy tip',
 | 
				
			||||||
 | 
					      text: 'We accept a prebaked ***invoice.macaroon*** for your convenience. To gain better privacy, generate a new macaroon as follows:\n\n```lncli bakemacaroon invoices:write invoices:read```'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    type: 'text',
 | 
				
			||||||
 | 
					    placeholder: 'AgEDbG5kAlgDChCn7YgfWX7uTkQQgXZ2uahNEgEwGhYKB2FkZHJlc3MSBHJlYWQSBXdyaXRlGhcKCGludm9pY2VzEgRyZWFkEgV3cml0ZRoPCgdvbmNoYWluEgRyZWFkAAAGIJkMBrrDV0npU90JV0TGNJPrqUD8m2QYoTDjolaL6eBs',
 | 
				
			||||||
 | 
					    hint: 'hex or base64 encoded',
 | 
				
			||||||
 | 
					    clear: true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    name: 'cert',
 | 
				
			||||||
 | 
					    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)</>,
 | 
				
			||||||
 | 
					    clear: true
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const card = {
 | 
				
			||||||
 | 
					  title: 'LND',
 | 
				
			||||||
 | 
					  subtitle: 'autowithdraw to your Lightning Labs node',
 | 
				
			||||||
 | 
					  badges: ['receive only', 'non-custodial']
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const schema = LNDAutowithdrawSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const server = {
 | 
				
			||||||
 | 
					  walletType: 'LND',
 | 
				
			||||||
 | 
					  mutation: UPSERT_WALLET_LND
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -22,7 +22,7 @@ function macaroonOPs (macaroon) {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } catch (e) {
 | 
					  } catch (e) {
 | 
				
			||||||
    console.error('macaroonOPs error:', e)
 | 
					    console.error('macaroonOPs error:', e.message)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return []
 | 
					  return []
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ import { useRouter } from 'next/router'
 | 
				
			|||||||
import { useWallet, Status } from '@/components/wallet'
 | 
					import { useWallet, Status } from '@/components/wallet'
 | 
				
			||||||
import Info from '@/components/info'
 | 
					import Info from '@/components/info'
 | 
				
			||||||
import Text from '@/components/text'
 | 
					import Text from '@/components/text'
 | 
				
			||||||
 | 
					import { AutowithdrawSettings } from '@/components/autowithdraw-shared'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getServerSideProps = getGetServerSideProps({ authRequired: true })
 | 
					export const getServerSideProps = getGetServerSideProps({ authRequired: true })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -23,7 +24,7 @@ export default function WalletSettings () {
 | 
				
			|||||||
      ...acc,
 | 
					      ...acc,
 | 
				
			||||||
      [field.name]: wallet.config?.[field.name] || ''
 | 
					      [field.name]: wallet.config?.[field.name] || ''
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }, {})
 | 
					  }, wallet.server ? wallet.config.autowithdrawSettings : {})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <CenterLayout>
 | 
					    <CenterLayout>
 | 
				
			||||||
@ -50,12 +51,16 @@ export default function WalletSettings () {
 | 
				
			|||||||
        }}
 | 
					        }}
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
        <WalletFields wallet={wallet} />
 | 
					        <WalletFields wallet={wallet} />
 | 
				
			||||||
        <ClientCheckbox
 | 
					        {wallet.server
 | 
				
			||||||
          disabled={false}
 | 
					          ? <AutowithdrawSettings />
 | 
				
			||||||
          initialValue={wallet.status === Status.Enabled}
 | 
					          : (
 | 
				
			||||||
          label='enabled'
 | 
					            <ClientCheckbox
 | 
				
			||||||
          name='enabled'
 | 
					              disabled={false}
 | 
				
			||||||
        />
 | 
					              initialValue={wallet.status === Status.Enabled}
 | 
				
			||||||
 | 
					              label='enabled'
 | 
				
			||||||
 | 
					              name='enabled'
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
        <WalletButtonBar
 | 
					        <WalletButtonBar
 | 
				
			||||||
          wallet={wallet} onDelete={async () => {
 | 
					          wallet={wallet} onDelete={async () => {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
@ -86,12 +91,17 @@ function WalletFields ({ wallet: { config, fields } }) {
 | 
				
			|||||||
      label: (
 | 
					      label: (
 | 
				
			||||||
        <div className='d-flex align-items-center'>
 | 
					        <div className='d-flex align-items-center'>
 | 
				
			||||||
          {label}
 | 
					          {label}
 | 
				
			||||||
 | 
					          {/* help can be a string or object to customize the label */}
 | 
				
			||||||
          {help && (
 | 
					          {help && (
 | 
				
			||||||
            <Info label='help'>
 | 
					            <Info label={help.label || 'help'}>
 | 
				
			||||||
              <Text>{help}</Text>
 | 
					              <Text>{help.text || help}</Text>
 | 
				
			||||||
            </Info>
 | 
					            </Info>
 | 
				
			||||||
          )}
 | 
					          )}
 | 
				
			||||||
          {optional && <small className='text-muted ms-2'>optional</small>}
 | 
					          {optional && (
 | 
				
			||||||
 | 
					            <small className='text-muted ms-2'>
 | 
				
			||||||
 | 
					              {typeof optional === 'boolean' ? 'optional' : optional}
 | 
				
			||||||
 | 
					            </small>
 | 
				
			||||||
 | 
					          )}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      required: !optional,
 | 
					      required: !optional,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user