From db55cc7a00353466f80f3a5b7cbc0e997afad177 Mon Sep 17 00:00:00 2001 From: k00b Date: Mon, 4 Nov 2024 18:39:52 -0600 Subject: [PATCH] fix 1538 --- wallets/blink/index.js | 24 +++++++++++++----------- wallets/validate.js | 13 ++++++++++--- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/wallets/blink/index.js b/wallets/blink/index.js index 7975c9d4d..bd8ac4df3 100644 --- a/wallets/blink/index.js +++ b/wallets/blink/index.js @@ -15,8 +15,8 @@ export const fields = [ validate: string() .matches(/^blink_[A-Za-z0-9]+$/, { message: 'must match pattern blink_A-Za-z0-9' }), help: `you can get an API key from [Blink Dashboard](${galoyBlinkDashboardUrl}).\nPlease make sure to select ONLY the 'Read' and 'Write' scopes when generating this API key.`, - optional: 'for sending', - requiredWithout: 'apiKeyRecv' + requiredWithout: 'apiKeyRecv', + optional: 'for sending' }, { name: 'currency', @@ -30,33 +30,35 @@ export const fields = [ validate: string() .transform(value => value ? value.toUpperCase() : 'BTC') .oneOf(['USD', 'BTC'], 'must be BTC or USD'), - optional: 'for sending' + optional: 'for sending', + requiredWithout: 'currencyRecv' }, { name: 'apiKeyRecv', - label: 'api key', + label: 'receive api key', type: 'password', help: `you can get an API key from [Blink Dashboard](${galoyBlinkDashboardUrl}).\nPlease make sure to select ONLY the 'Read' and 'Receive' scopes when generating this API key.`, placeholder: 'blink_...', - optional: 'for receiving', serverOnly: true, - requiredWithout: 'apiKey', validate: string() - .matches(/^blink_[A-Za-z0-9]+$/, { message: 'must match pattern blink_A-Za-z0-9' }) + .matches(/^blink_[A-Za-z0-9]+$/, { message: 'must match pattern blink_A-Za-z0-9' }), + optional: 'for receiving', + requiredWithout: 'apiKey' }, { name: 'currencyRecv', - label: 'wallet type', + label: 'receive wallet type', type: 'text', help: 'the blink wallet to use for receiving (only BTC available)', - value: 'BTC', clear: true, autoComplete: 'off', - optional: 'for receiving', + placeholder: 'BTC', serverOnly: true, validate: string() .transform(value => value ? value.toUpperCase() : 'BTC') - .oneOf(['BTC'], 'must be BTC') + .oneOf(['BTC'], 'must be BTC'), + optional: 'for receiving', + requiredWithout: 'currency' } ] diff --git a/wallets/validate.js b/wallets/validate.js index 592e642ab..bea0cddd3 100644 --- a/wallets/validate.js +++ b/wallets/validate.js @@ -62,6 +62,7 @@ function composeWalletSchema (walletDef, serverSide, skipGenerated) { const { fields } = walletDef const vaultEntrySchemas = { required: [], optional: [] } + const cycleBreaker = [] const schemaShape = fields.reduce((acc, field) => { const { name, validate, optional, generated, clientOnly, requiredWithout } = field @@ -78,8 +79,14 @@ function composeWalletSchema (walletDef, serverSide, skipGenerated) { if (!optional) { acc[name] = acc[name].required('required') } else if (requiredWithout) { + const myName = serverSide ? 'vaultEntries' : name + const partnerName = serverSide ? 'vaultEntries' : requiredWithout + // if a cycle breaker between this pair hasn't been added yet, add it + if (!cycleBreaker.some(pair => pair[1] === myName)) { + cycleBreaker.push([myName, partnerName]) + } // if we are the server, the pairSetting will be in the vaultEntries array - acc[name] = acc[name].when([serverSide ? 'vaultEntries' : requiredWithout], ([pairSetting], schema) => { + acc[name] = acc[name].when([partnerName], ([pairSetting], schema) => { if (!pairSetting || (serverSide && !pairSetting.some(v => v.key === requiredWithout))) { return schema.required(`required if ${requiredWithout} not set`) } @@ -99,9 +106,9 @@ function composeWalletSchema (walletDef, serverSide, skipGenerated) { schemaShape.vaultEntries = Yup.array().equalto(vaultEntrySchemas) } - // we use Object.keys(schemaShape).reverse() to avoid cyclic dependencies in Yup schema + // we use cycleBreaker to avoid cyclic dependencies in Yup schema // see https://github.com/jquense/yup/issues/176#issuecomment-367352042 - const composedSchema = Yup.object().shape(schemaShape, Object.keys(schemaShape).reverse()).concat(Yup.object({ + const composedSchema = Yup.object().shape(schemaShape, cycleBreaker).concat(Yup.object({ enabled: Yup.boolean(), priority: Yup.number().min(0, 'must be at least 0').max(100, 'must be at most 100') }))