Skip to content

Commit

Permalink
feat(core): add new 'AccountDefaultWallet' with UsernameWithFlags type
Browse files Browse the repository at this point in the history
  • Loading branch information
vindard committed Feb 15, 2024
1 parent e4b9305 commit 9968417
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 33 deletions.
60 changes: 49 additions & 11 deletions bats/core/api/public-ln-receive.bats
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ usd_amount=50
--arg username "$username" \
'{username: $username}'
)
exec_graphql 'anon' 'account-default-wallet' "$variables"
receiver_wallet_id="$(graphql_output '.data.accountDefaultWallet.id')"
exec_graphql 'anon' 'account-default-wallet-by-username' "$variables"
receiver_wallet_id="$(graphql_output '.data.accountDefaultWalletByUsername.id')"
[[ "$receiver_wallet_id" == "$(read_value $btc_wallet_name)" ]] || exit 1

# Fetch usd-wallet-id from username
Expand All @@ -57,8 +57,8 @@ usd_amount=50
--arg username "$username" \
'{username: $username, walletCurrency: "USD"}'
)
exec_graphql 'anon' 'account-default-wallet' "$variables"
receiver_wallet_id="$(graphql_output '.data.accountDefaultWallet.id')"
exec_graphql 'anon' 'account-default-wallet-by-username' "$variables"
receiver_wallet_id="$(graphql_output '.data.accountDefaultWalletByUsername.id')"
[[ "$receiver_wallet_id" == "$(read_value $usd_wallet_name)" ]] || exit 1
}

Expand All @@ -84,8 +84,8 @@ usd_amount=50
--arg username "$username" \
'{username: $username}'
)
exec_graphql 'anon' 'account-default-wallet' "$variables"
receiver_wallet_id="$(graphql_output '.data.accountDefaultWallet.id')"
exec_graphql 'anon' 'account-default-wallet-by-username' "$variables"
receiver_wallet_id="$(graphql_output '.data.accountDefaultWalletByUsername.id')"
[[ "$receiver_wallet_id" == "$(read_value $usd_wallet_name)" ]] || exit 1

# Fetch btc-wallet-id from username
Expand All @@ -94,17 +94,55 @@ usd_amount=50
--arg username "$username" \
'{username: $username, walletCurrency: "BTC"}'
)
exec_graphql 'anon' 'account-default-wallet' "$variables"
receiver_wallet_id="$(graphql_output '.data.accountDefaultWallet.id')"
exec_graphql 'anon' 'account-default-wallet-by-username' "$variables"
receiver_wallet_id="$(graphql_output '.data.accountDefaultWalletByUsername.id')"
[[ "$receiver_wallet_id" == "$(read_value $btc_wallet_name)" ]] || exit 1
}

@test "public-ln-receive: account details - can fetch with usd flag from username" {
token_name=$ALICE
btc_wallet_name="$token_name.btc_wallet_id"
usd_wallet_name="$token_name.usd_wallet_id"
local username="$(read_value $token_name.username)"

# Change default wallet to btc
variables=$(
jq -n \
--arg wallet_id "$(read_value $btc_wallet_name)" \
'{input: {walletId: $wallet_id}}'
)
exec_graphql "$token_name" 'account-update-default-wallet-id' "$variables"
updated_wallet_id="$(graphql_output '.data.accountUpdateDefaultWalletId.account.defaultWalletId')"
[[ "$updated_wallet_id" == "$(read_value $btc_wallet_name)" ]] || exit 1

# Fetch default btc-wallet-id from username
variables=$(
jq -n \
--arg username "$username" \
'{username: $username}'
)
exec_graphql 'anon' 'account-default-wallet-by-username' "$variables"
receiver_wallet_id="$(graphql_output '.data.accountDefaultWalletByUsername.id')"
[[ "$receiver_wallet_id" == "$(read_value $btc_wallet_name)" ]] || exit 1

# Fetch usd-wallet-id from username via '+usd' flag
variables=$(
jq -n \
--arg username "$username+usd" \
'{username: $username}'
)
exec_graphql 'anon' 'account-default-wallet-by-username' "$variables"
receiver_wallet_id="$(graphql_output '.data.accountDefaultWalletByUsername.id')"
[[ "$receiver_wallet_id" == "$(read_value $usd_wallet_name)" ]] || exit 1
}

@test "public-ln-receive: account details - return error for invalid username" {
exec_graphql 'anon' 'account-default-wallet' '{"username": "incorrectly-formatted"}'
exec_graphql 'anon' 'account-default-wallet-by-username' '{"username": "incorrectly-formatted"}'
graphql_output
error_msg="$(graphql_output '.errors[0].message')"
[[ "$error_msg" == "Invalid value for Username" ]] || exit 1
[[ "$error_msg" == "Invalid value for Username with optional flags" ]] || exit 1

exec_graphql 'anon' 'account-default-wallet' '{"username": "idontexist"}'
exec_graphql 'anon' 'account-default-wallet-by-username' '{"username": "idontexist"}'
error_msg="$(graphql_output '.errors[0].message')"
[[ "$error_msg" == "Account does not exist for username idontexist" ]] || exit 1
}
Expand Down
12 changes: 12 additions & 0 deletions bats/gql/account-default-wallet-by-username.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
query accountDefaultWalletByUsername(
$username: UsernameWithFlags!
$walletCurrency: WalletCurrency
) {
accountDefaultWalletByUsername(
username: $username
walletCurrency: $walletCurrency
) {
id
currency
}
}
6 changes: 0 additions & 6 deletions bats/gql/account-default-wallet.gql

