From 3d8ae4a7a3329f11d6497cf41114ec00b317e498 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sun, 18 Aug 2024 11:32:25 -0500 Subject: [PATCH] Generate more server wallet code (#1309) * Generate more code from wallet defs * generate "type WalletLND { ... }" * generate "union WalletDetails = WalletLND | ..." * hardcode function for __resolveType * add comments where updates are needed if another server wallet is added * Fix type for LN addresses * Generate __resolveType from wallet.type column --- api/resolvers/wallet.js | 14 +++++-- api/typeDefs/wallet.js | 90 +++++++++++++++++++++-------------------- fragments/wallet.js | 6 ++- lib/wallet.js | 18 +++++++++ 4 files changed, 79 insertions(+), 49 deletions(-) diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js index bff9451e0..de43a61a2 100644 --- a/api/resolvers/wallet.js +++ b/api/resolvers/wallet.js @@ -13,7 +13,7 @@ import assertApiKeyNotPermitted from './apiKey' import { bolt11Tags } from '@/lib/bolt11' import { finalizeHodlInvoice } from 'worker/wallet' import walletDefs from 'wallets/server' -import { generateResolverName } from '@/lib/wallet' +import { generateResolverName, walletTypeToResolveType } from '@/lib/wallet' import { lnAddrOptions } from '@/lib/lnurl' function injectResolvers (resolvers) { @@ -349,11 +349,17 @@ const resolvers = { }) } }, - WalletDetails: { - __resolveType (wallet) { - return wallet.address ? 'WalletLNAddr' : wallet.macaroon ? 'WalletLND' : wallet.rune ? 'WalletCLN' : 'WalletLNbits' + Wallet: { + wallet: async (wallet) => { + return { + ...wallet.wallet, + __resolveType: walletTypeToResolveType(wallet.type) + } } }, + WalletDetails: { + __resolveType: wallet => wallet.__resolveType + }, Mutation: { createInvoice: async (parent, { amount, hodlInvoice = false, expireSecs = 3600 }, { me, models, lnd, headers }) => { await ssValidate(amountSchema, { amount }) diff --git a/api/typeDefs/wallet.js b/api/typeDefs/wallet.js index 3d011c44a..2baa2d089 100644 --- a/api/typeDefs/wallet.js +++ b/api/typeDefs/wallet.js @@ -1,32 +1,59 @@ import { gql } from 'graphql-tag' -import { generateResolverName } from '@/lib/wallet' +import { fieldToGqlArg, generateResolverName, generateTypeDefName } from '@/lib/wallet' import walletDefs from 'wallets/server' import { isServerField } from 'wallets' function injectTypeDefs (typeDefs) { + const injected = [rawTypeDefs(), mutationTypeDefs()] + return `${typeDefs}\n\n${injected.join('\n\n')}\n` +} + +function mutationTypeDefs () { + console.group('injected GraphQL mutations:') + + const typeDefs = walletDefs.map((w) => { + let args = 'id: ID, ' + args += w.fields + .filter(isServerField) + .map(fieldToGqlArg).join(', ') + args += ', settings: AutowithdrawSettings!' + const resolverName = generateResolverName(w.walletField) + const typeDef = `${resolverName}(${args}): Boolean` + console.log(typeDef) + return typeDef + }) + + console.groupEnd() + + return `extend type Mutation {\n${typeDefs.join('\n')}\n}` +} + +function rawTypeDefs () { console.group('injected GraphQL type defs:') - const injected = walletDefs.map( - (w) => { - let args = 'id: ID, ' - args += w.fields - .filter(isServerField) - .map(f => { - let arg = `${f.name}: String` - if (!f.optional) { - arg += '!' - } - return arg - }).join(', ') - args += ', settings: AutowithdrawSettings!' - const resolverName = generateResolverName(w.walletField) - const typeDef = `${resolverName}(${args}): Boolean` - console.log(typeDef) - return typeDef - }) + + const typeDefs = walletDefs.map((w) => { + const args = w.fields + .filter(isServerField) + .map(fieldToGqlArg) + .map(s => ' ' + s) + .join('\n') + const typeDefName = generateTypeDefName(w.walletField) + const typeDef = `type ${typeDefName} {\n${args}\n}` + console.log(typeDef) + return typeDef + }) + + let union = 'union WalletDetails = ' + union += walletDefs.map((w) => { + const typeDefName = generateTypeDefName(w.walletField) + return typeDefName + }).join(' | ') + console.log(union) + console.groupEnd() - return `${typeDefs}\n\nextend type Mutation {\n${injected.join('\n')}\n}` + return typeDefs.join('\n\n') + union } const typeDefs = ` @@ -61,29 +88,6 @@ const typeDefs = ` wallet: WalletDetails! } - type WalletLNAddr { - address: String! - } - - type WalletLND { - socket: String! - macaroon: String! - cert: String - } - - type WalletCLN { - socket: String! - rune: String! - cert: String - } - - type WalletLNbits { - url: String! - invoiceKey: String! - } - - union WalletDetails = WalletLNAddr | WalletLND | WalletCLN | WalletLNbits - input AutowithdrawSettings { autoWithdrawThreshold: Int! autoWithdrawMaxFeePercent: Float! diff --git a/fragments/wallet.js b/fragments/wallet.js index 8b10fe4db..edcb19083 100644 --- a/fragments/wallet.js +++ b/fragments/wallet.js @@ -107,6 +107,7 @@ mutation removeWallet($id: ID!) { } ` +// XXX [WALLET] this needs to be updated if another server wallet is added export const WALLET = gql` query Wallet($id: ID!) { wallet(id: $id) { @@ -116,7 +117,7 @@ export const WALLET = gql` type wallet { __typename - ... on WalletLNAddr { + ... on WalletLightningAddress { address } ... on WalletLND { @@ -138,6 +139,7 @@ export const WALLET = gql` } ` +// XXX [WALLET] this needs to be updated if another server wallet is added export const WALLET_BY_TYPE = gql` query WalletByType($type: String!) { walletByType(type: $type) { @@ -148,7 +150,7 @@ export const WALLET_BY_TYPE = gql` type wallet { __typename - ... on WalletLNAddr { + ... on WalletLightningAddress { address } ... on WalletLND { diff --git a/lib/wallet.js b/lib/wallet.js index eaa329f26..d54a4f63f 100644 --- a/lib/wallet.js +++ b/lib/wallet.js @@ -1,4 +1,22 @@ +export function fieldToGqlArg (field) { + let arg = `${field.name}: String` + if (!field.optional) { + arg += '!' + } + return arg +} + export function generateResolverName (walletField) { const capitalized = walletField[0].toUpperCase() + walletField.slice(1) return `upsert${capitalized}` } + +export function generateTypeDefName (walletField) { + return walletField[0].toUpperCase() + walletField.slice(1) +} + +export function walletTypeToResolveType (walletType) { + // wallet type is in UPPER_CASE but __resolveType requires PascalCase + const PascalCase = walletType.split('_').map(s => s[0].toUpperCase() + s.slice(1)).join() + return `Wallet${PascalCase}` +}