Wallet tests as separate mutations (#2385)

* Rename mutation to UPSERT_WALLET_RECEIVE_LND_GRPC

* Move wallet typedefs into individual sections

* Split wallet tests into separate mutation

---------

Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
This commit is contained in:
ekzyis 2025-08-03 19:23:56 +02:00 committed by GitHub
parent 21532509fb
commit 7c6a65c332
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 257 additions and 100 deletions

View File

@ -1,8 +1,6 @@
import { gql } from 'graphql-tag' import { gql } from 'graphql-tag'
const sharedSend = 'walletId: ID, templateName: ID, enabled: Boolean!' const shared = 'walletId: ID, templateName: ID, enabled: Boolean!'
const sharedRecv = `${sharedSend}, networkTests: Boolean`
const typeDefs = gql` const typeDefs = gql`
extend type Query { extend type Query {
@ -24,78 +22,76 @@ const typeDefs = gql`
sendToLnAddr(addr: String!, amount: Int!, maxFee: Int!, comment: String, identifier: Boolean, name: String, email: String): Withdrawl! sendToLnAddr(addr: String!, amount: Int!, maxFee: Int!, comment: String, identifier: Boolean, name: String, email: String): Withdrawl!
cancelInvoice(hash: String!, hmac: String, userCancel: Boolean): Invoice! cancelInvoice(hash: String!, hmac: String, userCancel: Boolean): Invoice!
dropBolt11(hash: String!): Boolean dropBolt11(hash: String!): Boolean
removeWallet(id: ID!): Boolean
deleteWalletLogs(protocolId: Int, debug: Boolean): Boolean
setWalletPriorities(priorities: [WalletPriorityUpdate!]!): Boolean
buyCredits(credits: Int!): BuyCreditsPaidAction! buyCredits(credits: Int!): BuyCreditsPaidAction!
# upserts
upsertWalletSendLNbits( upsertWalletSendLNbits(
${sharedSend}, ${shared},
url: String!, url: String!,
apiKey: VaultEntryInput! apiKey: VaultEntryInput!
): WalletSendLNbits! ): WalletSendLNbits!
upsertWalletRecvLNbits( upsertWalletRecvLNbits(
${sharedRecv}, ${shared},
url: String!, url: String!,
apiKey: String! apiKey: String!
): WalletRecvLNbits! ): WalletRecvLNbits!
upsertWalletSendPhoenixd( upsertWalletSendPhoenixd(
${sharedSend}, ${shared},
url: String!, url: String!,
apiKey: VaultEntryInput! apiKey: VaultEntryInput!
): WalletSendPhoenixd! ): WalletSendPhoenixd!
upsertWalletRecvPhoenixd( upsertWalletRecvPhoenixd(
${sharedRecv}, ${shared},
url: String!, url: String!,
apiKey: String! apiKey: String!
): WalletRecvPhoenixd! ): WalletRecvPhoenixd!
upsertWalletSendBlink( upsertWalletSendBlink(
${sharedSend}, ${shared},
currency: VaultEntryInput!, currency: VaultEntryInput!,
apiKey: VaultEntryInput! apiKey: VaultEntryInput!
): WalletSendBlink! ): WalletSendBlink!
upsertWalletRecvBlink( upsertWalletRecvBlink(
${sharedRecv}, ${shared},
currency: String!, currency: String!,
apiKey: String! apiKey: String!
): WalletRecvBlink! ): WalletRecvBlink!
upsertWalletRecvLightningAddress( upsertWalletRecvLightningAddress(
${sharedRecv}, ${shared},
address: String! address: String!
): WalletRecvLightningAddress! ): WalletRecvLightningAddress!
upsertWalletSendNWC( upsertWalletSendNWC(
${sharedSend}, ${shared},
url: VaultEntryInput! url: VaultEntryInput!
): WalletSendNWC! ): WalletSendNWC!
upsertWalletRecvNWC( upsertWalletRecvNWC(
${sharedRecv}, ${shared},
url: String! url: String!
): WalletRecvNWC! ): WalletRecvNWC!
upsertWalletRecvCLNRest( upsertWalletRecvCLNRest(
${sharedRecv}, ${shared},
socket: String!, socket: String!,
rune: String!, rune: String!,
cert: String cert: String
): WalletRecvCLNRest! ): WalletRecvCLNRest!
upsertWalletRecvLNDGRPC( upsertWalletRecvLNDGRPC(
${sharedRecv}, ${shared},
socket: String!, socket: String!,
macaroon: String!, macaroon: String!,
cert: String cert: String
): WalletRecvLNDGRPC! ): WalletRecvLNDGRPC!
upsertWalletSendLNC( upsertWalletSendLNC(
${sharedSend}, ${shared},
pairingPhrase: VaultEntryInput!, pairingPhrase: VaultEntryInput!,
localKey: VaultEntryInput!, localKey: VaultEntryInput!,
remoteKey: VaultEntryInput!, remoteKey: VaultEntryInput!,
@ -103,16 +99,62 @@ const typeDefs = gql`
): WalletSendLNC! ): WalletSendLNC!
upsertWalletSendWebLN( upsertWalletSendWebLN(
${sharedSend} ${shared}
): WalletSendWebLN! ): WalletSendWebLN!
# tests
testWalletRecvNWC(
url: String!
): Boolean!
testWalletRecvLightningAddress(
address: String!
): Boolean!
testWalletRecvCLNRest(
socket: String!,
rune: String!,
cert: String
): Boolean!
testWalletRecvLNDGRPC(
socket: String!,
macaroon: String!,
cert: String
): Boolean!
testWalletRecvPhoenixd(
url: String!
apiKey: String!
): Boolean!
testWalletRecvLNbits(
url: String!
apiKey: String!
): Boolean!
testWalletRecvBlink(
currency: String!
apiKey: String!
): Boolean!
# delete
removeWallet(id: ID!): Boolean
removeWalletProtocol(id: ID!): Boolean removeWalletProtocol(id: ID!): Boolean
# crypto
updateWalletEncryption(keyHash: String!, wallets: [WalletEncryptionUpdate!]!): Boolean updateWalletEncryption(keyHash: String!, wallets: [WalletEncryptionUpdate!]!): Boolean
updateKeyHash(keyHash: String!): Boolean updateKeyHash(keyHash: String!): Boolean
resetWallets(newKeyHash: String!): Boolean resetWallets(newKeyHash: String!): Boolean
disablePassphraseExport: Boolean disablePassphraseExport: Boolean
# settings
setWalletSettings(settings: WalletSettingsInput!): Boolean setWalletSettings(settings: WalletSettingsInput!): Boolean
setWalletPriorities(priorities: [WalletPriorityUpdate!]!): Boolean
# logs
addWalletLog(protocolId: Int, level: String!, message: String!, timestamp: Date!, invoiceId: Int): Boolean addWalletLog(protocolId: Int, level: String!, message: String!, timestamp: Date!, invoiceId: Int): Boolean
deleteWalletLogs(protocolId: Int, debug: Boolean): Boolean
} }
type BuyCreditsResult { type BuyCreditsResult {

View File

@ -291,7 +291,7 @@ index 26c292d9..3ac88ae1 100644
- add GraphQL type - add GraphQL type
- add GraphQL type to `WalletProtocolConfig` union - add GraphQL type to `WalletProtocolConfig` union
- add GraphQL type to `WalletProtocolFields` fragment via spread operator (...) - add GraphQL type to `WalletProtocolFields` fragment via spread operator (...)
- add GraphQL mutation to upsert protocol - add GraphQL mutation to upsert and test protocol
- resolve GraphQL type in `mapWalletResolveTypes` function - resolve GraphQL type in `mapWalletResolveTypes` function
<details> <details>
@ -303,10 +303,10 @@ index 3c1fffd1..af3858a5 100644
--- a/api/typeDefs/wallet.js --- a/api/typeDefs/wallet.js
+++ b/api/typeDefs/wallet.js +++ b/api/typeDefs/wallet.js
@@ -38,6 +38,7 @@ const typeDefs = gql` @@ -38,6 +38,7 @@ const typeDefs = gql`
upsertWalletRecvLNDGRPC(walletId: ID, templateId: ID, enabled: Boolean!, networkTests: Boolean, socket: String!, macaroon: String!, cert: String): WalletRecvLNDGRPC! upsertWalletRecvLNDGRPC(walletId: ID, templateId: ID, enabled: Boolean!, socket: String!, macaroon: String!, cert: String): WalletRecvLNDGRPC!
upsertWalletSendLNC(walletId: ID, templateId: ID, enabled: Boolean!, pairingPhrase: VaultEntryInput!, localKey: VaultEntryInput!, remoteKey: VaultEntryInput!, serverHost: VaultEntryInput!): WalletSendLNC! upsertWalletSendLNC(walletId: ID, templateId: ID, enabled: Boolean!, pairingPhrase: VaultEntryInput!, localKey: VaultEntryInput!, remoteKey: VaultEntryInput!, serverHost: VaultEntryInput!): WalletSendLNC!
upsertWalletSendWebLN(walletId: ID, templateId: ID, enabled: Boolean!): WalletSendWebLN! upsertWalletSendWebLN(walletId: ID, templateId: ID, enabled: Boolean!): WalletSendWebLN!
+ upsertWalletRecvBolt12(walletId: ID, templateId: ID, enabled: Boolean!, networkTests: Boolean, offer: String!): WalletRecvBolt12! + upsertWalletRecvBolt12(walletId: ID, templateId: ID, enabled: Boolean!, offer: String!): WalletRecvBolt12!
removeWalletProtocol(id: ID!): Boolean removeWalletProtocol(id: ID!): Boolean
updateWalletEncryption(keyHash: String!, wallets: [WalletEncryptionUpdate!]!): Boolean updateWalletEncryption(keyHash: String!, wallets: [WalletEncryptionUpdate!]!): Boolean
updateKeyHash(keyHash: String!): Boolean updateKeyHash(keyHash: String!): Boolean
@ -340,8 +340,8 @@ index d1a65ff4..138d1a62 100644
` `
+ +
+export const UPSERT_WALLET_RECEIVE_BOLT12 = gql` +export const UPSERT_WALLET_RECEIVE_BOLT12 = gql`
+ mutation upsertWalletRecvBolt12($walletId: ID, $templateId: ID, $enabled: Boolean!, $networkTests: Boolean, $offer: String!) { + mutation upsertWalletRecvBolt12($walletId: ID, $templateId: ID, $enabled: Boolean!, $offer: String!) {
+ upsertWalletRecvBolt12(walletId: $walletId, templateId: $templateId, enabled: $enabled, networkTests: $networkTests, offer: $offer) { + upsertWalletRecvBolt12(walletId: $walletId, templateId: $templateId, enabled: $enabled, offer: $offer) {
+ id + id
+ } + }
+ } + }

View File

@ -1,29 +1,26 @@
import { gql } from '@apollo/client' import { gql } from '@apollo/client'
const sharedSend = { const shared = {
variables: '$walletId: ID, $templateName: ID, $enabled: Boolean!', variables: '$walletId: ID, $templateName: ID, $enabled: Boolean!',
arguments: 'walletId: $walletId, templateName: $templateName, enabled: $enabled' arguments: 'walletId: $walletId, templateName: $templateName, enabled: $enabled'
} }
const sharedRecv = {
variables: `${sharedSend.variables}, $networkTests: Boolean`,
arguments: `${sharedSend.arguments}, networkTests: $networkTests`
}
export const REMOVE_WALLET_PROTOCOL = gql` export const REMOVE_WALLET_PROTOCOL = gql`
mutation removeWalletProtocol($id: ID!) { mutation removeWalletProtocol($id: ID!) {
removeWalletProtocol(id: $id) removeWalletProtocol(id: $id)
} }
` `
// upserts
export const UPSERT_WALLET_SEND_LNBITS = gql` export const UPSERT_WALLET_SEND_LNBITS = gql`
mutation upsertWalletSendLNbits( mutation upsertWalletSendLNbits(
${sharedSend.variables}, ${shared.variables},
$url: String!, $url: String!,
$apiKey: VaultEntryInput! $apiKey: VaultEntryInput!
) { ) {
upsertWalletSendLNbits( upsertWalletSendLNbits(
${sharedSend.arguments} ${shared.arguments}
url: $url, url: $url,
apiKey: $apiKey apiKey: $apiKey
) { ) {
@ -34,12 +31,12 @@ export const UPSERT_WALLET_SEND_LNBITS = gql`
export const UPSERT_WALLET_RECEIVE_LNBITS = gql` export const UPSERT_WALLET_RECEIVE_LNBITS = gql`
mutation upsertWalletRecvLNbits( mutation upsertWalletRecvLNbits(
${sharedRecv.variables}, ${shared.variables},
$url: String!, $url: String!,
$apiKey: String! $apiKey: String!
) { ) {
upsertWalletRecvLNbits( upsertWalletRecvLNbits(
${sharedRecv.arguments}, ${shared.arguments},
url: $url, url: $url,
apiKey: $apiKey apiKey: $apiKey
) { ) {
@ -50,12 +47,12 @@ export const UPSERT_WALLET_RECEIVE_LNBITS = gql`
export const UPSERT_WALLET_SEND_PHOENIXD = gql` export const UPSERT_WALLET_SEND_PHOENIXD = gql`
mutation upsertWalletSendPhoenixd( mutation upsertWalletSendPhoenixd(
${sharedSend.variables}, ${shared.variables},
$url: String!, $url: String!,
$apiKey: VaultEntryInput! $apiKey: VaultEntryInput!
) { ) {
upsertWalletSendPhoenixd( upsertWalletSendPhoenixd(
${sharedSend.arguments}, ${shared.arguments},
url: $url, url: $url,
apiKey: $apiKey apiKey: $apiKey
) { ) {
@ -66,12 +63,12 @@ export const UPSERT_WALLET_SEND_PHOENIXD = gql`
export const UPSERT_WALLET_RECEIVE_PHOENIXD = gql` export const UPSERT_WALLET_RECEIVE_PHOENIXD = gql`
mutation upsertWalletRecvPhoenixd( mutation upsertWalletRecvPhoenixd(
${sharedRecv.variables}, ${shared.variables},
$url: String!, $url: String!,
$apiKey: String! $apiKey: String!
) { ) {
upsertWalletRecvPhoenixd( upsertWalletRecvPhoenixd(
${sharedRecv.arguments}, ${shared.arguments},
url: $url, url: $url,
apiKey: $apiKey apiKey: $apiKey
) { ) {
@ -82,12 +79,12 @@ export const UPSERT_WALLET_RECEIVE_PHOENIXD = gql`
export const UPSERT_WALLET_SEND_BLINK = gql` export const UPSERT_WALLET_SEND_BLINK = gql`
mutation upsertWalletSendBlink( mutation upsertWalletSendBlink(
${sharedSend.variables}, ${shared.variables},
$currency: VaultEntryInput!, $currency: VaultEntryInput!,
$apiKey: VaultEntryInput! $apiKey: VaultEntryInput!
) { ) {
upsertWalletSendBlink( upsertWalletSendBlink(
${sharedSend.arguments}, ${shared.arguments},
currency: $currency, currency: $currency,
apiKey: $apiKey apiKey: $apiKey
) { ) {
@ -98,12 +95,12 @@ export const UPSERT_WALLET_SEND_BLINK = gql`
export const UPSERT_WALLET_RECEIVE_BLINK = gql` export const UPSERT_WALLET_RECEIVE_BLINK = gql`
mutation upsertWalletRecvBlink( mutation upsertWalletRecvBlink(
${sharedRecv.variables}, ${shared.variables},
$currency: String!, $currency: String!,
$apiKey: String! $apiKey: String!
) { ) {
upsertWalletRecvBlink( upsertWalletRecvBlink(
${sharedRecv.arguments}, ${shared.arguments},
currency: $currency, currency: $currency,
apiKey: $apiKey apiKey: $apiKey
) { ) {
@ -114,11 +111,11 @@ export const UPSERT_WALLET_RECEIVE_BLINK = gql`
export const UPSERT_WALLET_RECEIVE_LIGHTNING_ADDRESS = gql` export const UPSERT_WALLET_RECEIVE_LIGHTNING_ADDRESS = gql`
mutation upsertWalletRecvLightningAddress( mutation upsertWalletRecvLightningAddress(
${sharedRecv.variables}, ${shared.variables},
$address: String! $address: String!
) { ) {
upsertWalletRecvLightningAddress( upsertWalletRecvLightningAddress(
${sharedRecv.arguments}, ${shared.arguments},
address: $address address: $address
) { ) {
id id
@ -128,11 +125,11 @@ export const UPSERT_WALLET_RECEIVE_LIGHTNING_ADDRESS = gql`
export const UPSERT_WALLET_SEND_NWC = gql` export const UPSERT_WALLET_SEND_NWC = gql`
mutation upsertWalletSendNWC( mutation upsertWalletSendNWC(
${sharedSend.variables}, ${shared.variables},
$url: VaultEntryInput! $url: VaultEntryInput!
) { ) {
upsertWalletSendNWC( upsertWalletSendNWC(
${sharedSend.arguments}, ${shared.arguments},
url: $url url: $url
) { ) {
id id
@ -142,11 +139,11 @@ export const UPSERT_WALLET_SEND_NWC = gql`
export const UPSERT_WALLET_RECEIVE_NWC = gql` export const UPSERT_WALLET_RECEIVE_NWC = gql`
mutation upsertWalletRecvNWC( mutation upsertWalletRecvNWC(
${sharedRecv.variables}, ${shared.variables},
$url: String! $url: String!
) { ) {
upsertWalletRecvNWC( upsertWalletRecvNWC(
${sharedRecv.arguments}, ${shared.arguments},
url: $url url: $url
) { ) {
id id
@ -156,13 +153,13 @@ export const UPSERT_WALLET_RECEIVE_NWC = gql`
export const UPSERT_WALLET_RECEIVE_CLN_REST = gql` export const UPSERT_WALLET_RECEIVE_CLN_REST = gql`
mutation upsertWalletRecvCLNRest( mutation upsertWalletRecvCLNRest(
${sharedRecv.variables}, ${shared.variables},
$socket: String!, $socket: String!,
$rune: String!, $rune: String!,
$cert: String $cert: String
) { ) {
upsertWalletRecvCLNRest( upsertWalletRecvCLNRest(
${sharedRecv.arguments}, ${shared.arguments},
socket: $socket, socket: $socket,
rune: $rune, rune: $rune,
cert: $cert cert: $cert
@ -174,13 +171,13 @@ export const UPSERT_WALLET_RECEIVE_CLN_REST = gql`
export const UPSERT_WALLET_RECEIVE_LND_GRPC = gql` export const UPSERT_WALLET_RECEIVE_LND_GRPC = gql`
mutation upsertWalletRecvLNDGRPC( mutation upsertWalletRecvLNDGRPC(
${sharedRecv.variables}, ${shared.variables},
$socket: String!, $socket: String!,
$macaroon: String!, $macaroon: String!,
$cert: String $cert: String
) { ) {
upsertWalletRecvLNDGRPC( upsertWalletRecvLNDGRPC(
${sharedRecv.arguments}, ${shared.arguments},
socket: $socket, socket: $socket,
macaroon: $macaroon, macaroon: $macaroon,
cert: $cert cert: $cert
@ -192,14 +189,14 @@ export const UPSERT_WALLET_RECEIVE_LND_GRPC = gql`
export const UPSERT_WALLET_SEND_LNC = gql` export const UPSERT_WALLET_SEND_LNC = gql`
mutation upsertWalletSendLNC( mutation upsertWalletSendLNC(
${sharedSend.variables}, ${shared.variables},
$pairingPhrase: VaultEntryInput!, $pairingPhrase: VaultEntryInput!,
$localKey: VaultEntryInput!, $localKey: VaultEntryInput!,
$remoteKey: VaultEntryInput!, $remoteKey: VaultEntryInput!,
$serverHost: VaultEntryInput! $serverHost: VaultEntryInput!
) { ) {
upsertWalletSendLNC( upsertWalletSendLNC(
${sharedSend.arguments}, ${shared.arguments},
pairingPhrase: $pairingPhrase, pairingPhrase: $pairingPhrase,
localKey: $localKey, localKey: $localKey,
remoteKey: $remoteKey, remoteKey: $remoteKey,
@ -212,12 +209,56 @@ export const UPSERT_WALLET_SEND_LNC = gql`
export const UPSERT_WALLET_SEND_WEBLN = gql` export const UPSERT_WALLET_SEND_WEBLN = gql`
mutation upsertWalletSendWebLN( mutation upsertWalletSendWebLN(
${sharedSend.variables} ${shared.variables}
) { ) {
upsertWalletSendWebLN( upsertWalletSendWebLN(
${sharedSend.arguments} ${shared.arguments}
) { ) {
id id
} }
} }
` `
// tests
export const TEST_WALLET_RECEIVE_NWC = gql`
mutation testWalletRecvNWC($url: String!) {
testWalletRecvNWC(url: $url)
}
`
export const TEST_WALLET_RECEIVE_LIGHTNING_ADDRESS = gql`
mutation testWalletRecvLightningAddress($address: String!) {
testWalletRecvLightningAddress(address: $address)
}
`
export const TEST_WALLET_RECEIVE_CLN_REST = gql`
mutation testWalletRecvCLNRest($socket: String!, $rune: String!, $cert: String) {
testWalletRecvCLNRest(socket: $socket, rune: $rune, cert: $cert)
}
`
export const TEST_WALLET_RECEIVE_LND_GRPC = gql`
mutation testWalletRecvLNDGRPC($socket: String!, $macaroon: String!, $cert: String) {
testWalletRecvLNDGRPC(socket: $socket, macaroon: $macaroon, cert: $cert)
}
`
export const TEST_WALLET_RECEIVE_PHOENIXD = gql`
mutation testWalletRecvPhoenixd($url: String!, $apiKey: String!) {
testWalletRecvPhoenixd(url: $url, apiKey: $apiKey)
}
`
export const TEST_WALLET_RECEIVE_LNBITS = gql`
mutation testWalletRecvLNbits($url: String!, $apiKey: String!) {
testWalletRecvLNbits(url: $url, apiKey: $apiKey)
}
`
export const TEST_WALLET_RECEIVE_BLINK = gql`
mutation testWalletRecvBlink($currency: String!, $apiKey: String!) {
testWalletRecvBlink(currency: $currency, apiKey: $apiKey)
}
`

View File

@ -19,9 +19,16 @@ import {
RESET_WALLETS, RESET_WALLETS,
DISABLE_PASSPHRASE_EXPORT, DISABLE_PASSPHRASE_EXPORT,
SET_WALLET_PRIORITIES, SET_WALLET_PRIORITIES,
UPDATE_KEY_HASH UPDATE_KEY_HASH,
TEST_WALLET_RECEIVE_LNBITS,
TEST_WALLET_RECEIVE_PHOENIXD,
TEST_WALLET_RECEIVE_BLINK,
TEST_WALLET_RECEIVE_LIGHTNING_ADDRESS,
TEST_WALLET_RECEIVE_NWC,
TEST_WALLET_RECEIVE_CLN_REST,
TEST_WALLET_RECEIVE_LND_GRPC
} from '@/wallets/client/fragments' } from '@/wallets/client/fragments'
import { useApolloClient, useMutation, useQuery } from '@apollo/client' import { gql, useApolloClient, useMutation, useQuery } from '@apollo/client'
import { useDecryption, useEncryption, useSetKey, useWalletLogger, useWalletsUpdatedAt, WalletStatus } from '@/wallets/client/hooks' import { useDecryption, useEncryption, useSetKey, useWalletLogger, useWalletsUpdatedAt, WalletStatus } from '@/wallets/client/hooks'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { import {
@ -144,10 +151,11 @@ export function useWalletQuery ({ id, name }) {
} }
export function useWalletProtocolUpsert (wallet, protocol) { export function useWalletProtocolUpsert (wallet, protocol) {
const mutation = getWalletProtocolMutation(protocol) const mutation = getWalletProtocolUpsertMutation(protocol)
const [mutate] = useMutation(mutation) const [mutate] = useMutation(mutation)
const { encryptConfig } = useEncryptConfig(protocol) const { encryptConfig } = useEncryptConfig(protocol)
const testSendPayment = useTestSendPayment(protocol) const testSendPayment = useTestSendPayment(protocol)
const testCreateInvoice = useTestCreateInvoice(protocol)
const logger = useWalletLogger(protocol) const logger = useWalletLogger(protocol)
return useCallback(async (values) => { return useCallback(async (values) => {
@ -158,11 +166,14 @@ export function useWalletProtocolUpsert (wallet, protocol) {
} }
// skip network tests if we're disabling the wallet // skip network tests if we're disabling the wallet
const networkTests = values.enabled if (values.enabled) {
if (networkTests) {
try { try {
const additionalValues = await testSendPayment(values) if (protocol.send) {
values = { ...values, ...additionalValues } const additionalValues = await testSendPayment(values)
values = { ...values, ...additionalValues }
} else {
await testCreateInvoice(values)
}
} catch (err) { } catch (err) {
logger.error(err.message) logger.error(err.message)
throw err throw err
@ -172,9 +183,6 @@ export function useWalletProtocolUpsert (wallet, protocol) {
const encrypted = await encryptConfig(values) const encrypted = await encryptConfig(values)
const variables = encrypted const variables = encrypted
if (!protocol.send) {
variables.networkTests = networkTests
}
if (isWallet(wallet)) { if (isWallet(wallet)) {
variables.walletId = wallet.id variables.walletId = wallet.id
} else { } else {
@ -194,7 +202,7 @@ export function useWalletProtocolUpsert (wallet, protocol) {
requestPersistentStorage() requestPersistentStorage()
return updatedWallet return updatedWallet
}, [wallet, protocol, logger, testSendPayment, encryptConfig, mutate]) }, [wallet, protocol, logger, testSendPayment, testCreateInvoice, encryptConfig, mutate])
} }
export function useLightningAddressUpsert () { export function useLightningAddressUpsert () {
@ -286,7 +294,12 @@ export function useSetWalletPriorities () {
}, [mutate, toaster]) }, [mutate, toaster])
} }
function getWalletProtocolMutation (protocol) { // we only have test mutations for receive protocols and useMutation throws if we pass null to it,
// so we use this placeholder mutation in such cases to respect the rules of hooks.
// (the mutation would throw if called but we make sure to never call it.)
const NOOP_MUTATION = gql`mutation noop { noop }`
function getWalletProtocolUpsertMutation (protocol) {
switch (protocol.name) { switch (protocol.name) {
case 'LNBITS': case 'LNBITS':
return protocol.send ? UPSERT_WALLET_SEND_LNBITS : UPSERT_WALLET_RECEIVE_LNBITS return protocol.send ? UPSERT_WALLET_SEND_LNBITS : UPSERT_WALLET_RECEIVE_LNBITS
@ -295,26 +308,47 @@ function getWalletProtocolMutation (protocol) {
case 'BLINK': case 'BLINK':
return protocol.send ? UPSERT_WALLET_SEND_BLINK : UPSERT_WALLET_RECEIVE_BLINK return protocol.send ? UPSERT_WALLET_SEND_BLINK : UPSERT_WALLET_RECEIVE_BLINK
case 'LN_ADDR': case 'LN_ADDR':
return protocol.send ? null : UPSERT_WALLET_RECEIVE_LIGHTNING_ADDRESS return protocol.send ? NOOP_MUTATION : UPSERT_WALLET_RECEIVE_LIGHTNING_ADDRESS
case 'NWC': case 'NWC':
return protocol.send ? UPSERT_WALLET_SEND_NWC : UPSERT_WALLET_RECEIVE_NWC return protocol.send ? UPSERT_WALLET_SEND_NWC : UPSERT_WALLET_RECEIVE_NWC
case 'CLN_REST': case 'CLN_REST':
return protocol.send ? null : UPSERT_WALLET_RECEIVE_CLN_REST return protocol.send ? NOOP_MUTATION : UPSERT_WALLET_RECEIVE_CLN_REST
case 'LND_GRPC': case 'LND_GRPC':
return protocol.send ? null : UPSERT_WALLET_RECEIVE_LND_GRPC return protocol.send ? NOOP_MUTATION : UPSERT_WALLET_RECEIVE_LND_GRPC
case 'LNC': case 'LNC':
return protocol.send ? UPSERT_WALLET_SEND_LNC : null return protocol.send ? UPSERT_WALLET_SEND_LNC : NOOP_MUTATION
case 'WEBLN': case 'WEBLN':
return protocol.send ? UPSERT_WALLET_SEND_WEBLN : null return protocol.send ? UPSERT_WALLET_SEND_WEBLN : NOOP_MUTATION
default: default:
return null return NOOP_MUTATION
}
}
function getWalletProtocolTestMutation (protocol) {
if (protocol.send) return NOOP_MUTATION
switch (protocol.name) {
case 'LNBITS':
return TEST_WALLET_RECEIVE_LNBITS
case 'PHOENIXD':
return TEST_WALLET_RECEIVE_PHOENIXD
case 'BLINK':
return TEST_WALLET_RECEIVE_BLINK
case 'LN_ADDR':
return TEST_WALLET_RECEIVE_LIGHTNING_ADDRESS
case 'NWC':
return TEST_WALLET_RECEIVE_NWC
case 'CLN_REST':
return TEST_WALLET_RECEIVE_CLN_REST
case 'LND_GRPC':
return TEST_WALLET_RECEIVE_LND_GRPC
default:
return NOOP_MUTATION
} }
} }
function useTestSendPayment (protocol) { function useTestSendPayment (protocol) {
return useCallback(async (values) => { return useCallback(async (values) => {
if (!protocol.send) return
return await protocolTestSendPayment( return await protocolTestSendPayment(
protocol, protocol,
values, values,
@ -323,6 +357,15 @@ function useTestSendPayment (protocol) {
}, [protocol]) }, [protocol])
} }
function useTestCreateInvoice (protocol) {
const mutation = getWalletProtocolTestMutation(protocol)
const [testCreateInvoice] = useMutation(mutation)
return useCallback(async (values) => {
return await testCreateInvoice({ variables: values })
}, [testCreateInvoice])
}
function useWalletDecryption () { function useWalletDecryption () {
const { decryptConfig, ready } = useDecryptConfig() const { decryptConfig, ready } = useDecryptConfig()
@ -452,7 +495,7 @@ export function useWalletMigrationMutation () {
} }
await client.mutate({ await client.mutate({
mutation: getWalletProtocolMutation(protocol), mutation: getWalletProtocolUpsertMutation(protocol),
variables: { variables: {
...(walletId ? { walletId } : { templateName }), ...(walletId ? { walletId } : { templateName }),
enabled, enabled,

View File

@ -76,6 +76,11 @@ export function protocolMutationName ({ name, send }) {
return `upsert${relationName.charAt(0).toUpperCase() + relationName.slice(1)}` return `upsert${relationName.charAt(0).toUpperCase() + relationName.slice(1)}`
} }
export function protocolTestMutationName ({ name, send }) {
const relationName = protocolRelationName({ name, send })
return `test${relationName.charAt(0).toUpperCase() + relationName.slice(1)}`
}
export function protocolFields ({ name, send }) { export function protocolFields ({ name, send }) {
return protocol({ name, send })?.fields || [] return protocol({ name, send })?.fields || []
} }

View File

@ -1,7 +1,7 @@
import { GqlAuthenticationError, GqlInputError } from '@/lib/error' import { GqlAuthenticationError, GqlInputError } from '@/lib/error'
import { validateSchema } from '@/lib/validate' import { validateSchema } from '@/lib/validate'
import protocols from '@/wallets/lib/protocols' import protocols from '@/wallets/lib/protocols'
import { protocolRelationName, isEncryptedField, protocolMutationName, protocolServerSchema } from '@/wallets/lib/util' import { protocolRelationName, isEncryptedField, protocolMutationName, protocolServerSchema, protocolTestMutationName } from '@/wallets/lib/util'
import { mapWalletResolveTypes } from '@/wallets/server/resolvers/util' import { mapWalletResolveTypes } from '@/wallets/server/resolvers/util'
import { protocolTestCreateInvoice } from '@/wallets/server/protocols' import { protocolTestCreateInvoice } from '@/wallets/server/protocols'
import { timeoutSignal, withTimeout } from '@/lib/time' import { timeoutSignal, withTimeout } from '@/lib/time'
@ -43,12 +43,23 @@ export const resolvers = {
}, },
Mutation: { Mutation: {
...Object.fromEntries( ...Object.fromEntries(
protocols.map(protocol => { protocols.reduce((acc, protocol) => {
return [ return [
protocolMutationName(protocol), ...acc,
upsertWalletProtocol(protocol) [
protocolMutationName(protocol),
upsertWalletProtocol(protocol)
],
...(protocol.send
? []
: [
[
protocolTestMutationName(protocol),
testWalletProtocol(protocol)
]
])
] ]
}) }, [])
), ),
addWalletLog, addWalletLog,
removeWalletProtocol, removeWalletProtocol,
@ -56,12 +67,43 @@ export const resolvers = {
} }
} }
function testWalletProtocol (protocol) {
return async (parent, args, { me, models, tx }) => {
if (!me) {
throw new GqlAuthenticationError()
}
if (protocol.send) {
throw new GqlInputError('can only test receive protocols')
}
let invoice
try {
invoice = await withTimeout(
protocolTestCreateInvoice(
protocol,
args,
{ signal: timeoutSignal(WALLET_CREATE_INVOICE_TIMEOUT_MS) }
),
WALLET_CREATE_INVOICE_TIMEOUT_MS
)
} catch (e) {
throw new GqlInputError('failed to create invoice: ' + e.message)
}
if (!invoice || !invoice.startsWith('lnbc')) {
throw new GqlInputError('wallet returned invalid invoice')
}
return true
}
}
export function upsertWalletProtocol (protocol) { export function upsertWalletProtocol (protocol) {
return async (parent, { return async (parent, {
walletId, walletId,
templateName, templateName,
enabled, enabled,
networkTests = true,
ignoreKeyHash = false, ignoreKeyHash = false,
...args ...args
}, { me, models, tx }) => { }, { me, models, tx }) => {
@ -84,22 +126,6 @@ export function upsertWalletProtocol (protocol) {
throw new GqlInputError(e.message) throw new GqlInputError(e.message)
} }
if (!protocol.send && networkTests) {
let invoice
try {
invoice = await withTimeout(
protocolTestCreateInvoice(protocol, args, { signal: timeoutSignal(WALLET_CREATE_INVOICE_TIMEOUT_MS) }),
WALLET_CREATE_INVOICE_TIMEOUT_MS
)
} catch (e) {
throw new GqlInputError('failed to create test invoice: ' + e.message)
}
if (!invoice || !invoice.startsWith('lnbc')) {
throw new GqlInputError('wallet returned invalid invoice')
}
}
const relation = protocolRelationName(protocol) const relation = protocolRelationName(protocol)
function dataFragment (args, type) { function dataFragment (args, type) {

View File

@ -134,7 +134,7 @@ async function updateWalletEncryption (parent, { keyHash, wallets }, { me, model
for (const { id: walletId, protocols } of wallets) { for (const { id: walletId, protocols } of wallets) {
for (const { name, send, config } of protocols) { for (const { name, send, config } of protocols) {
const mutation = upsertWalletProtocol({ name, send }) const mutation = upsertWalletProtocol({ name, send })
await mutation(parent, { walletId, networkTests: false, ignoreKeyHash: true, ...config }, { me, models: tx, tx }) await mutation(parent, { walletId, ignoreKeyHash: true, ...config }, { me, models: tx, tx })
} }
} }