This file was deleted.

7 changes: 6 additions & 1 deletion core/api/dev/apollo-federation/supergraph.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1562,7 +1562,8 @@ type Query
@join__type(graph: NOTIFICATIONS)
@join__type(graph: PUBLIC)
{
accountDefaultWallet(username: Username!, walletCurrency: WalletCurrency): PublicWallet! @join__field(graph: PUBLIC)
accountDefaultWallet(username: Username!, walletCurrency: WalletCurrency): PublicWallet! @join__field(graph: PUBLIC) @deprecated(reason: "will be migrated to AccountDefaultWalletIdByUsername")
accountDefaultWalletByUsername(username: UsernameWithFlags!, walletCurrency: WalletCurrency): PublicWallet! @join__field(graph: PUBLIC)
btcPriceList(range: PriceGraphRange!): [PricePoint] @join__field(graph: PUBLIC)
businessMapMarkers: [MapMarker!]! @join__field(graph: PUBLIC)
currencyList: [Currency!]! @join__field(graph: PUBLIC)
Expand Down Expand Up @@ -2079,6 +2080,10 @@ input UserLogoutInput
scalar Username
@join__type(graph: PUBLIC)

"""Unique identifier of a user, with optional flags"""
scalar UsernameWithFlags
@join__type(graph: PUBLIC)

enum UserNotificationCategory
@join__type(graph: NOTIFICATIONS)
{
Expand Down
2 changes: 2 additions & 0 deletions core/api/src/graphql/public/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import OnChainUsdTxFeeAsBtcDenominatedQuery from "@/graphql/public/root/query/on
import UsernameAvailableQuery from "@/graphql/public/root/query/username-available"
import BusinessMapMarkersQuery from "@/graphql/public/root/query/business-map-markers"
import AccountDefaultWalletQuery from "@/graphql/public/root/query/account-default-wallet"
import AccountDefaultWalletByUsernameQuery from "@/graphql/public/root/query/account-default-wallet-by-username"
import AccountDefaultWalletIdQuery from "@/graphql/public/root/query/account-default-wallet-id"
import LnInvoicePaymentStatusQuery from "@/graphql/public/root/query/ln-invoice-payment-status"
import LnInvoicePaymentStatusByHashQuery from "@/graphql/public/root/query/ln-invoice-payment-status-by-hash"
Expand All @@ -23,6 +24,7 @@ export const queryFields = {
usernameAvailable: UsernameAvailableQuery,
userDefaultWalletId: AccountDefaultWalletIdQuery, // FIXME: migrate to AccountDefaultWalletId
accountDefaultWallet: AccountDefaultWalletQuery,
accountDefaultWalletByUsername: AccountDefaultWalletByUsernameQuery,
businessMapMarkers: BusinessMapMarkersQuery,
currencyList: CurrencyListQuery,
mobileVersions: MobileVersionsQuery,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Wallets } from "@/app"

import { UsernameParser } from "@/domain/accounts"
import { WalletCurrency as DomainWalletCurrency } from "@/domain/shared"
import { CouldNotFindWalletFromUsernameAndCurrencyError } from "@/domain/errors"

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

import { mapError } from "@/graphql/error-map"
import { GT } from "@/graphql/index"
import UsernameWithFlags from "@/graphql/shared/types/scalar/username-with-flags"
import WalletCurrency from "@/graphql/shared/types/scalar/wallet-currency"
import PublicWallet from "@/graphql/public/types/object/public-wallet"

const AccountDefaultWalletByUsernameQuery = GT.Field({
type: GT.NonNull(PublicWallet),
args: {
username: {
type: GT.NonNull(UsernameWithFlags),
},
walletCurrency: { type: WalletCurrency },
},
resolve: async (_, args) => {
const { username: usernameWithFlags, walletCurrency } = args

if (usernameWithFlags instanceof Error) {
throw usernameWithFlags
}

const parser = UsernameParser(usernameWithFlags)
const username = parser.parsedUsername()
if (username instanceof Error) {
throw mapError(username)
}

const account = await AccountsRepository().findByUsername(username)
if (account instanceof Error) {
throw mapError(account)
}

const wallets = await Wallets.listWalletsByAccountId(account.id)
if (wallets instanceof Error) {
throw mapError(wallets)
}

if (parser.isUsd()) {
const wallet = wallets.find(
(wallet) => wallet.currency === DomainWalletCurrency.Usd,
)
if (!wallet) {
throw mapError(new CouldNotFindWalletFromUsernameAndCurrencyError(username))
}

return wallet
}

if (!walletCurrency) {
return wallets.find((wallet) => wallet.id === account.defaultWalletId)
}

const wallet = wallets.find((wallet) => wallet.currency === walletCurrency)
if (!wallet) {
throw mapError(
new CouldNotFindWalletFromUsernameAndCurrencyError(usernameWithFlags),
)
}

return wallet
},
})

export default AccountDefaultWalletByUsernameQuery
14 changes: 1 addition & 13 deletions core/api/src/graphql/public/root/query/account-default-wallet.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { Wallets } from "@/app"

import { UsernameParser } from "@/domain/accounts"
import { WalletCurrency as DomainWalletCurrency } from "@/domain/shared"
import { CouldNotFindWalletFromUsernameAndCurrencyError } from "@/domain/errors"

import { AccountsRepository } from "@/services/mongoose"
Expand All @@ -13,6 +11,7 @@ import WalletCurrency from "@/graphql/shared/types/scalar/wallet-currency"
import PublicWallet from "@/graphql/public/types/object/public-wallet"

const AccountDefaultWalletQuery = GT.Field({
deprecationReason: "will be migrated to AccountDefaultWalletIdByUsername",
type: GT.NonNull(PublicWallet),
args: {
username: {
Expand All @@ -37,17 +36,6 @@ const AccountDefaultWalletQuery = GT.Field({
throw mapError(wallets)
}

if (UsernameParser(username).isUsd()) {
const wallet = wallets.find(
(wallet) => wallet.currency === DomainWalletCurrency.Usd,
)
if (!wallet) {
throw mapError(new CouldNotFindWalletFromUsernameAndCurrencyError(username))
}

return wallet
}

if (!walletCurrency) {
return wallets.find((wallet) => wallet.id === account.defaultWalletId)
}
Expand Down
6 changes: 5 additions & 1 deletion core/api/src/graphql/public/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,8 @@ type PublicWallet {
}

type Query {
accountDefaultWallet(username: Username!, walletCurrency: WalletCurrency): PublicWallet!
accountDefaultWallet(username: Username!, walletCurrency: WalletCurrency): PublicWallet! @deprecated(reason: "will be migrated to AccountDefaultWalletIdByUsername")
accountDefaultWalletByUsername(username: UsernameWithFlags!, walletCurrency: WalletCurrency): PublicWallet!
btcPriceList(range: PriceGraphRange!): [PricePoint]
businessMapMarkers: [MapMarker!]!
currencyList: [Currency!]!
Expand Down Expand Up @@ -1667,6 +1668,9 @@ type UserUpdateUsernamePayload {
"""Unique identifier of a user"""
scalar Username

"""Unique identifier of a user, with optional flags"""
scalar UsernameWithFlags

"""
A generic wallet which stores value in one of our supported currencies.
"""
Expand Down
35 changes: 35 additions & 0 deletions core/api/src/graphql/shared/types/scalar/username-with-flags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { UsernameWithFlagsRegex } from "@/domain/accounts"
import { InputValidationError } from "@/graphql/error"
import { GT } from "@/graphql/index"

const UsernameWithFlags = GT.Scalar({
name: "UsernameWithFlags",
description: "Unique identifier of a user, with optional flags",
parseValue(value) {
if (typeof value !== "string") {
return new InputValidationError({
message: "Invalid type for Username with optional flags",
})
}
return validUsernameWithFlagsValue(value)
},
parseLiteral(ast) {
if (ast.kind === GT.Kind.STRING) {
return validUsernameWithFlagsValue(ast.value)
}
return new InputValidationError({
message: "Invalid type for Username with optional flags",
})
},
})

function validUsernameWithFlagsValue(value: string) {
if (value.match(UsernameWithFlagsRegex)) {
return value.toLowerCase()
}
return new InputValidationError({
message: "Invalid value for Username with optional flags",
})
}

export default UsernameWithFlags
7 changes: 6 additions & 1 deletion dev/config/apollo-federation/supergraph.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1562,7 +1562,8 @@ type Query
@join__type(graph: NOTIFICATIONS)
@join__type(graph: PUBLIC)
{
accountDefaultWallet(username: Username!, walletCurrency: WalletCurrency): PublicWallet! @join__field(graph: PUBLIC)
accountDefaultWallet(username: Username!, walletCurrency: WalletCurrency): PublicWallet! @join__field(graph: PUBLIC) @deprecated(reason: "will be migrated to AccountDefaultWalletIdByUsername")
accountDefaultWalletByUsername(username: UsernameWithFlags!, walletCurrency: WalletCurrency): PublicWallet! @join__field(graph: PUBLIC)
btcPriceList(range: PriceGraphRange!): [PricePoint] @join__field(graph: PUBLIC)
businessMapMarkers: [MapMarker!]! @join__field(graph: PUBLIC)
currencyList: [Currency!]! @join__field(graph: PUBLIC)
Expand Down Expand Up @@ -2079,6 +2080,10 @@ input UserLogoutInput
scalar Username
@join__type(graph: PUBLIC)

"""Unique identifier of a user, with optional flags"""
scalar UsernameWithFlags
@join__type(graph: PUBLIC)

enum UserNotificationCategory
@join__type(graph: NOTIFICATIONS)
{
Expand Down

0 comments on commit 9968417

Please sign in to comment.