From 24bdf0a0997e7da62fdb8cdbd14c156b90ea0616 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 8 Jul 2024 12:56:49 +0200 Subject: [PATCH] Add example wallet def --- components/wallet/_example.js | 162 ++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 components/wallet/_example.js diff --git a/components/wallet/_example.js b/components/wallet/_example.js new file mode 100644 index 00000000..1e3ff788 --- /dev/null +++ b/components/wallet/_example.js @@ -0,0 +1,162 @@ +import React from 'react' +import { lnbitsSchema } from '@/lib/validate' + +// ~~~ +// AFTER YOU HAVE FILLED OUT THIS TEMPLATE, IMPORT THIS FILE IN components/wallet/index.js +// AND ADD IT TO THE `WALLET_DEFS` array. +// DO THE SAME IN api/resolvers/wallet.js WITH THE `SERVER_WALLET_DEFS` ARRAY. +// (these arrays are separate to avoid backend imports in frontend) +// ~~~ + +// This name is used to identify this wallet and thus must be unique. +// It is used with the useWallet hook to select this wallet, see components/wallet/index.js. +// [required] +export const name = 'lnbits-as-an-example' + +// The form to configure this wallet is generated from these fields, +// see the component in pages/settings/wallets/[wallet].js. +// +// If you need to include React code, you need to use React.createElement +// since the worker will also import this file and does not support JSX syntax. +// +// If not handled otherwise in , field properties are simply +// passed into or as props (component depends on 'type'). +// +// For example, the following fields will generate a config in this shape (depending on user inputs): +// { +// url: 'https://demo.lnbits.com/', +// adminKey: 'a47acd6feba4489e9e99b256b4ae9049' +// } +// [required] +export const fields = [ + { + name: 'url', + label: 'lnbits url', + // 'type' can be 'text' or 'password' + type: 'text' + }, + { + name: 'adminKey', + label: 'admin key', + type: 'password' + // see other wallets for more complex fields + } +] + +// Used to display information about this wallet to the user in the wallet list or during configuration, +// see components/wallet-card.js and pages/settings/wallets/[wallet].js. +// [required] +export const card = { + title: 'LNbits', + // as mentioned above, you need to use React.createElement instead of JSX for more complex content + subtitle: React.createElement( + React.Fragment, + {}, + 'use ', + React.createElement('a', { href: 'https://lnbits.com/', target: '_blank', rel: 'noreferrer' }, 'LNbits'), + ' for payments'), + badges: ['send only', 'non-custodialish'] +} + +// The validation schema that will be used on the client and server during save +// [required] +export const schema = lnbitsSchema + +// This optional function will be called during save to abort the save if the configuration is invalid. +// It receives the config and context as arguments. +// It must throw an error if validation fails. +// [optional] +export async function validate (config, context) { + // what the config object will contain is determined by the fields array above + // const { url, adminKey } = config + + // the context includes the logger and other useful stuff, see save method in components/wallet/index.js + const { logger } = context + + // validate should log useful, wallet-specific information for the user + logger.info('running some wallet-specific validation') + + // ... + // throw error if validation failed +} + +// If this wallet supports payments, you need to implement this function: +// +// sendPayment: (bolt11, config, context) => Promise<{ preimage: string }> +// +// [required for payments] +export async function sendPayment (bolt11, config, context) { + // ... +} + +// If this wallet supports receiving, you need to implement this object. +// [required for receiving] +export const server = { + // This must match a WalletType enum value in the database + // since it will be used to fetch this wallet using the WALLET_BY_TYPE GraphQL query, + // see `useServerConfig` in components/wallet/index.js. + // [required] + walletType: 'LNBITS', + + // This used must match a column of the 'Wallet' table + // since it will be used to save the wallet configuration. + // [required] + walletField: 'walletLNbits', + + // This can be any name but it makes sense to use something appropriate here like 'upsertWallet'. + // This is used to generate the mutation during save (see `generateMutation` in components/wallets/index.js) + // and inject the corresponding resolver into the GraphQL schema + // (see `injectResolvers` in pages/api/resolvers/wallet.js.). + // [required] + resolverName: 'upsertWalletLNbits', + + // Similar to validate above, this function should throw an error if the connection test fails. + // It is called on save on the server before writing the configuration to the database. + // As the name suggests, a good idea is to try to connect to the wallet and create an invoice in this function. + // [required] + testConnect: async ( + // Wallet configuration as entered by the user + config, + // Context object with useful stuff, see `injectResolvers` in pages/api/resolvers/wallet.js. + { + me, + models, + addWalletLog, + lnService: { authenticatedLndGrpc, createInvoice }, + cln: { createInvoice: clnCreateInvoice } + } + ) => { + + // ... + // throw error if validation failed + // (logging errors is handled by calling context but you can add custom logging on success here) + }, + + // This function is called during autowithdrawals. + // It should return a bolt11 payment request. + // + // createInvoice: ({ amount, maxFee }, config, context) => Promise + // + createInvoice: async ( + { amount, maxFee }, + { socket, rune, cert }, + // Context object with useful stuff, see `autowithdraw` function in worker/autowithdraw.js. + { + me, + models, + // SN LND node instance + lnd, + lnService: { + authenticatedLndGrpc, + createInvoice: lndCreateInvoice, + getIdentity, + decodePaymentRequest + }, + cln: { + createInvoice: clnCreateInvoice + } + } + ) => { + // ... create invoice and return bolt11 that the SN node will pay + } +}