Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add pending tx queries #3488

Merged
merged 2 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions core/api/dev/apollo-federation/supergraph.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface Account
level: AccountLevel!
limits: AccountLimits!
notificationSettings: NotificationSettings!
pendingTransactions(walletIds: [WalletId]): [Transaction!]!
realtimePrice: RealtimePrice!
transactions(
"""Returns the items in the list that come after the specified cursor."""
Expand Down Expand Up @@ -221,6 +222,11 @@ type BTCWallet implements Wallet

"""An unconfirmed incoming onchain balance."""
pendingIncomingBalance: SignedAmount!
pendingTransactions: [Transaction!]!
pendingTransactionsByAddress(
"""Returns the items that include this address."""
address: OnChainAddress!
): [Transaction!]!
transactionById(transactionId: ID!): Transaction!

"""A list of BTC transactions associated with this wallet."""
Expand Down Expand Up @@ -344,6 +350,7 @@ type ConsumerAccount implements Account
level: AccountLevel!
limits: AccountLimits!
notificationSettings: NotificationSettings!
pendingTransactions(walletIds: [WalletId]): [Transaction!]!

"""List the quiz questions of the consumer account"""
quiz: [Quiz!]!
Expand Down Expand Up @@ -1656,6 +1663,11 @@ type UsdWallet implements Wallet

"""An unconfirmed incoming onchain balance."""
pendingIncomingBalance: SignedAmount!
pendingTransactions: [Transaction!]!
pendingTransactionsByAddress(
"""Returns the items that include this address."""
address: OnChainAddress!
): [Transaction!]!
transactionById(transactionId: ID!): Transaction!
transactions(
"""Returns the items in the list that come after the specified cursor."""
Expand Down Expand Up @@ -1964,6 +1976,25 @@ interface Wallet
paymentHash: PaymentHash!
): Invoice!
pendingIncomingBalance: SignedAmount!

"""
Pending OnChain transactions. When transactions
are confirmed they will receive a new id and be found in the transactions
list. Transactions are ordered anti-chronologically,
ie: the newest transaction will be first
"""
pendingTransactions: [Transaction!]!

"""
Pending OnChain transactions. When transactions
are confirmed they will receive a new id and be found in the transactions
list. Transactions are ordered anti-chronologically,
ie: the newest transaction will be first
"""
pendingTransactionsByAddress(
UncleSamtoshi marked this conversation as resolved.
Show resolved Hide resolved
"""Returns the items that include this address."""
address: OnChainAddress!
): [Transaction!]!
transactionById(transactionId: ID!): Transaction!

"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { getPendingOnChainTransactionsForWallets } from "../wallets/get-pending-onchain-transactions-for-wallets"

import { RepositoryError } from "@/domain/errors"
import { checkedToWalletId } from "@/domain/wallets"
import { WalletsRepository } from "@/services/mongoose"

export const getPendingOnChainTransactionsForAccountByWalletIds = async ({
account,
walletIds,
}: {
account: Account
walletIds?: string[]
}): Promise<WalletOnChainSettledTransaction[] | ApplicationError> => {
const walletsRepo = WalletsRepository()

const accountWallets = await walletsRepo.listByAccountId(account.id)
if (accountWallets instanceof RepositoryError) return accountWallets

if (!walletIds) {
return getPendingOnChainTransactionsForWallets({ wallets: accountWallets })
}

const checkedWalletIds: WalletId[] = []

for (const walletId of walletIds) {
const checkedWalletId = checkedToWalletId(walletId)
if (checkedWalletId instanceof Error) return checkedWalletId
checkedWalletIds.push(checkedWalletId)
}

const selectedWallets = accountWallets.filter((wallet) =>
checkedWalletIds.includes(wallet.id),
)

return getPendingOnChainTransactionsForWallets({ wallets: selectedWallets })
}
1 change: 1 addition & 0 deletions core/api/src/app/accounts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export * from "./disable-notification-category"
export * from "./enable-notification-category"
export * from "./enable-notification-channel"
export * from "./disable-notification-channel"
export * from "./get-pending-onchain-transactions-for-account"

const accounts = AccountsRepository()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { CouldNotFindError } from "@/domain/errors"

import { WalletOnChainPendingReceiveRepository } from "@/services/mongoose"

export const getPendingOnChainTransactionsForWallets = async ({
wallets,
}: {
wallets: Wallet[]
}): Promise<WalletOnChainSettledTransaction[] | ApplicationError> => {
const walletIds = wallets.map((wallet) => wallet.id)

const pendingHistory = await WalletOnChainPendingReceiveRepository().listByWalletIds({
walletIds,
})

if (pendingHistory instanceof CouldNotFindError) {
return []
}

return pendingHistory
}
25 changes: 25 additions & 0 deletions core/api/src/app/wallets/get-pending-transactions-by-addresses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { CouldNotFindError } from "@/domain/errors"

import { WalletOnChainPendingReceiveRepository } from "@/services/mongoose"

export const getPendingTransactionsForWalletsByAddresses = async ({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know wallets are passed from source but we must enforce in app layer that wallets belong the user/account (similar to logic in getPendingOnChainTransactionsForAccountByWalletIds)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont necessarily agree with that. The function does what it says which is getPendingTransactionsForWalletsByAddress. It's different than the getPendingOnChainTransactionsForAccountByWalletIds which says its getting them for a specific account and therefore must verify that the account owns the wallets. I think this is a pretty common pattern across the app layer.

wallets,
addresses,
}: {
wallets: Wallet[]
addresses: OnChainAddress[]
}): Promise<WalletOnChainSettledTransaction[] | ApplicationError> => {
const walletIds = wallets.map((wallet) => wallet.id)

const pendingHistory =
await WalletOnChainPendingReceiveRepository().listByWalletIdsAndAddresses({
walletIds,
addresses,
})

if (pendingHistory instanceof CouldNotFindError) {
return []
}

return pendingHistory
}
2 changes: 2 additions & 0 deletions core/api/src/app/wallets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export * from "./update-legacy-on-chain-receipt"
export * from "./update-pending-invoices"
export * from "./validate"
export * from "./get-invoice-for-wallet-by-hash"
export * from "./get-pending-onchain-transactions-for-wallets"
export * from "./get-pending-transactions-by-addresses"

import { WalletsRepository } from "@/services/mongoose"

Expand Down
29 changes: 29 additions & 0 deletions core/api/src/graphql/admin/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ type BTCWallet implements Wallet {

"""An unconfirmed incoming onchain balance."""
pendingIncomingBalance: SignedAmount!
pendingTransactions: [Transaction!]!
pendingTransactionsByAddress(
"""Returns the items that include this address."""
address: OnChainAddress!
): [Transaction!]!
transactionById(transactionId: ID!): Transaction!

"""A list of BTC transactions associated with this wallet."""
Expand Down Expand Up @@ -424,6 +429,11 @@ type UsdWallet implements Wallet {

"""An unconfirmed incoming onchain balance."""
pendingIncomingBalance: SignedAmount!
pendingTransactions: [Transaction!]!
pendingTransactionsByAddress(
UncleSamtoshi marked this conversation as resolved.
Show resolved Hide resolved
"""Returns the items that include this address."""
address: OnChainAddress!
): [Transaction!]!
transactionById(transactionId: ID!): Transaction!
transactions(
"""Returns the items in the list that come after the specified cursor."""
Expand Down Expand Up @@ -480,6 +490,25 @@ interface Wallet {
paymentHash: PaymentHash!
): Invoice!
pendingIncomingBalance: SignedAmount!

"""
Pending OnChain transactions. When transactions
are confirmed they will receive a new id and be found in the transactions
list. Transactions are ordered anti-chronologically,
ie: the newest transaction will be first
"""
pendingTransactions: [Transaction!]!

"""
Pending OnChain transactions. When transactions
are confirmed they will receive a new id and be found in the transactions
list. Transactions are ordered anti-chronologically,
ie: the newest transaction will be first
"""
pendingTransactionsByAddress(
"""Returns the items that include this address."""
address: OnChainAddress!
): [Transaction!]!
transactionById(transactionId: ID!): Transaction!

"""
Expand Down
31 changes: 31 additions & 0 deletions core/api/src/graphql/public/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface Account {
level: AccountLevel!
limits: AccountLimits!
notificationSettings: NotificationSettings!
pendingTransactions(walletIds: [WalletId]): [Transaction!]!
realtimePrice: RealtimePrice!
transactions(
"""Returns the items in the list that come after the specified cursor."""
Expand Down Expand Up @@ -126,6 +127,11 @@ type BTCWallet implements Wallet {

"""An unconfirmed incoming onchain balance."""
pendingIncomingBalance: SignedAmount!
pendingTransactions: [Transaction!]!
pendingTransactionsByAddress(
"""Returns the items that include this address."""
address: OnChainAddress!
): [Transaction!]!
transactionById(transactionId: ID!): Transaction!

"""A list of BTC transactions associated with this wallet."""
Expand Down Expand Up @@ -227,6 +233,7 @@ type ConsumerAccount implements Account {
level: AccountLevel!
limits: AccountLimits!
notificationSettings: NotificationSettings!
pendingTransactions(walletIds: [WalletId]): [Transaction!]!

"""List the quiz questions of the consumer account"""
quiz: [Quiz!]!
Expand Down Expand Up @@ -1269,6 +1276,11 @@ type UsdWallet implements Wallet {

"""An unconfirmed incoming onchain balance."""
pendingIncomingBalance: SignedAmount!
pendingTransactions: [Transaction!]!
pendingTransactionsByAddress(
"""Returns the items that include this address."""
address: OnChainAddress!
): [Transaction!]!
transactionById(transactionId: ID!): Transaction!
transactions(
"""Returns the items in the list that come after the specified cursor."""
Expand Down Expand Up @@ -1510,6 +1522,25 @@ interface Wallet {
paymentHash: PaymentHash!
): Invoice!
pendingIncomingBalance: SignedAmount!

"""
Pending OnChain transactions. When transactions
are confirmed they will receive a new id and be found in the transactions
list. Transactions are ordered anti-chronologically,
ie: the newest transaction will be first
"""
pendingTransactions: [Transaction!]!

"""
Pending OnChain transactions. When transactions
are confirmed they will receive a new id and be found in the transactions
list. Transactions are ordered anti-chronologically,
ie: the newest transaction will be first
"""
pendingTransactionsByAddress(
"""Returns the items that include this address."""
address: OnChainAddress!
): [Transaction!]!
transactionById(transactionId: ID!): Transaction!

"""
Expand Down
12 changes: 11 additions & 1 deletion core/api/src/graphql/public/types/abstract/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import WalletId from "@/graphql/shared/types/scalar/wallet-id"
import AccountLimits from "@/graphql/public/types/object/account-limits"
import RealtimePrice from "@/graphql/public/types/object/realtime-price"
import DisplayCurrency from "@/graphql/shared/types/scalar/display-currency"
import { TransactionConnection } from "@/graphql/shared/types/object/transaction"
import Transaction, {
TransactionConnection,
} from "@/graphql/shared/types/object/transaction"

const IAccount = GT.Interface({
name: "Account",
Expand Down Expand Up @@ -59,6 +61,14 @@ const IAccount = GT.Interface({
},
},
},
pendingTransactions: {
type: GT.NonNullList(Transaction),
args: {
walletIds: {
type: GT.List(WalletId),
},
},
},
notificationSettings: {
type: GT.NonNull(NotificationSettings),
},
Expand Down
26 changes: 25 additions & 1 deletion core/api/src/graphql/public/types/object/business-account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import DisplayCurrency from "../../../shared/types/scalar/display-currency"

import AccountLevel from "../../../shared/types/scalar/account-level"

import { TransactionConnection } from "../../../shared/types/object/transaction"
import Transaction, {
TransactionConnection,
} from "../../../shared/types/object/transaction"

import RealtimePrice from "./realtime-price"
import { NotificationSettings } from "./notification-settings"
Expand Down Expand Up @@ -158,6 +160,28 @@ const BusinessAccount = GT.Object({
)
},
},
pendingTransactions: {
type: GT.NonNullList(Transaction),
args: {
walletIds: {
type: GT.List(WalletId),
},
},
resolve: async (source, args) => {
const { walletIds } = args

const transactions =
await Accounts.getPendingOnChainTransactionsForAccountByWalletIds({
account: source,
walletIds,
})

if (transactions instanceof Error) {
throw mapError(transactions)
}
return transactions
},
},
notificationSettings: {
type: GT.NonNull(NotificationSettings),
resolve: (source) => source.notificationSettings,
Expand Down
26 changes: 25 additions & 1 deletion core/api/src/graphql/public/types/object/consumer-account.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import AccountLevel from "../../../shared/types/scalar/account-level"

import { TransactionConnection } from "../../../shared/types/object/transaction"
import Transaction, {
TransactionConnection,
} from "../../../shared/types/object/transaction"

import AccountLimits from "./account-limits"

Expand Down Expand Up @@ -206,6 +208,28 @@ const ConsumerAccount = GT.Object<Account, GraphQLPublicContextAuth>({
)
},
},
pendingTransactions: {
type: GT.NonNullList(Transaction),
args: {
walletIds: {
type: GT.List(WalletId),
},
},
resolve: async (source, args) => {
const { walletIds } = args

const transactions =
await Accounts.getPendingOnChainTransactionsForAccountByWalletIds({
account: source,
walletIds,
})

if (transactions instanceof Error) {
throw mapError(transactions)
}
return transactions
},
},

notificationSettings: {
type: GT.NonNull(NotificationSettings),
Expand Down
Loading
Loading