From ff2710c0fa6f525e96e55a280aa791e21aea6966 Mon Sep 17 00:00:00 2001
From: Riccardo Balbo <riccardo0blb@gmail.com>
Date: Fri, 27 Dec 2024 11:17:56 +0100
Subject: [PATCH] support generated fields on serverside wallets

---
 api/resolvers/wallet.js | 24 +++++++++++++++---------
 wallets/config.js       |  2 +-
 wallets/validate.js     |  2 +-
 3 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/api/resolvers/wallet.js b/api/resolvers/wallet.js
index ff1f1782e..008496c69 100644
--- a/api/resolvers/wallet.js
+++ b/api/resolvers/wallet.js
@@ -47,14 +47,19 @@ function injectResolvers (resolvers) {
         })
       }
 
-      const validData = await validateWallet(walletDef,
-        { ...data, ...settings, vaultEntries: vaultEntries ?? existingVaultEntries },
-        { serverSide: true })
-      if (validData) {
-        data && Object.keys(validData).filter(key => key in data).forEach(key => { data[key] = validData[key] })
-        settings && Object.keys(validData).filter(key => key in settings).forEach(key => { settings[key] = validData[key] })
+      const validate = async ({ data, settings, skipGenerated = false }) => {
+        const validData = await validateWallet(walletDef,
+          { ...data, ...settings, vaultEntries: vaultEntries ?? existingVaultEntries },
+          { serverSide: true, skipGenerated })
+        if (validData) {
+          data && Object.keys(validData).filter(key => key in data).forEach(key => { data[key] = validData[key] })
+          settings && Object.keys(validData).filter(key => key in settings).forEach(key => { settings[key] = validData[key] })
+        }
       }
 
+      const needsTest = walletDef.testCreateInvoice && validateLightning && canReceive({ def: walletDef, config: data })
+      await validate({ data, settings, skipGenerated: needsTest })
+
       // wallet in shape of db row
       const wallet = {
         field: walletDef.walletField,
@@ -67,7 +72,7 @@ function injectResolvers (resolvers) {
         wallet,
         walletDef,
         testCreateInvoice:
-          walletDef.testCreateInvoice && validateLightning && canReceive({ def: walletDef, config: data })
+          needsTest
             ? (data) => withTimeout(
                 walletDef.testCreateInvoice(data, {
                   logger,
@@ -79,7 +84,7 @@ function injectResolvers (resolvers) {
         settings,
         data,
         vaultEntries
-      }, { logger, me, models })
+      }, { logger, me, models, validate })
     }
   }
   console.groupEnd()
@@ -770,7 +775,7 @@ export const walletLogger = ({ wallet, models }) => {
 }
 
 async function upsertWallet (
-  { wallet, walletDef, testCreateInvoice }, { settings, data, vaultEntries }, { logger, me, models }) {
+  { wallet, walletDef, testCreateInvoice }, { settings, data, vaultEntries }, { logger, me, models, validate }) {
   if (!me) {
     throw new GqlAuthenticationError()
   }
@@ -779,6 +784,7 @@ async function upsertWallet (
   if (testCreateInvoice) {
     try {
       await testCreateInvoice(data)
+      await validate({ data, settings, skipGenerated: false })
     } catch (err) {
       const message = 'failed to create test invoice: ' + (err.message || err.toString?.())
       logger.error(message)
diff --git a/wallets/config.js b/wallets/config.js
index cdc574240..b78f1405e 100644
--- a/wallets/config.js
+++ b/wallets/config.js
@@ -63,7 +63,7 @@ export function useWalletConfigurator (wallet) {
         throw err
       }
     } else if (canReceive({ def: wallet.def, config: serverConfig })) {
-      const transformedConfig = await validateWallet(wallet.def, serverConfig)
+      const transformedConfig = await validateWallet(wallet.def, serverConfig, { skipGenerated: true })
       if (transformedConfig) {
         serverConfig = Object.assign(serverConfig, transformedConfig)
       }
diff --git a/wallets/validate.js b/wallets/validate.js
index bea0cddd3..718d48bb9 100644
--- a/wallets/validate.js
+++ b/wallets/validate.js
@@ -72,7 +72,7 @@ function composeWalletSchema (walletDef, serverSide, skipGenerated) {
 
     if (clientOnly && serverSide) {
       // For server-side validation, accumulate clientOnly fields as vaultEntries
-      vaultEntrySchemas[optional ? 'optional' : 'required'].push(vaultEntrySchema(name))
+      vaultEntrySchemas[(optional || generated) ? 'optional' : 'required'].push(vaultEntrySchema(name))
     } else {
       acc[name] = createFieldSchema(name, validate)