From 147c62a66e12fde4a7871b34ee90f48def25275e Mon Sep 17 00:00:00 2001 From: Juan P Lopez Date: Mon, 19 Feb 2024 08:52:22 -0500 Subject: [PATCH] feat(core): add transactionsByPaymentRequest query --- bats/core/api/ln-receive.bats | 19 ++++++ ...sactions-for-wallet-by-payment-request.gql | 58 +++++++++++++++++++ .../get-transactions-by-payment-request.ts | 33 +++++++++++ core/api/src/app/wallets/index.ts | 1 + .../query/transactions-by-payment-request.ts | 27 +++++++++ .../graphql/shared/types/object/btc-wallet.ts | 38 ++++++++---- .../graphql/shared/types/object/usd-wallet.ts | 42 ++++++++++---- 7 files changed, 196 insertions(+), 22 deletions(-) create mode 100644 bats/gql/transactions-for-wallet-by-payment-request.gql create mode 100644 core/api/src/app/wallets/get-transactions-by-payment-request.ts create mode 100644 core/api/src/graphql/admin/root/query/transactions-by-payment-request.ts diff --git a/bats/core/api/ln-receive.bats b/bats/core/api/ln-receive.bats index fc7790d7d8..ee7f2fc5b2 100644 --- a/bats/core/api/ln-receive.bats +++ b/bats/core/api/ln-receive.bats @@ -100,6 +100,25 @@ usd_amount=50 transaction_id="$(graphql_output '.data.me.defaultAccount.walletById.transactionsByPaymentHash[0].id')" + # Get transaction by payment request + variables=$( + jq -n \ + --arg wallet_id "$(read_value $btc_wallet_name)" \ + --arg payment_request "$payment_request" \ + '{walletId: $wallet_id, paymentRequest: $payment_request}' + ) + + exec_graphql "$token_name" 'transactions-for-wallet-by-payment-request' "$variables" + + query_payment_hash="$(graphql_output '.data.me.defaultAccount.walletById.transactionsByPaymentRequest[0].initiationVia.paymentHash')" + [[ "${query_payment_hash}" == "${payment_hash}" ]] || exit 1 + + query_payment_request="$(graphql_output '.data.me.defaultAccount.walletById.transactionsByPaymentRequest[0].initiationVia.paymentRequest')" + [[ "${query_payment_request}" == "${payment_request}" ]] || exit 1 + + query_transaction_id="$(graphql_output '.data.me.defaultAccount.walletById.transactionsByPaymentRequest[0].id')" + [[ "${query_transaction_id}" == "${transaction_id}" ]] || exit 1 + # Get transaction by tx id variables=$( jq -n \ diff --git a/bats/gql/transactions-for-wallet-by-payment-request.gql b/bats/gql/transactions-for-wallet-by-payment-request.gql new file mode 100644 index 0000000000..54b0f08042 --- /dev/null +++ b/bats/gql/transactions-for-wallet-by-payment-request.gql @@ -0,0 +1,58 @@ +query transactionsForWalletByPaymentRequest( + $walletId: WalletId! + $paymentRequest: PaymentRequest! +) { + me { + defaultAccount { + displayCurrency + walletById(walletId: $walletId) { + id + transactionsByPaymentRequest(paymentRequest: $paymentRequest) { + __typename + id + status + direction + memo + createdAt + settlementAmount + settlementFee + settlementDisplayAmount + settlementDisplayFee + settlementDisplayCurrency + settlementCurrency + settlementPrice { + base + offset + } + initiationVia { + __typename + ... on InitiationViaIntraLedger { + counterPartyWalletId + counterPartyUsername + } + ... on InitiationViaLn { + paymentHash + paymentRequest + } + ... on InitiationViaOnChain { + address + } + } + settlementVia { + __typename + ... on SettlementViaIntraLedger { + counterPartyWalletId + counterPartyUsername + } + ... on SettlementViaLn { + preImage + } + ... on SettlementViaOnChain { + transactionHash + } + } + } + } + } + } +} diff --git a/core/api/src/app/wallets/get-transactions-by-payment-request.ts b/core/api/src/app/wallets/get-transactions-by-payment-request.ts new file mode 100644 index 0000000000..53b4d12944 --- /dev/null +++ b/core/api/src/app/wallets/get-transactions-by-payment-request.ts @@ -0,0 +1,33 @@ +import { + getTransactionsByHash, + getTransactionsForWalletByPaymentHash, +} from "./get-transactions-by-hash" + +import { decodeInvoice } from "@/domain/bitcoin/lightning" + +export const getTransactionsForWalletByPaymentRequest = async ({ + walletId, + uncheckedPaymentRequest, +}: { + walletId: WalletId + uncheckedPaymentRequest: string +}): Promise => { + const decodedInvoice = decodeInvoice(uncheckedPaymentRequest) + if (decodedInvoice instanceof Error) return decodedInvoice + + return getTransactionsForWalletByPaymentHash({ + walletId, + paymentHash: decodedInvoice.paymentHash, + }) +} + +export const getTransactionsByPaymentRequest = async ({ + uncheckedPaymentRequest, +}: { + uncheckedPaymentRequest: string +}): Promise => { + const decodedInvoice = decodeInvoice(uncheckedPaymentRequest) + if (decodedInvoice instanceof Error) return decodedInvoice + + return getTransactionsByHash(decodedInvoice.paymentHash) +} diff --git a/core/api/src/app/wallets/index.ts b/core/api/src/app/wallets/index.ts index 21da48d6d9..1b5b935153 100644 --- a/core/api/src/app/wallets/index.ts +++ b/core/api/src/app/wallets/index.ts @@ -11,6 +11,7 @@ export * from "./get-transaction-by-id" export * from "./get-transaction-by-journal-id" export * from "./get-transactions-by-addresses" export * from "./get-transactions-by-hash" +export * from "./get-transactions-by-payment-request" export * from "./get-transactions-for-wallet" export * from "./handle-held-invoices" export * from "./register-broadcasted-payout-txn" diff --git a/core/api/src/graphql/admin/root/query/transactions-by-payment-request.ts b/core/api/src/graphql/admin/root/query/transactions-by-payment-request.ts new file mode 100644 index 0000000000..d9c2f49abb --- /dev/null +++ b/core/api/src/graphql/admin/root/query/transactions-by-payment-request.ts @@ -0,0 +1,27 @@ +import { GT } from "@/graphql/index" + +import { Wallets } from "@/app" +import { mapError } from "@/graphql/error-map" +import Transaction from "@/graphql/shared/types/object/transaction" +import LnPaymentRequest from "@/graphql/shared/types/scalar/ln-payment-request" + +const TransactionsByPaymentRequestQuery = GT.Field({ + type: GT.List(Transaction), + args: { + paymentRequest: { type: GT.NonNull(LnPaymentRequest) }, + }, + resolve: async (_, { paymentRequest }) => { + if (paymentRequest instanceof Error) throw paymentRequest + + const ledgerTxs = await Wallets.getTransactionsByPaymentRequest({ + uncheckedPaymentRequest: paymentRequest, + }) + if (ledgerTxs instanceof Error) { + throw mapError(ledgerTxs) + } + + return ledgerTxs + }, +}) + +export default TransactionsByPaymentRequestQuery diff --git a/core/api/src/graphql/shared/types/object/btc-wallet.ts b/core/api/src/graphql/shared/types/object/btc-wallet.ts index d8b1480ffa..af382eac70 100644 --- a/core/api/src/graphql/shared/types/object/btc-wallet.ts +++ b/core/api/src/graphql/shared/types/object/btc-wallet.ts @@ -1,26 +1,21 @@ import IWallet from "../abstract/wallet" - +import PaymentHash from "../scalar/payment-hash" import SignedAmount from "../scalar/signed-amount" - import WalletCurrency from "../scalar/wallet-currency" - import OnChainAddress from "../scalar/on-chain-address" - -import PaymentHash from "../scalar/payment-hash" - +import LnPaymentRequest from "../scalar/ln-payment-request" import IInvoice, { IInvoiceConnection } from "../abstract/invoice" import Transaction, { TransactionConnection } from "./transaction" -import { GT } from "@/graphql/index" +import { WalletCurrency as WalletCurrencyDomain } from "@/domain/shared" + import { normalizePaymentAmount } from "@/graphql/shared/root/mutation" import { connectionArgs } from "@/graphql/connections" +import { GT } from "@/graphql/index" import { mapError } from "@/graphql/error-map" - import { Wallets } from "@/app" -import { WalletCurrency as WalletCurrencyDomain } from "@/domain/shared" - const BtcWallet = GT.Object({ name: "BTCWallet", description: @@ -206,6 +201,29 @@ const BtcWallet = GT.Object({ return transactions }, }, + transactionsByPaymentRequest: { + type: GT.NonNullList(Transaction), + args: { + paymentRequest: { + type: GT.NonNull(LnPaymentRequest), + }, + }, + resolve: async (source, args) => { + const { paymentRequest } = args + if (paymentRequest instanceof Error) throw paymentRequest + + const transactions = await Wallets.getTransactionsForWalletByPaymentRequest({ + walletId: source.id, + uncheckedPaymentRequest: paymentRequest, + }) + + if (transactions instanceof Error) { + throw mapError(transactions) + } + + return transactions + }, + }, transactionById: { type: GT.NonNull(Transaction), args: { diff --git a/core/api/src/graphql/shared/types/object/usd-wallet.ts b/core/api/src/graphql/shared/types/object/usd-wallet.ts index 0ce1882028..dde420afac 100644 --- a/core/api/src/graphql/shared/types/object/usd-wallet.ts +++ b/core/api/src/graphql/shared/types/object/usd-wallet.ts @@ -1,26 +1,21 @@ import IWallet from "../abstract/wallet" - -import WalletCurrency from "../scalar/wallet-currency" - +import PaymentHash from "../scalar/payment-hash" import SignedAmount from "../scalar/signed-amount" - +import WalletCurrency from "../scalar/wallet-currency" import OnChainAddress from "../scalar/on-chain-address" - -import PaymentHash from "../scalar/payment-hash" - +import LnPaymentRequest from "../scalar/ln-payment-request" import IInvoice, { IInvoiceConnection } from "../abstract/invoice" import Transaction, { TransactionConnection } from "./transaction" -import { GT } from "@/graphql/index" -import { connectionArgs } from "@/graphql/connections" +import { WalletCurrency as WalletCurrencyDomain } from "@/domain/shared" + import { normalizePaymentAmount } from "@/graphql/shared/root/mutation" +import { connectionArgs } from "@/graphql/connections" +import { GT } from "@/graphql/index" import { mapError } from "@/graphql/error-map" - import { Wallets } from "@/app" -import { WalletCurrency as WalletCurrencyDomain } from "@/domain/shared" - const UsdWallet = GT.Object({ name: "UsdWallet", description: @@ -204,6 +199,29 @@ const UsdWallet = GT.Object({ return transactions }, }, + transactionsByPaymentRequest: { + type: GT.NonNullList(Transaction), + args: { + paymentRequest: { + type: GT.NonNull(LnPaymentRequest), + }, + }, + resolve: async (source, args) => { + const { paymentRequest } = args + if (paymentRequest instanceof Error) throw paymentRequest + + const transactions = await Wallets.getTransactionsForWalletByPaymentRequest({ + walletId: source.id, + uncheckedPaymentRequest: paymentRequest, + }) + + if (transactions instanceof Error) { + throw mapError(transactions) + } + + return transactions + }, + }, transactionById: { type: GT.NonNull(Transaction), args: {