From f1be6ef396c2bfd5f51fe5d799f72db547ab7c02 Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Sun, 4 Feb 2024 14:21:49 -0600 Subject: [PATCH] feat: adding the approval map view on admin panel --- apps/admin-panel/app/account/[uuid]/page.tsx | 6 +- apps/admin-panel/app/account/layout.tsx | 7 +- apps/admin-panel/app/merchants/page.tsx | 28 + apps/admin-panel/app/types.ts | 3 + apps/admin-panel/codegen.yml | 2 +- .../account/business-map-update.tsx | 153 ----- .../components/account/details.tsx | 31 +- .../admin-panel/components/account/update.tsx | 6 +- .../components/{account => }/confirm.tsx | 0 .../components/icons/search-globe.svg | 8 + .../components/merchants/details.tsx | 64 ++ .../components/merchants/update.tsx | 43 ++ apps/admin-panel/components/side-bar.tsx | 6 + apps/admin-panel/generated.ts | 548 +++++++++++++----- apps/admin-panel/graphql.gql | 151 ++--- apps/admin-panel/next.config.js | 1 - core/api/src/app/index.ts | 4 +- core/api/src/app/merchants/index.ts | 17 + core/api/src/domain/accounts/index.ts | 5 +- core/api/src/domain/merchants/errors.ts | 5 + core/api/src/domain/merchants/index.ts | 14 + .../root/mutation/merchant-map-delete.ts | 19 +- .../root/mutation/merchant-map-validate.ts | 9 +- .../merchants-pending-approval-listing.ts | 2 +- core/api/src/graphql/admin/schema.graphql | 5 +- .../src/graphql/admin/types/object/account.ts | 17 +- core/api/src/graphql/public/schema.graphql | 2 +- .../graphql/shared/types/object/merchant.ts | 2 +- core/api/src/utils/uuid.ts | 2 + .../apollo-federation/supergraph.graphql | 2 +- 30 files changed, 747 insertions(+), 415 deletions(-) create mode 100644 apps/admin-panel/app/merchants/page.tsx create mode 100644 apps/admin-panel/app/types.ts delete mode 100644 apps/admin-panel/components/account/business-map-update.tsx rename apps/admin-panel/components/{account => }/confirm.tsx (100%) create mode 100644 apps/admin-panel/components/icons/search-globe.svg create mode 100644 apps/admin-panel/components/merchants/details.tsx create mode 100644 apps/admin-panel/components/merchants/update.tsx create mode 100644 core/api/src/domain/merchants/errors.ts create mode 100644 core/api/src/domain/merchants/index.ts create mode 100644 core/api/src/utils/uuid.ts diff --git a/apps/admin-panel/app/account/[uuid]/page.tsx b/apps/admin-panel/app/account/[uuid]/page.tsx index 7f063c4b047..5c011bf31d5 100644 --- a/apps/admin-panel/app/account/[uuid]/page.tsx +++ b/apps/admin-panel/app/account/[uuid]/page.tsx @@ -1,6 +1,6 @@ -import BusinessMapUpdate from "../../../components/account/business-map-update" import Details from "../../../components/account/details" import AccountUpdate from "../../../components/account/update" +import { Merchants } from "../../../components/merchants/details" import { AccountDetailsByAccountIdDocument, AccountDetailsByAccountIdQuery, @@ -19,8 +19,6 @@ export default async function AccountDetails({ params }: { params: { uuid: strin const auditedAccount = data?.accountDetailsByAccountId - console.log({ auditedAccount }, "data") - return ( auditedAccount && ( <> @@ -31,9 +29,9 @@ export default async function AccountDetails({ params }: { params: { uuid: strin
-
+ ) ) diff --git a/apps/admin-panel/app/account/layout.tsx b/apps/admin-panel/app/account/layout.tsx index 273ecb8972d..aac4eef4462 100644 --- a/apps/admin-panel/app/account/layout.tsx +++ b/apps/admin-panel/app/account/layout.tsx @@ -1,16 +1,15 @@ "use client" import Image from "next/image" -/* eslint @typescript-eslint/ban-ts-comment: "off" */ -// @ts-ignore-next-line no-implicit-any error -import { experimental_useFormState as useFormState } from "react-dom" + +import { useFormState } from "react-dom" import SearchIcon from "../../components/icons/search.svg" import { accountSearch } from "./search-action" const initialState = { - message: null, + message: "", } export default function Account({ children }: { children: React.ReactNode }) { diff --git a/apps/admin-panel/app/merchants/page.tsx b/apps/admin-panel/app/merchants/page.tsx new file mode 100644 index 00000000000..e07b758b89a --- /dev/null +++ b/apps/admin-panel/app/merchants/page.tsx @@ -0,0 +1,28 @@ +import { Merchants } from "../../components/merchants/details" +import { + MerchantsPendingApprovalDocument, + MerchantsPendingApprovalQuery, + MerchantsPendingApprovalQueryVariables, + useMerchantsPendingApprovalQuery, +} from "../../generated" +import { getClient } from "../graphql-rsc" + +export default async function () { + const query = await getClient().query< + MerchantsPendingApprovalQuery, + MerchantsPendingApprovalQueryVariables + >({ + query: MerchantsPendingApprovalDocument, + }) + + const merchants = query?.data.merchantsPendingApproval ?? [] + + return ( + <> +

+ {"Merchants pending validation"} +

+ + + ) +} diff --git a/apps/admin-panel/app/types.ts b/apps/admin-panel/app/types.ts new file mode 100644 index 00000000000..d56f1b35246 --- /dev/null +++ b/apps/admin-panel/app/types.ts @@ -0,0 +1,3 @@ +import { AuditedAccount } from "../generated" + +export type AuditedAccountMainValues = Omit diff --git a/apps/admin-panel/codegen.yml b/apps/admin-panel/codegen.yml index 37754fa1ec9..fb6980ab1fe 100644 --- a/apps/admin-panel/codegen.yml +++ b/apps/admin-panel/codegen.yml @@ -1,6 +1,6 @@ overwrite: true schema: - - "https://raw.githubusercontent.com/GaloyMoney/galoy/main/core/api/src/graphql/admin/schema.graphql" + - "../../core/api/src/graphql/admin/schema.graphql" documents: - "graphql.gql" generates: diff --git a/apps/admin-panel/components/account/business-map-update.tsx b/apps/admin-panel/components/account/business-map-update.tsx deleted file mode 100644 index f352fdcb1d5..00000000000 --- a/apps/admin-panel/components/account/business-map-update.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import { revalidatePath } from "next/cache" - -import { - AuditedAccount, - BusinessDeleteMapInfoDocument, - BusinessDeleteMapInfoMutation, - BusinessDeleteMapInfoMutationVariables, - BusinessUpdateMapInfoDocument, - BusinessUpdateMapInfoMutation, - BusinessUpdateMapInfoMutationVariables, -} from "../../generated" - -import { getClient } from "../../app/graphql-rsc" - -import ConfirmForm from "./confirm" - -const isValidLatitude = (latitude: number) => - isFinite(latitude) && Math.abs(latitude) <= 90 -const isValidLongitude = (longitude: number) => - isFinite(longitude) && Math.abs(longitude) <= 180 -const isValidTitle = (title: string) => title.length >= 3 - -const deleteBusiness = async (formData: FormData) => { - "use server" - - const username = formData.get("username") as string - - await getClient().mutate< - BusinessDeleteMapInfoMutation, - BusinessDeleteMapInfoMutationVariables - >({ - mutation: BusinessDeleteMapInfoDocument, - variables: { input: { username } }, - }) - - revalidatePath("/account") -} - -const update = async (formData: FormData) => { - "use server" - - const username = String(formData.get("username")) - const title = String(formData.get("title")) - const latitude = Number(formData.get("latitude")) - const longitude = Number(formData.get("longitude")) - - if ( - !!title && - isValidTitle(title) && - username && - isValidLatitude(latitude) && - isValidLongitude(longitude) - ) { - const input = { username, title, latitude, longitude } - - await getClient().mutate< - BusinessUpdateMapInfoMutation, - BusinessUpdateMapInfoMutationVariables - >({ - mutation: BusinessUpdateMapInfoDocument, - variables: { input }, - }) - } - - revalidatePath("/account") -} - -const BusinessMapUpdate: React.FC<{ - auditedAccount: AuditedAccount -}> = ({ auditedAccount }) => { - return ( -
-
-
- - - -
-
- - -
-
- - -
-
- -
-
- - -
- -
-
-
- ) -} - -export default BusinessMapUpdate diff --git a/apps/admin-panel/components/account/details.tsx b/apps/admin-panel/components/account/details.tsx index be04fd9f982..d7c933f819e 100644 --- a/apps/admin-panel/components/account/details.tsx +++ b/apps/admin-panel/components/account/details.tsx @@ -1,8 +1,8 @@ -import { AuditedAccount } from "../../generated" +import { AuditedAccountMainValues } from "../../app/types" import { formatDate } from "../../app/utils" const Details: React.FC<{ - auditedAccount: AuditedAccount + auditedAccount: AuditedAccountMainValues }> = ({ auditedAccount }) => { return (
@@ -26,33 +26,6 @@ const Details: React.FC<{

Username

{auditedAccount.username || "--"}

-
-

Title

-

{auditedAccount.title || "--"}

-
-
-

Coordinates

-

- {auditedAccount.coordinates ? ( - - {auditedAccount.coordinates?.latitude + - ", " + - auditedAccount.coordinates?.longitude} - - ) : ( - "--" - )} -

-

Created At

{formatDate(auditedAccount.createdAt)}

diff --git a/apps/admin-panel/components/account/update.tsx b/apps/admin-panel/components/account/update.tsx index 7f0977c8a4e..45ca5a31c21 100644 --- a/apps/admin-panel/components/account/update.tsx +++ b/apps/admin-panel/components/account/update.tsx @@ -13,13 +13,13 @@ import { AccountUpdateStatusDocument, AccountUpdateStatusMutation, AccountUpdateStatusMutationVariables, - AuditedAccount, } from "../../generated" -import ConfirmForm from "./confirm" +import ConfirmForm from "../confirm" +import { AuditedAccountMainValues } from "../../app/types" type PropType = { - auditedAccount: AuditedAccount + auditedAccount: AuditedAccountMainValues } const updateLevel = async (formData: FormData) => { diff --git a/apps/admin-panel/components/account/confirm.tsx b/apps/admin-panel/components/confirm.tsx similarity index 100% rename from apps/admin-panel/components/account/confirm.tsx rename to apps/admin-panel/components/confirm.tsx diff --git a/apps/admin-panel/components/icons/search-globe.svg b/apps/admin-panel/components/icons/search-globe.svg new file mode 100644 index 00000000000..f0ba7002108 --- /dev/null +++ b/apps/admin-panel/components/icons/search-globe.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/apps/admin-panel/components/merchants/details.tsx b/apps/admin-panel/components/merchants/details.tsx new file mode 100644 index 00000000000..918ff4522ea --- /dev/null +++ b/apps/admin-panel/components/merchants/details.tsx @@ -0,0 +1,64 @@ +import { Merchant } from "../../generated" +import ConfirmForm from "../confirm" +import { deleteMerchant, validateMerchant } from "./update" + +type Props = { + merchants: readonly Merchant[] +} + +export const Merchants = ({ merchants }: Props) => { + return ( +
+ {merchants.map((merchant) => ( +
+
+

+ Username: {merchant.username} + + Name: {merchant.title} + + + View Location + + + Validated:{" "} + {String(merchant.validated)} +

+
+ {!merchant.validated && ( +
+ + + + +
+ )} +
+ + + + +
+
+ ))} +
+ ) +} diff --git a/apps/admin-panel/components/merchants/update.tsx b/apps/admin-panel/components/merchants/update.tsx new file mode 100644 index 00000000000..5e4059c2b31 --- /dev/null +++ b/apps/admin-panel/components/merchants/update.tsx @@ -0,0 +1,43 @@ +import { revalidatePath } from "next/cache" +import { getClient } from "../../app/graphql-rsc" + +import { + MerchantMapDeleteDocument, + MerchantMapDeleteMutation, + MerchantMapDeleteMutationVariables, + MerchantMapValidateDocument, + MerchantMapValidateMutation, + MerchantMapValidateMutationVariables, +} from "../../generated" + +export const deleteMerchant = async (formData: FormData) => { + "use server" + console.log("delete merchant") + + const id = formData.get("id") as string + + await getClient().mutate( + { + mutation: MerchantMapDeleteDocument, + variables: { input: { id } }, + }, + ) + + revalidatePath("/account") +} + +export const validateMerchant = async (formData: FormData) => { + "use server" + console.log("validate merchant") + + const id = formData.get("id") as string + + await getClient().mutate( + { + mutation: MerchantMapValidateDocument, + variables: { input: { id } }, + }, + ) + + revalidatePath("/account") +} diff --git a/apps/admin-panel/components/side-bar.tsx b/apps/admin-panel/components/side-bar.tsx index 87b76959b8b..cb61e9d92bc 100644 --- a/apps/admin-panel/components/side-bar.tsx +++ b/apps/admin-panel/components/side-bar.tsx @@ -8,6 +8,7 @@ import { signOut } from "next-auth/react" import PeopleIcon from "./icons/people.svg" import TransactionsIcon from "./icons/transactions.svg" +import GlobeIcon from "./icons/search-globe.svg" import LogoutIcon from "./icons/logout.svg" const dashboardRoutes = [ @@ -21,6 +22,11 @@ const dashboardRoutes = [ icon: TransactionsIcon, path: "/transactions", }, + { + name: "Merchants", + icon: GlobeIcon, + path: "/merchants", + }, ] function SideBar() { diff --git a/apps/admin-panel/generated.ts b/apps/admin-panel/generated.ts index 421e0aea73d..5bfb7539b1f 100644 --- a/apps/admin-panel/generated.ts +++ b/apps/admin-panel/generated.ts @@ -105,14 +105,12 @@ export type AdminPushNotificationSendPayload = { /** Accounts are core to the Galoy architecture. they have users, and own wallets */ export type AuditedAccount = { readonly __typename: 'AuditedAccount'; - /** GPS coordinates for the account that can be used to place the related business on a map */ - readonly coordinates?: Maybe; readonly createdAt: Scalars['Timestamp']['output']; readonly id: Scalars['ID']['output']; readonly level: AccountLevel; + readonly merchants: ReadonlyArray; readonly owner: AuditedUser; readonly status: AccountStatus; - readonly title?: Maybe; readonly username?: Maybe; readonly wallets: ReadonlyArray; }; @@ -134,15 +132,49 @@ export type BtcWallet = Wallet & { /** A balance stored in BTC. */ readonly balance: Scalars['SignedAmount']['output']; readonly id: Scalars['ID']['output']; + readonly invoiceByPaymentHash: Invoice; + /** A list of all invoices associated with walletIds optionally passed. */ + readonly invoices?: Maybe; /** An unconfirmed incoming onchain balance. */ readonly pendingIncomingBalance: Scalars['SignedAmount']['output']; + readonly pendingIncomingTransactions: ReadonlyArray; + readonly pendingIncomingTransactionsByAddress: ReadonlyArray; + readonly transactionById: Transaction; /** A list of BTC transactions associated with this wallet. */ readonly transactions?: Maybe; readonly transactionsByAddress?: Maybe; + readonly transactionsByPaymentHash: ReadonlyArray; readonly walletCurrency: WalletCurrency; }; +/** A wallet belonging to an account which contains a BTC balance and a list of transactions. */ +export type BtcWalletInvoiceByPaymentHashArgs = { + paymentHash: Scalars['PaymentHash']['input']; +}; + + +/** A wallet belonging to an account which contains a BTC balance and a list of transactions. */ +export type BtcWalletInvoicesArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; +}; + + +/** A wallet belonging to an account which contains a BTC balance and a list of transactions. */ +export type BtcWalletPendingIncomingTransactionsByAddressArgs = { + address: Scalars['OnChainAddress']['input']; +}; + + +/** A wallet belonging to an account which contains a BTC balance and a list of transactions. */ +export type BtcWalletTransactionByIdArgs = { + transactionId: Scalars['ID']['input']; +}; + + /** A wallet belonging to an account which contains a BTC balance and a list of transactions. */ export type BtcWalletTransactionsArgs = { after?: InputMaybe; @@ -161,15 +193,10 @@ export type BtcWalletTransactionsByAddressArgs = { last?: InputMaybe; }; -export type BusinessDeleteMapInfoInput = { - readonly username: Scalars['Username']['input']; -}; -export type BusinessUpdateMapInfoInput = { - readonly latitude: Scalars['Float']['input']; - readonly longitude: Scalars['Float']['input']; - readonly title: Scalars['String']['input']; - readonly username: Scalars['Username']['input']; +/** A wallet belonging to an account which contains a BTC balance and a list of transactions. */ +export type BtcWalletTransactionsByPaymentHashArgs = { + paymentHash: Scalars['PaymentHash']['input']; }; export type Coordinates = { @@ -208,6 +235,8 @@ export type InitiationViaIntraLedger = { export type InitiationViaLn = { readonly __typename: 'InitiationViaLn'; readonly paymentHash: Scalars['PaymentHash']['output']; + /** Bolt11 invoice */ + readonly paymentRequest: Scalars['LnPaymentRequest']['output']; }; export type InitiationViaOnChain = { @@ -215,6 +244,44 @@ export type InitiationViaOnChain = { readonly address: Scalars['OnChainAddress']['output']; }; +/** A lightning invoice. */ +export type Invoice = { + readonly createdAt: Scalars['Timestamp']['output']; + /** The payment hash of the lightning invoice. */ + readonly paymentHash: Scalars['PaymentHash']['output']; + /** The bolt11 invoice to be paid. */ + readonly paymentRequest: Scalars['LnPaymentRequest']['output']; + /** The payment secret of the lightning invoice. This is not the preimage of the payment hash. */ + readonly paymentSecret: Scalars['LnPaymentSecret']['output']; + /** The payment status of the invoice. */ + readonly paymentStatus: InvoicePaymentStatus; +}; + +/** A connection to a list of items. */ +export type InvoiceConnection = { + readonly __typename: 'InvoiceConnection'; + /** A list of edges. */ + readonly edges?: Maybe>; + /** Information to aid in pagination. */ + readonly pageInfo: PageInfo; +}; + +/** An edge in a connection. */ +export type InvoiceEdge = { + readonly __typename: 'InvoiceEdge'; + /** A cursor for use in pagination */ + readonly cursor: Scalars['String']['output']; + /** The item at the end of the edge */ + readonly node: Invoice; +}; + +export const InvoicePaymentStatus = { + Expired: 'EXPIRED', + Paid: 'PAID', + Pending: 'PENDING' +} as const; + +export type InvoicePaymentStatus = typeof InvoicePaymentStatus[keyof typeof InvoicePaymentStatus]; export type LightningInvoice = { readonly __typename: 'LightningInvoice'; readonly confirmedAt?: Maybe; @@ -246,13 +313,40 @@ export const LnPaymentStatus = { } as const; export type LnPaymentStatus = typeof LnPaymentStatus[keyof typeof LnPaymentStatus]; +export type Merchant = { + readonly __typename: 'Merchant'; + /** GPS coordinates for the merchant that can be used to place the related business on a map */ + readonly coordinates: Coordinates; + readonly createdAt: Scalars['Timestamp']['output']; + readonly id: Scalars['ID']['output']; + readonly title: Scalars['String']['output']; + /** The username of the merchant */ + readonly username: Scalars['Username']['output']; + /** Whether the merchant has been validated */ + readonly validated: Scalars['Boolean']['output']; +}; + +export type MerchantMapDeleteInput = { + readonly id: Scalars['ID']['input']; +}; + +export type MerchantMapValidateInput = { + readonly id: Scalars['ID']['input']; +}; + +export type MerchantPayload = { + readonly __typename: 'MerchantPayload'; + readonly errors: ReadonlyArray; + readonly merchant?: Maybe; +}; + export type Mutation = { readonly __typename: 'Mutation'; readonly accountUpdateLevel: AccountDetailPayload; readonly accountUpdateStatus: AccountDetailPayload; readonly adminPushNotificationSend: AdminPushNotificationSendPayload; - readonly businessDeleteMapInfo: AccountDetailPayload; - readonly businessUpdateMapInfo: AccountDetailPayload; + readonly merchantMapDelete: MerchantPayload; + readonly merchantMapValidate: MerchantPayload; readonly userUpdatePhone: AccountDetailPayload; }; @@ -272,13 +366,13 @@ export type MutationAdminPushNotificationSendArgs = { }; -export type MutationBusinessDeleteMapInfoArgs = { - input: BusinessDeleteMapInfoInput; +export type MutationMerchantMapDeleteArgs = { + input: MerchantMapDeleteInput; }; -export type MutationBusinessUpdateMapInfoArgs = { - input: BusinessUpdateMapInfoInput; +export type MutationMerchantMapValidateArgs = { + input: MerchantMapValidateInput; }; @@ -328,6 +422,7 @@ export type Query = { readonly lightningInvoice: LightningInvoice; readonly lightningPayment: LightningPayment; readonly listWalletIds: ReadonlyArray; + readonly merchantsPendingApproval: ReadonlyArray; readonly transactionById?: Maybe; readonly transactionsByHash?: Maybe>>; readonly wallet: Wallet; @@ -395,6 +490,7 @@ export type SettlementViaIntraLedger = { /** Settlement destination: Could be null if the payee does not have a username */ readonly counterPartyUsername?: Maybe; readonly counterPartyWalletId?: Maybe; + readonly preImage?: Maybe; }; export type SettlementViaLn = { @@ -406,6 +502,7 @@ export type SettlementViaLn = { export type SettlementViaOnChain = { readonly __typename: 'SettlementViaOnChain'; + readonly arrivalInMempoolEstimatedAt?: Maybe; readonly transactionHash?: Maybe; readonly vout?: Maybe; }; @@ -477,14 +574,48 @@ export type UsdWallet = Wallet & { readonly accountId: Scalars['ID']['output']; readonly balance: Scalars['SignedAmount']['output']; readonly id: Scalars['ID']['output']; + readonly invoiceByPaymentHash: Invoice; + /** A list of all invoices associated with walletIds optionally passed. */ + readonly invoices?: Maybe; /** An unconfirmed incoming onchain balance. */ readonly pendingIncomingBalance: Scalars['SignedAmount']['output']; + readonly pendingIncomingTransactions: ReadonlyArray; + readonly pendingIncomingTransactionsByAddress: ReadonlyArray; + readonly transactionById: Transaction; readonly transactions?: Maybe; readonly transactionsByAddress?: Maybe; + readonly transactionsByPaymentHash: ReadonlyArray; readonly walletCurrency: WalletCurrency; }; +/** A wallet belonging to an account which contains a USD balance and a list of transactions. */ +export type UsdWalletInvoiceByPaymentHashArgs = { + paymentHash: Scalars['PaymentHash']['input']; +}; + + +/** A wallet belonging to an account which contains a USD balance and a list of transactions. */ +export type UsdWalletInvoicesArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; +}; + + +/** A wallet belonging to an account which contains a USD balance and a list of transactions. */ +export type UsdWalletPendingIncomingTransactionsByAddressArgs = { + address: Scalars['OnChainAddress']['input']; +}; + + +/** A wallet belonging to an account which contains a USD balance and a list of transactions. */ +export type UsdWalletTransactionByIdArgs = { + transactionId: Scalars['ID']['input']; +}; + + /** A wallet belonging to an account which contains a USD balance and a list of transactions. */ export type UsdWalletTransactionsArgs = { after?: InputMaybe; @@ -503,6 +634,12 @@ export type UsdWalletTransactionsByAddressArgs = { last?: InputMaybe; }; + +/** A wallet belonging to an account which contains a USD balance and a list of transactions. */ +export type UsdWalletTransactionsByPaymentHashArgs = { + paymentHash: Scalars['PaymentHash']['input']; +}; + export type UserUpdatePhoneInput = { readonly accountId: Scalars['AccountId']['input']; readonly phone: Scalars['Phone']['input']; @@ -513,7 +650,24 @@ export type Wallet = { readonly accountId: Scalars['ID']['output']; readonly balance: Scalars['SignedAmount']['output']; readonly id: Scalars['ID']['output']; + readonly invoiceByPaymentHash: Invoice; + readonly invoices?: Maybe; readonly pendingIncomingBalance: Scalars['SignedAmount']['output']; + /** + * Pending incoming 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 + */ + readonly pendingIncomingTransactions: ReadonlyArray; + /** + * Pending incoming 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 + */ + readonly pendingIncomingTransactionsByAddress: ReadonlyArray; + readonly transactionById: Transaction; /** * Transactions are ordered anti-chronologically, * ie: the newest transaction will be first @@ -524,10 +678,39 @@ export type Wallet = { * ie: the newest transaction will be first */ readonly transactionsByAddress?: Maybe; + /** Returns the transactions that include this paymentHash. This should be a list of size one for a received lightning payment. This can be more that one transaction for a sent lightning payment. */ + readonly transactionsByPaymentHash: ReadonlyArray; readonly walletCurrency: WalletCurrency; }; +/** A generic wallet which stores value in one of our supported currencies. */ +export type WalletInvoiceByPaymentHashArgs = { + paymentHash: Scalars['PaymentHash']['input']; +}; + + +/** A generic wallet which stores value in one of our supported currencies. */ +export type WalletInvoicesArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; +}; + + +/** A generic wallet which stores value in one of our supported currencies. */ +export type WalletPendingIncomingTransactionsByAddressArgs = { + address: Scalars['OnChainAddress']['input']; +}; + + +/** A generic wallet which stores value in one of our supported currencies. */ +export type WalletTransactionByIdArgs = { + transactionId: Scalars['ID']['input']; +}; + + /** A generic wallet which stores value in one of our supported currencies. */ export type WalletTransactionsArgs = { after?: InputMaybe; @@ -546,6 +729,12 @@ export type WalletTransactionsByAddressArgs = { last?: InputMaybe; }; + +/** A generic wallet which stores value in one of our supported currencies. */ +export type WalletTransactionsByPaymentHashArgs = { + paymentHash: Scalars['PaymentHash']['input']; +}; + export const WalletCurrency = { Btc: 'BTC', Usd: 'USD' @@ -557,56 +746,56 @@ export type AccountDetailsByUserPhoneQueryVariables = Exact<{ }>; -export type AccountDetailsByUserPhoneQuery = { readonly __typename: 'Query', readonly accountDetailsByUserPhone: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly title?: string | null, readonly createdAt: number, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly coordinates?: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } | null, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } }; +export type AccountDetailsByUserPhoneQuery = { readonly __typename: 'Query', readonly accountDetailsByUserPhone: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly createdAt: number, readonly merchants: ReadonlyArray<{ readonly __typename: 'Merchant', readonly id: string, readonly title: string, readonly createdAt: number, readonly validated: boolean, readonly username: string, readonly coordinates: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } }>, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } }; export type AccountDetailsByAccountIdQueryVariables = Exact<{ accountId: Scalars['ID']['input']; }>; -export type AccountDetailsByAccountIdQuery = { readonly __typename: 'Query', readonly accountDetailsByAccountId: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly title?: string | null, readonly createdAt: number, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly coordinates?: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } | null, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } }; +export type AccountDetailsByAccountIdQuery = { readonly __typename: 'Query', readonly accountDetailsByAccountId: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly createdAt: number, readonly merchants: ReadonlyArray<{ readonly __typename: 'Merchant', readonly id: string, readonly title: string, readonly createdAt: number, readonly validated: boolean, readonly username: string, readonly coordinates: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } }>, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } }; export type AccountDetailsByEmailQueryVariables = Exact<{ email: Scalars['EmailAddress']['input']; }>; -export type AccountDetailsByEmailQuery = { readonly __typename: 'Query', readonly accountDetailsByEmail: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly title?: string | null, readonly createdAt: number, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly coordinates?: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } | null, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } }; +export type AccountDetailsByEmailQuery = { readonly __typename: 'Query', readonly accountDetailsByEmail: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly createdAt: number, readonly merchants: ReadonlyArray<{ readonly __typename: 'Merchant', readonly id: string, readonly title: string, readonly createdAt: number, readonly validated: boolean, readonly username: string, readonly coordinates: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } }>, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } }; -export type BusinessDeleteMapInfoMutationVariables = Exact<{ - input: BusinessDeleteMapInfoInput; +export type MerchantMapDeleteMutationVariables = Exact<{ + input: MerchantMapDeleteInput; }>; -export type BusinessDeleteMapInfoMutation = { readonly __typename: 'Mutation', readonly businessDeleteMapInfo: { readonly __typename: 'AccountDetailPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }> } }; +export type MerchantMapDeleteMutation = { readonly __typename: 'Mutation', readonly merchantMapDelete: { readonly __typename: 'MerchantPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }> } }; -export type AccountUpdateLevelMutationVariables = Exact<{ - input: AccountUpdateLevelInput; +export type MerchantMapValidateMutationVariables = Exact<{ + input: MerchantMapValidateInput; }>; -export type AccountUpdateLevelMutation = { readonly __typename: 'Mutation', readonly accountUpdateLevel: { readonly __typename: 'AccountDetailPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }>, readonly accountDetails?: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly title?: string | null, readonly createdAt: number, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly coordinates?: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } | null, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } | null } }; +export type MerchantMapValidateMutation = { readonly __typename: 'Mutation', readonly merchantMapValidate: { readonly __typename: 'MerchantPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }> } }; -export type BusinessUpdateMapInfoMutationVariables = Exact<{ - input: BusinessUpdateMapInfoInput; +export type AccountUpdateLevelMutationVariables = Exact<{ + input: AccountUpdateLevelInput; }>; -export type BusinessUpdateMapInfoMutation = { readonly __typename: 'Mutation', readonly businessUpdateMapInfo: { readonly __typename: 'AccountDetailPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }>, readonly accountDetails?: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly title?: string | null, readonly createdAt: number, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly coordinates?: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } | null, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } | null } }; +export type AccountUpdateLevelMutation = { readonly __typename: 'Mutation', readonly accountUpdateLevel: { readonly __typename: 'AccountDetailPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }>, readonly accountDetails?: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly createdAt: number, readonly merchants: ReadonlyArray<{ readonly __typename: 'Merchant', readonly id: string, readonly title: string, readonly createdAt: number, readonly validated: boolean, readonly username: string, readonly coordinates: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } }>, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } | null } }; export type AccountUpdateStatusMutationVariables = Exact<{ input: AccountUpdateStatusInput; }>; -export type AccountUpdateStatusMutation = { readonly __typename: 'Mutation', readonly accountUpdateStatus: { readonly __typename: 'AccountDetailPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }>, readonly accountDetails?: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly title?: string | null, readonly createdAt: number, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly coordinates?: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } | null, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } | null } }; +export type AccountUpdateStatusMutation = { readonly __typename: 'Mutation', readonly accountUpdateStatus: { readonly __typename: 'AccountDetailPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }>, readonly accountDetails?: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly createdAt: number, readonly merchants: ReadonlyArray<{ readonly __typename: 'Merchant', readonly id: string, readonly title: string, readonly createdAt: number, readonly validated: boolean, readonly username: string, readonly coordinates: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } }>, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } | null } }; export type AccountDetailsByUsernameQueryVariables = Exact<{ username: Scalars['Username']['input']; }>; -export type AccountDetailsByUsernameQuery = { readonly __typename: 'Query', readonly accountDetailsByUsername: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly title?: string | null, readonly createdAt: number, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly coordinates?: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } | null, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } }; +export type AccountDetailsByUsernameQuery = { readonly __typename: 'Query', readonly accountDetailsByUsername: { readonly __typename: 'AuditedAccount', readonly id: string, readonly username?: string | null, readonly level: AccountLevel, readonly status: AccountStatus, readonly createdAt: number, readonly merchants: ReadonlyArray<{ readonly __typename: 'Merchant', readonly id: string, readonly title: string, readonly createdAt: number, readonly validated: boolean, readonly username: string, readonly coordinates: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } }>, readonly owner: { readonly __typename: 'AuditedUser', readonly id: string, readonly language: string, readonly phone?: string | null, readonly createdAt: number, readonly email?: { readonly __typename: 'Email', readonly address?: string | null, readonly verified?: boolean | null } | null }, readonly wallets: ReadonlyArray<{ readonly __typename: 'BTCWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number } | { readonly __typename: 'UsdWallet', readonly id: string, readonly walletCurrency: WalletCurrency, readonly accountId: string, readonly balance: number, readonly pendingIncomingBalance: number }> } }; export type LightningInvoiceQueryVariables = Exact<{ hash: Scalars['PaymentHash']['input']; @@ -636,6 +825,11 @@ export type TransactionByIdQueryVariables = Exact<{ export type TransactionByIdQuery = { readonly __typename: 'Query', readonly transactionById?: { readonly __typename: 'Transaction', readonly id: string, readonly settlementAmount: number, readonly settlementFee: number, readonly direction: TxDirection, readonly status: TxStatus, readonly memo?: string | null, readonly createdAt: number, readonly initiationVia: { readonly __typename: 'InitiationViaIntraLedger', readonly counterPartyWalletId?: string | null, readonly counterPartyUsername?: string | null } | { readonly __typename: 'InitiationViaLn', readonly paymentHash: string } | { readonly __typename: 'InitiationViaOnChain', readonly address: string }, readonly settlementVia: { readonly __typename: 'SettlementViaIntraLedger', readonly counterPartyWalletId?: string | null, readonly counterPartyUsername?: string | null } | { readonly __typename: 'SettlementViaLn', readonly paymentSecret?: string | null } | { readonly __typename: 'SettlementViaOnChain', readonly transactionHash?: string | null }, readonly settlementPrice: { readonly __typename: 'PriceOfOneSettlementMinorUnitInDisplayMinorUnit', readonly base: number, readonly offset: number, readonly currencyUnit: string, readonly formattedAmount: string } } | null }; +export type MerchantsPendingApprovalQueryVariables = Exact<{ [key: string]: never; }>; + + +export type MerchantsPendingApprovalQuery = { readonly __typename: 'Query', readonly merchantsPendingApproval: ReadonlyArray<{ readonly __typename: 'Merchant', readonly id: string, readonly title: string, readonly createdAt: number, readonly validated: boolean, readonly username: string, readonly coordinates: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } }> }; + export const AccountDetailsByUserPhoneDocument = gql` query accountDetailsByUserPhone($phone: Phone!) { @@ -644,7 +838,17 @@ export const AccountDetailsByUserPhoneDocument = gql` username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -655,10 +859,6 @@ export const AccountDetailsByUserPhoneDocument = gql` } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -695,8 +895,13 @@ export function useAccountDetailsByUserPhoneLazyQuery(baseOptions?: Apollo.LazyQ const options = {...defaultOptions, ...baseOptions} return Apollo.useLazyQuery(AccountDetailsByUserPhoneDocument, options); } +export function useAccountDetailsByUserPhoneSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(AccountDetailsByUserPhoneDocument, options); + } export type AccountDetailsByUserPhoneQueryHookResult = ReturnType; export type AccountDetailsByUserPhoneLazyQueryHookResult = ReturnType; +export type AccountDetailsByUserPhoneSuspenseQueryHookResult = ReturnType; export type AccountDetailsByUserPhoneQueryResult = Apollo.QueryResult; export const AccountDetailsByAccountIdDocument = gql` query accountDetailsByAccountId($accountId: ID!) { @@ -705,7 +910,17 @@ export const AccountDetailsByAccountIdDocument = gql` username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -716,10 +931,6 @@ export const AccountDetailsByAccountIdDocument = gql` } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -756,8 +967,13 @@ export function useAccountDetailsByAccountIdLazyQuery(baseOptions?: Apollo.LazyQ const options = {...defaultOptions, ...baseOptions} return Apollo.useLazyQuery(AccountDetailsByAccountIdDocument, options); } +export function useAccountDetailsByAccountIdSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(AccountDetailsByAccountIdDocument, options); + } export type AccountDetailsByAccountIdQueryHookResult = ReturnType; export type AccountDetailsByAccountIdLazyQueryHookResult = ReturnType; +export type AccountDetailsByAccountIdSuspenseQueryHookResult = ReturnType; export type AccountDetailsByAccountIdQueryResult = Apollo.QueryResult; export const AccountDetailsByEmailDocument = gql` query accountDetailsByEmail($email: EmailAddress!) { @@ -766,7 +982,17 @@ export const AccountDetailsByEmailDocument = gql` username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -777,10 +1003,6 @@ export const AccountDetailsByEmailDocument = gql` } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -817,111 +1039,87 @@ export function useAccountDetailsByEmailLazyQuery(baseOptions?: Apollo.LazyQuery const options = {...defaultOptions, ...baseOptions} return Apollo.useLazyQuery(AccountDetailsByEmailDocument, options); } +export function useAccountDetailsByEmailSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(AccountDetailsByEmailDocument, options); + } export type AccountDetailsByEmailQueryHookResult = ReturnType; export type AccountDetailsByEmailLazyQueryHookResult = ReturnType; +export type AccountDetailsByEmailSuspenseQueryHookResult = ReturnType; export type AccountDetailsByEmailQueryResult = Apollo.QueryResult; -export const BusinessDeleteMapInfoDocument = gql` - mutation businessDeleteMapInfo($input: BusinessDeleteMapInfoInput!) { - businessDeleteMapInfo(input: $input) { +export const MerchantMapDeleteDocument = gql` + mutation merchantMapDelete($input: MerchantMapDeleteInput!) { + merchantMapDelete(input: $input) { errors { message } } } `; -export type BusinessDeleteMapInfoMutationFn = Apollo.MutationFunction; +export type MerchantMapDeleteMutationFn = Apollo.MutationFunction; /** - * __useBusinessDeleteMapInfoMutation__ + * __useMerchantMapDeleteMutation__ * - * To run a mutation, you first call `useBusinessDeleteMapInfoMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useBusinessDeleteMapInfoMutation` returns a tuple that includes: + * To run a mutation, you first call `useMerchantMapDeleteMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useMerchantMapDeleteMutation` returns a tuple that includes: * - A mutate function that you can call at any time to execute the mutation * - An object with fields that represent the current status of the mutation's execution * * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; * * @example - * const [businessDeleteMapInfoMutation, { data, loading, error }] = useBusinessDeleteMapInfoMutation({ + * const [merchantMapDeleteMutation, { data, loading, error }] = useMerchantMapDeleteMutation({ * variables: { * input: // value for 'input' * }, * }); */ -export function useBusinessDeleteMapInfoMutation(baseOptions?: Apollo.MutationHookOptions) { +export function useMerchantMapDeleteMutation(baseOptions?: Apollo.MutationHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(BusinessDeleteMapInfoDocument, options); + return Apollo.useMutation(MerchantMapDeleteDocument, options); } -export type BusinessDeleteMapInfoMutationHookResult = ReturnType; -export type BusinessDeleteMapInfoMutationResult = Apollo.MutationResult; -export type BusinessDeleteMapInfoMutationOptions = Apollo.BaseMutationOptions; -export const AccountUpdateLevelDocument = gql` - mutation accountUpdateLevel($input: AccountUpdateLevelInput!) { - accountUpdateLevel(input: $input) { +export type MerchantMapDeleteMutationHookResult = ReturnType; +export type MerchantMapDeleteMutationResult = Apollo.MutationResult; +export type MerchantMapDeleteMutationOptions = Apollo.BaseMutationOptions; +export const MerchantMapValidateDocument = gql` + mutation merchantMapValidate($input: MerchantMapValidateInput!) { + merchantMapValidate(input: $input) { errors { message } - accountDetails { - id - username - level - status - title - owner { - id - language - phone - email { - address - verified - } - createdAt - } - coordinates { - latitude - longitude - } - wallets { - id - walletCurrency - accountId - balance - pendingIncomingBalance - } - createdAt - } } } `; -export type AccountUpdateLevelMutationFn = Apollo.MutationFunction; +export type MerchantMapValidateMutationFn = Apollo.MutationFunction; /** - * __useAccountUpdateLevelMutation__ + * __useMerchantMapValidateMutation__ * - * To run a mutation, you first call `useAccountUpdateLevelMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useAccountUpdateLevelMutation` returns a tuple that includes: + * To run a mutation, you first call `useMerchantMapValidateMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useMerchantMapValidateMutation` returns a tuple that includes: * - A mutate function that you can call at any time to execute the mutation * - An object with fields that represent the current status of the mutation's execution * * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; * * @example - * const [accountUpdateLevelMutation, { data, loading, error }] = useAccountUpdateLevelMutation({ + * const [merchantMapValidateMutation, { data, loading, error }] = useMerchantMapValidateMutation({ * variables: { * input: // value for 'input' * }, * }); */ -export function useAccountUpdateLevelMutation(baseOptions?: Apollo.MutationHookOptions) { +export function useMerchantMapValidateMutation(baseOptions?: Apollo.MutationHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(AccountUpdateLevelDocument, options); + return Apollo.useMutation(MerchantMapValidateDocument, options); } -export type AccountUpdateLevelMutationHookResult = ReturnType; -export type AccountUpdateLevelMutationResult = Apollo.MutationResult; -export type AccountUpdateLevelMutationOptions = Apollo.BaseMutationOptions; -export const BusinessUpdateMapInfoDocument = gql` - mutation businessUpdateMapInfo($input: BusinessUpdateMapInfoInput!) { - businessUpdateMapInfo(input: $input) { +export type MerchantMapValidateMutationHookResult = ReturnType; +export type MerchantMapValidateMutationResult = Apollo.MutationResult; +export type MerchantMapValidateMutationOptions = Apollo.BaseMutationOptions; +export const AccountUpdateLevelDocument = gql` + mutation accountUpdateLevel($input: AccountUpdateLevelInput!) { + accountUpdateLevel(input: $input) { errors { message } @@ -930,7 +1128,17 @@ export const BusinessUpdateMapInfoDocument = gql` username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -941,10 +1149,6 @@ export const BusinessUpdateMapInfoDocument = gql` } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -957,32 +1161,32 @@ export const BusinessUpdateMapInfoDocument = gql` } } `; -export type BusinessUpdateMapInfoMutationFn = Apollo.MutationFunction; +export type AccountUpdateLevelMutationFn = Apollo.MutationFunction; /** - * __useBusinessUpdateMapInfoMutation__ + * __useAccountUpdateLevelMutation__ * - * To run a mutation, you first call `useBusinessUpdateMapInfoMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useBusinessUpdateMapInfoMutation` returns a tuple that includes: + * To run a mutation, you first call `useAccountUpdateLevelMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useAccountUpdateLevelMutation` returns a tuple that includes: * - A mutate function that you can call at any time to execute the mutation * - An object with fields that represent the current status of the mutation's execution * * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; * * @example - * const [businessUpdateMapInfoMutation, { data, loading, error }] = useBusinessUpdateMapInfoMutation({ + * const [accountUpdateLevelMutation, { data, loading, error }] = useAccountUpdateLevelMutation({ * variables: { * input: // value for 'input' * }, * }); */ -export function useBusinessUpdateMapInfoMutation(baseOptions?: Apollo.MutationHookOptions) { +export function useAccountUpdateLevelMutation(baseOptions?: Apollo.MutationHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(BusinessUpdateMapInfoDocument, options); + return Apollo.useMutation(AccountUpdateLevelDocument, options); } -export type BusinessUpdateMapInfoMutationHookResult = ReturnType; -export type BusinessUpdateMapInfoMutationResult = Apollo.MutationResult; -export type BusinessUpdateMapInfoMutationOptions = Apollo.BaseMutationOptions; +export type AccountUpdateLevelMutationHookResult = ReturnType; +export type AccountUpdateLevelMutationResult = Apollo.MutationResult; +export type AccountUpdateLevelMutationOptions = Apollo.BaseMutationOptions; export const AccountUpdateStatusDocument = gql` mutation accountUpdateStatus($input: AccountUpdateStatusInput!) { accountUpdateStatus(input: $input) { @@ -994,7 +1198,17 @@ export const AccountUpdateStatusDocument = gql` username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -1005,10 +1219,6 @@ export const AccountUpdateStatusDocument = gql` } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -1054,7 +1264,17 @@ export const AccountDetailsByUsernameDocument = gql` username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -1065,10 +1285,6 @@ export const AccountDetailsByUsernameDocument = gql` } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -1105,8 +1321,13 @@ export function useAccountDetailsByUsernameLazyQuery(baseOptions?: Apollo.LazyQu const options = {...defaultOptions, ...baseOptions} return Apollo.useLazyQuery(AccountDetailsByUsernameDocument, options); } +export function useAccountDetailsByUsernameSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(AccountDetailsByUsernameDocument, options); + } export type AccountDetailsByUsernameQueryHookResult = ReturnType; export type AccountDetailsByUsernameLazyQueryHookResult = ReturnType; +export type AccountDetailsByUsernameSuspenseQueryHookResult = ReturnType; export type AccountDetailsByUsernameQueryResult = Apollo.QueryResult; export const LightningInvoiceDocument = gql` query lightningInvoice($hash: PaymentHash!) { @@ -1147,8 +1368,13 @@ export function useLightningInvoiceLazyQuery(baseOptions?: Apollo.LazyQueryHookO const options = {...defaultOptions, ...baseOptions} return Apollo.useLazyQuery(LightningInvoiceDocument, options); } +export function useLightningInvoiceSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(LightningInvoiceDocument, options); + } export type LightningInvoiceQueryHookResult = ReturnType; export type LightningInvoiceLazyQueryHookResult = ReturnType; +export type LightningInvoiceSuspenseQueryHookResult = ReturnType; export type LightningInvoiceQueryResult = Apollo.QueryResult; export const LightningPaymentDocument = gql` query lightningPayment($hash: PaymentHash!) { @@ -1189,8 +1415,13 @@ export function useLightningPaymentLazyQuery(baseOptions?: Apollo.LazyQueryHookO const options = {...defaultOptions, ...baseOptions} return Apollo.useLazyQuery(LightningPaymentDocument, options); } +export function useLightningPaymentSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(LightningPaymentDocument, options); + } export type LightningPaymentQueryHookResult = ReturnType; export type LightningPaymentLazyQueryHookResult = ReturnType; +export type LightningPaymentSuspenseQueryHookResult = ReturnType; export type LightningPaymentQueryResult = Apollo.QueryResult; export const TransactionsByHashDocument = gql` query transactionsByHash($hash: PaymentHash!) { @@ -1262,8 +1493,13 @@ export function useTransactionsByHashLazyQuery(baseOptions?: Apollo.LazyQueryHoo const options = {...defaultOptions, ...baseOptions} return Apollo.useLazyQuery(TransactionsByHashDocument, options); } +export function useTransactionsByHashSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(TransactionsByHashDocument, options); + } export type TransactionsByHashQueryHookResult = ReturnType; export type TransactionsByHashLazyQueryHookResult = ReturnType; +export type TransactionsByHashSuspenseQueryHookResult = ReturnType; export type TransactionsByHashQueryResult = Apollo.QueryResult; export const TransactionByIdDocument = gql` query transactionById($id: ID!) { @@ -1335,6 +1571,58 @@ export function useTransactionByIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOp const options = {...defaultOptions, ...baseOptions} return Apollo.useLazyQuery(TransactionByIdDocument, options); } +export function useTransactionByIdSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(TransactionByIdDocument, options); + } export type TransactionByIdQueryHookResult = ReturnType; export type TransactionByIdLazyQueryHookResult = ReturnType; -export type TransactionByIdQueryResult = Apollo.QueryResult; \ No newline at end of file +export type TransactionByIdSuspenseQueryHookResult = ReturnType; +export type TransactionByIdQueryResult = Apollo.QueryResult; +export const MerchantsPendingApprovalDocument = gql` + query merchantsPendingApproval { + merchantsPendingApproval { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } +} + `; + +/** + * __useMerchantsPendingApprovalQuery__ + * + * To run a query within a React component, call `useMerchantsPendingApprovalQuery` and pass it any options that fit your needs. + * When your component renders, `useMerchantsPendingApprovalQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useMerchantsPendingApprovalQuery({ + * variables: { + * }, + * }); + */ +export function useMerchantsPendingApprovalQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(MerchantsPendingApprovalDocument, options); + } +export function useMerchantsPendingApprovalLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(MerchantsPendingApprovalDocument, options); + } +export function useMerchantsPendingApprovalSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(MerchantsPendingApprovalDocument, options); + } +export type MerchantsPendingApprovalQueryHookResult = ReturnType; +export type MerchantsPendingApprovalLazyQueryHookResult = ReturnType; +export type MerchantsPendingApprovalSuspenseQueryHookResult = ReturnType; +export type MerchantsPendingApprovalQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/apps/admin-panel/graphql.gql b/apps/admin-panel/graphql.gql index 4251703ac37..591b5ee2425 100644 --- a/apps/admin-panel/graphql.gql +++ b/apps/admin-panel/graphql.gql @@ -4,7 +4,17 @@ query accountDetailsByUserPhone($phone: Phone!) { username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -15,10 +25,6 @@ query accountDetailsByUserPhone($phone: Phone!) { } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -36,7 +42,17 @@ query accountDetailsByAccountId($accountId: ID!) { username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -47,10 +63,6 @@ query accountDetailsByAccountId($accountId: ID!) { } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -68,7 +80,17 @@ query accountDetailsByEmail($email: EmailAddress!) { username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -79,10 +101,6 @@ query accountDetailsByEmail($email: EmailAddress!) { } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -94,53 +112,24 @@ query accountDetailsByEmail($email: EmailAddress!) { } } -mutation businessDeleteMapInfo($input: BusinessDeleteMapInfoInput!) { - businessDeleteMapInfo(input: $input) { +mutation merchantMapDelete($input: MerchantMapDeleteInput!) { + merchantMapDelete(input: $input) { errors { message } } } -mutation accountUpdateLevel($input: AccountUpdateLevelInput!) { - accountUpdateLevel(input: $input) { +mutation merchantMapValidate($input: MerchantMapValidateInput!) { + merchantMapValidate(input: $input) { errors { message } - accountDetails { - id - username - level - status - title - owner { - id - language - phone - email { - address - verified - } - createdAt - } - coordinates { - latitude - longitude - } - wallets { - id - walletCurrency - accountId - balance - pendingIncomingBalance - } - createdAt - } } } -mutation businessUpdateMapInfo($input: BusinessUpdateMapInfoInput!) { - businessUpdateMapInfo(input: $input) { +mutation accountUpdateLevel($input: AccountUpdateLevelInput!) { + accountUpdateLevel(input: $input) { errors { message } @@ -149,7 +138,17 @@ mutation businessUpdateMapInfo($input: BusinessUpdateMapInfoInput!) { username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -160,10 +159,6 @@ mutation businessUpdateMapInfo($input: BusinessUpdateMapInfoInput!) { } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -186,7 +181,17 @@ mutation accountUpdateStatus($input: AccountUpdateStatusInput!) { username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -197,10 +202,6 @@ mutation accountUpdateStatus($input: AccountUpdateStatusInput!) { } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -219,7 +220,17 @@ query accountDetailsByUsername($username: Username!) { username level status - title + merchants { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } owner { id language @@ -230,10 +241,6 @@ query accountDetailsByUsername($username: Username!) { } createdAt } - coordinates { - latitude - longitude - } wallets { id walletCurrency @@ -358,3 +365,17 @@ query transactionById($id: ID!) { createdAt } } + +query merchantsPendingApproval { + merchantsPendingApproval { + id + title + coordinates { + latitude + longitude + } + createdAt + validated + username + } +} diff --git a/apps/admin-panel/next.config.js b/apps/admin-panel/next.config.js index 13bdb8d8343..cbd4faab40e 100644 --- a/apps/admin-panel/next.config.js +++ b/apps/admin-panel/next.config.js @@ -2,7 +2,6 @@ const nextConfig = { experimental: { outputFileTracingRoot: require("path").join(__dirname, "../../"), - serverActions: true, instrumentationHook: true, }, output: "standalone", diff --git a/core/api/src/app/index.ts b/core/api/src/app/index.ts index 920a5d51ccf..4005fc75055 100644 --- a/core/api/src/app/index.ts +++ b/core/api/src/app/index.ts @@ -22,7 +22,6 @@ const allFunctions = { Callback: { ...CallbackMod }, Comm: { ...CommMod }, Quiz: { ...QuizMod }, - Merchants: { ...MerchantsMod }, Lightning: { ...LightningMod }, OnChain: { ...OnChainMod }, Prices: { ...PricesMod }, @@ -30,6 +29,7 @@ const allFunctions = { Users: { ...UsersMod }, Wallets: { ...WalletsMod }, Payments: { ...PaymentsMod }, + Merchants: { ...MerchantsMod }, } as const let subModule: keyof typeof allFunctions @@ -52,7 +52,6 @@ export const { Callback, Comm, Quiz, - Merchants, Lightning, OnChain, Prices, @@ -60,4 +59,5 @@ export const { Users, Wallets, Payments, + Merchants, } = allFunctions diff --git a/core/api/src/app/merchants/index.ts b/core/api/src/app/merchants/index.ts index bca26701c53..06f0df1e7ea 100644 --- a/core/api/src/app/merchants/index.ts +++ b/core/api/src/app/merchants/index.ts @@ -1,3 +1,5 @@ +import { checkedToUsername } from "@/domain/accounts" +import { CouldNotFindMerchantFromUsernameError } from "@/domain/errors" import { MerchantsRepository } from "@/services/mongoose" export * from "./suggest-merchant-map" @@ -13,3 +15,18 @@ export const getMerchantsMapMarkers = async () => { export const getMerchantsPendingApproval = async () => { return merchants.listPendingApproval() } + +export const getMerchantsByUsername = async (username: string) => { + const usernameValidated = checkedToUsername(username) + if (usernameValidated instanceof Error) { + return usernameValidated + } + + const result = await merchants.findByUsername(usernameValidated) + + if (result instanceof CouldNotFindMerchantFromUsernameError) { + return [] + } + + return result +} diff --git a/core/api/src/domain/accounts/index.ts b/core/api/src/domain/accounts/index.ts index bb7f8c127af..f3e20bc41cd 100644 --- a/core/api/src/domain/accounts/index.ts +++ b/core/api/src/domain/accounts/index.ts @@ -2,6 +2,8 @@ import { InvalidAccountIdError } from "./errors" import { AccountLevel, AccountStatus } from "./primitives" +import { UUIDV4 } from "@/utils/uuid" + import { toSats } from "@/domain/bitcoin" import { InvalidCoordinatesError, @@ -20,9 +22,6 @@ export * from "./limits-volume" export * from "./account-validator" export * from "./primitives" -const UUIDV4 = - /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i - const KratosUserIdRegex = UUIDV4 const AccountIdRegex = UUIDV4 diff --git a/core/api/src/domain/merchants/errors.ts b/core/api/src/domain/merchants/errors.ts new file mode 100644 index 00000000000..f2cfb629acf --- /dev/null +++ b/core/api/src/domain/merchants/errors.ts @@ -0,0 +1,5 @@ +import { DomainError } from "@/domain/shared" + +export class MerchantError extends DomainError {} + +export class InvalidMerchantIdError extends MerchantError {} diff --git a/core/api/src/domain/merchants/index.ts b/core/api/src/domain/merchants/index.ts new file mode 100644 index 00000000000..273a99e6a2d --- /dev/null +++ b/core/api/src/domain/merchants/index.ts @@ -0,0 +1,14 @@ +import { InvalidMerchantIdError } from "./errors" + +import { UUIDV4 } from "@/utils/uuid" + +const MerchantIdRegex = UUIDV4 + +export const checkedToMerchantId = ( + merchantId: string, +): MerchantId | InvalidMerchantIdError => { + if (merchantId.match(MerchantIdRegex)) { + return merchantId as MerchantId + } + return new InvalidMerchantIdError(merchantId) +} diff --git a/core/api/src/graphql/admin/root/mutation/merchant-map-delete.ts b/core/api/src/graphql/admin/root/mutation/merchant-map-delete.ts index b13c59771cb..faef2eaf9a1 100644 --- a/core/api/src/graphql/admin/root/mutation/merchant-map-delete.ts +++ b/core/api/src/graphql/admin/root/mutation/merchant-map-delete.ts @@ -1,4 +1,5 @@ import { Merchants } from "@/app" +import { checkedToMerchantId } from "@/domain/merchants" import { mapAndParseErrorForGqlResponse } from "@/graphql/error-map" import { GT } from "@/graphql/index" import MerchantPayload from "@/graphql/shared/types/payload/merchant" @@ -12,16 +13,7 @@ const MerchantMapDeleteInput = GT.Input({ }), }) -const MerchantMapDeleteMutation = GT.Field< - null, - GraphQLAdminContext, - { - input: { - // TODO: UUID v4 check - id: string | InputValidationError - } - } ->({ +const MerchantMapDeleteMutation = GT.Field({ extensions: { complexity: 120, }, @@ -36,7 +28,12 @@ const MerchantMapDeleteMutation = GT.Field< return { errors: [{ message: id.message }] } } - const account = await Merchants.deleteMerchantById(id as MerchantId) + const merchantId = checkedToMerchantId(id) + if (merchantId instanceof Error) { + return { errors: [mapAndParseErrorForGqlResponse(merchantId)] } + } + + const account = await Merchants.deleteMerchantById(merchantId) if (account instanceof Error) { return { errors: [mapAndParseErrorForGqlResponse(account)] } diff --git a/core/api/src/graphql/admin/root/mutation/merchant-map-validate.ts b/core/api/src/graphql/admin/root/mutation/merchant-map-validate.ts index 9245de48b6f..4d499f2aff0 100644 --- a/core/api/src/graphql/admin/root/mutation/merchant-map-validate.ts +++ b/core/api/src/graphql/admin/root/mutation/merchant-map-validate.ts @@ -1,4 +1,5 @@ import { Merchants } from "@/app" +import { checkedToMerchantId } from "@/domain/merchants" import { mapAndParseErrorForGqlResponse } from "@/graphql/error-map" import { GT } from "@/graphql/index" import MerchantPayload from "@/graphql/shared/types/payload/merchant" @@ -7,7 +8,6 @@ const MerchantMapValidateInput = GT.Input({ name: "MerchantMapValidateInput", fields: () => ({ id: { - // TODO: MerchantID? type: GT.NonNullID, }, }), @@ -28,7 +28,12 @@ const MerchantMapValidate = GT.Field({ return { errors: [{ message: id.message }] } } - const merchant = await Merchants.approveMerchantById(id) + const merchantId = checkedToMerchantId(id) + if (merchantId instanceof Error) { + return { errors: [mapAndParseErrorForGqlResponse(merchantId)] } + } + + const merchant = await Merchants.approveMerchantById(merchantId) if (merchant instanceof Error) { return { errors: [mapAndParseErrorForGqlResponse(merchant)] } diff --git a/core/api/src/graphql/admin/root/query/merchants-pending-approval-listing.ts b/core/api/src/graphql/admin/root/query/merchants-pending-approval-listing.ts index 9c9a2aa6891..5b6c409dcd7 100644 --- a/core/api/src/graphql/admin/root/query/merchants-pending-approval-listing.ts +++ b/core/api/src/graphql/admin/root/query/merchants-pending-approval-listing.ts @@ -5,7 +5,7 @@ import { mapError } from "@/graphql/error-map" import Merchant from "@/graphql/shared/types/object/merchant" const MerchantsPendingApprovalQuery = GT.Field({ - type: GT.List(Merchant), + type: GT.NonNullList(Merchant), resolve: async (_, { id }) => { if (id instanceof Error) throw id diff --git a/core/api/src/graphql/admin/schema.graphql b/core/api/src/graphql/admin/schema.graphql index 6e5b75f2cbe..391b019fa5a 100644 --- a/core/api/src/graphql/admin/schema.graphql +++ b/core/api/src/graphql/admin/schema.graphql @@ -51,6 +51,7 @@ type AuditedAccount { createdAt: Timestamp! id: ID! level: AccountLevel! + merchants: [Merchant!]! owner: AuditedUser! status: AccountStatus! username: Username @@ -271,7 +272,7 @@ type Merchant { """ GPS coordinates for the merchant that can be used to place the related business on a map """ - coordinates: Coordinates + coordinates: Coordinates! createdAt: Timestamp! id: ID! title: String! @@ -360,7 +361,7 @@ type Query { lightningInvoice(hash: PaymentHash!): LightningInvoice! lightningPayment(hash: PaymentHash!): LightningPayment! listWalletIds(walletCurrency: WalletCurrency!): [WalletId!]! - merchantsPendingApproval: [Merchant] + merchantsPendingApproval: [Merchant!]! transactionById(id: ID!): Transaction transactionsByHash(hash: PaymentHash!): [Transaction] wallet(walletId: WalletId!): Wallet! diff --git a/core/api/src/graphql/admin/types/object/account.ts b/core/api/src/graphql/admin/types/object/account.ts index cb877a238b6..8a250189fa5 100644 --- a/core/api/src/graphql/admin/types/object/account.ts +++ b/core/api/src/graphql/admin/types/object/account.ts @@ -4,7 +4,7 @@ import AccountStatus from "../scalar/account-status" import GraphQLUser from "./user" -import { Wallets, Users } from "@/app" +import { Wallets, Users, Merchants } from "@/app" import { GT } from "@/graphql/index" import Timestamp from "@/graphql/shared/types/scalar/timestamp" import Username from "@/graphql/shared/types/scalar/username" @@ -12,6 +12,7 @@ import Wallet from "@/graphql/shared/types/abstract/wallet" import { mapError } from "@/graphql/error-map" import AccountLevel from "@/graphql/shared/types/scalar/account-level" +import Merchant from "@/graphql/shared/types/object/merchant" const AuditedAccount: GraphQLObjectType = GT.Object({ name: "AuditedAccount", @@ -30,6 +31,20 @@ const AuditedAccount: GraphQLObjectType = GT.Object({ return result }, }, + merchants: { + type: GT.NonNullList(Merchant), + resolve: async (source) => { + const username = source.username + if (!username) { + return [] + } + + const result = await Merchants.getMerchantsByUsername(username) + + if (result instanceof Error) throw mapError(result) + return result + }, + }, owner: { // should be used for individual account only, // ie: when there are no multiple users diff --git a/core/api/src/graphql/public/schema.graphql b/core/api/src/graphql/public/schema.graphql index 0e258123f55..5bdfa82c2fd 100644 --- a/core/api/src/graphql/public/schema.graphql +++ b/core/api/src/graphql/public/schema.graphql @@ -782,7 +782,7 @@ type Merchant { """ GPS coordinates for the merchant that can be used to place the related business on a map """ - coordinates: Coordinates + coordinates: Coordinates! createdAt: Timestamp! id: ID! title: String! diff --git a/core/api/src/graphql/shared/types/object/merchant.ts b/core/api/src/graphql/shared/types/object/merchant.ts index 2b72d835a87..b415da35203 100644 --- a/core/api/src/graphql/shared/types/object/merchant.ts +++ b/core/api/src/graphql/shared/types/object/merchant.ts @@ -11,7 +11,7 @@ const Merchant: GraphQLObjectType = GT.Object