diff --git a/package.json b/package.json index 3e3eaf0..56f0e25 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wildcat-dashboard-ui", "private": true, - "version": "0.0.1", + "version": "0.1.1", "type": "module", "scripts": { "dev": "vite", diff --git a/src/generated/client/sdk.gen.ts b/src/generated/client/sdk.gen.ts index ada7f5f..625d876 100644 --- a/src/generated/client/sdk.gen.ts +++ b/src/generated/client/sdk.gen.ts @@ -1,7 +1,8 @@ // This file is auto-generated by @hey-api/openapi-ts import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch'; -import type { ListQuotesData, ListQuotesResponse, ListPendingQuotesData, ListPendingQuotesResponse, AdminLookupQuoteData, AdminLookupQuoteResponse, AdminUpdateQuoteData, AdminUpdateQuoteResponse, ResolveOfferData, EnquireQuoteData, EnquireQuoteResponse, LookupQuoteData, LookupQuoteResponse, ActivateKeysetData, ActivateKeysetResponse, DebitData, CreditData, ECashBalance, OnChainBalanceData, OnChainData, KeysetInfoData, KeySetInfo} from './types.gen'; +import type { ListQuotesData, ListQuotesResponse, ListPendingQuotesData, ListPendingQuotesResponse, AdminLookupQuoteData, AdminLookupQuoteResponse, AdminUpdateQuoteData, AdminUpdateQuoteResponse, ResolveOfferData, EnquireQuoteData, EnquireQuoteResponse, LookupQuoteData, LookupQuoteResponse, ActivateKeysetData, ActivateKeysetResponse, DebitData, CreditData, ECashBalance, OnChainBalanceData, OnChainData, KeysetInfoData, KeySetInfo, RequestToMintData, RequestToMintResponseInfo} from './types.gen'; + import { client as _heyApiClient } from './client.gen'; export type Options = ClientOptions & { @@ -136,3 +137,18 @@ export const keysetInfo = (options: Option ...options }); }; + +/** + * --------------------------- RequestMint +*/ + +export const requestToMint = (options: Options) => { + return (options.client ?? _heyApiClient).post({ + url: '/v1/admin/treasury/debit/request_to_mint_from_ebill', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); +}; diff --git a/src/generated/client/types.gen.ts b/src/generated/client/types.gen.ts index 94db385..2addb30 100644 --- a/src/generated/client/types.gen.ts +++ b/src/generated/client/types.gen.ts @@ -496,3 +496,36 @@ export type KeysetInfoData = { query?: never; url: '/v1/admin/keysets/{keyset_id}'; }; + +/** + * Request Mint + */ + + // pub struct RequestToMintFromEBillRequest { + // pub ebill_id: String, + // pub amount: Amount, + // } + + export type RequestToMintRequest = { + ebill_id: string; + amount: number; + }; + + export type RequestToMintResponseInfo = { + request_id: string; + request: string; + }; + + export type RequestToMintResponse = { + /** + * Successful response + */ + 200: RequestToMintResponseInfo; + }; + + export type RequestToMintData = { + body?: RequestToMintRequest; + path?: never; + query?: never; + url: '/v1/admin/treasury/debit/request_to_mint_from_ebill' + }; diff --git a/src/pages/quotes/QuotePage.tsx b/src/pages/quotes/QuotePage.tsx index daff027..dfe3f1a 100644 --- a/src/pages/quotes/QuotePage.tsx +++ b/src/pages/quotes/QuotePage.tsx @@ -6,13 +6,19 @@ import { Button } from "@/components/ui/button" import { Skeleton } from "@/components/ui/skeleton" import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" -import { IdentityPublicData, PayeePublicData, InfoReply, AnonPublicData } from "@/generated/client" +import { + IdentityPublicData, + PayeePublicData, + InfoReply, + AnonPublicData, + RequestToMintResponseInfo, +} from "@/generated/client" import { adminLookupQuoteOptions, adminLookupQuoteQueryKey, adminUpdateQuoteMutation, } from "@/generated/client/@tanstack/react-query.gen" -import { activateKeyset, keysetInfo } from "@/generated/client/sdk.gen" +import { activateKeyset, keysetInfo, requestToMint } from "@/generated/client/sdk.gen" import { cn, getInitials } from "@/lib/utils" import { formatDate, humanReadableDuration } from "@/utils/dates" @@ -211,12 +217,24 @@ function DenyConfirmDrawer({ children, onSubmit, ...drawerProps }: DenyConfirmDr ) } -function QuoteActions({ value, isFetching, newKeyset }: { value: InfoReply; isFetching: boolean; newKeyset: boolean }) { +function QuoteActions({ + value, + isFetching, + newKeyset, + ebillPaid, +}: { + value: InfoReply + isFetching: boolean + newKeyset: boolean + ebillPaid: boolean +}) { const [offerFormData, setOfferFormData] = useState() const [offerFormDrawerOpen, setOfferFormDrawerOpen] = useState(false) const [offerConfirmDrawerOpen, setOfferConfirmDrawerOpen] = useState(false) const [denyConfirmDrawerOpen, setDenyConfirmDrawerOpen] = useState(false) const [activateKeysetConfirmDrawerOpen, setActivateKeysetConfirmDrawerOpen] = useState(false) + const [requestToMintConfirmDrawerOpen, setRequestToMintConfirmDrawerOpen] = useState(false) + const [mintRequestResponse, setMintRequestResponse] = useState(null) const effectiveDiscount = useMemo(() => { if (!offerFormData) return @@ -293,6 +311,33 @@ function QuoteActions({ value, isFetching, newKeyset }: { value: InfoReply; isFe }, }) + const requestToMintMutation = useMutation({ + mutationFn: async () => { + const { data } = await requestToMint({ + body: { + ebill_id: value.bill.id, + amount: value.bill.sum, + }, + throwOnError: true, + }) + return data + }, + onMutate: () => { + toast.loading("Requesting to pay…", { id: `quote-${value.id}-request-to-mint` }) + }, + onSettled: () => { + toast.dismiss(`quote-${value.id}-request-to-pay`) + }, + onError: (error) => { + toast.error("Error while requesting to pay") + console.warn(error) + }, + onSuccess: (data) => { + toast.success("Payment request has been created.") + setMintRequestResponse(data) + }, + }) + const onDenyQuote = () => { toast.loading("Denying quote…", { id: `quote-${value.id}-deny` }) denyQuote.mutate({ @@ -325,107 +370,152 @@ function QuoteActions({ value, isFetching, newKeyset }: { value: InfoReply; isFe const onActivateKeyset = () => { activateKeysetMutation.mutate() } + + const onRequestToMint = () => { + requestToMintMutation.mutate() + } return ( -
- {value.status === "Pending" ? ( - { - onDenyQuote() - setDenyConfirmDrawerOpen(false) - }} - > - - - ) : ( - <> - )} - {value.status === "Pending" ? ( - { - setOfferFormData(data) - setOfferConfirmDrawerOpen(true) - setOfferFormDrawerOpen(false) - }} - > - - - ) : ( - <> - )} - - { - if (!offerFormData) return - onOfferQuote(offerFormData) - setOfferConfirmDrawerOpen(false) - }} - > -
- - Effective discount (relative):{" "} - {effectiveDiscount?.mul(new Big("100")).toFixed(2)}% - - - Effective discount (absolute):{" "} - {offerFormData?.discount.gross.value.minus(offerFormData?.discount.net.value).toFixed(0)}{" "} - {offerFormData?.discount.net.currency} - - - Net amount: {offerFormData?.discount.net.value.round(0).toFixed(0)}{" "} - {offerFormData?.discount.net.currency} - - - Valid until: {offerFormData?.ttl.ttl.toDateString()} ( - {offerFormData && humanReadableDuration("en", offerFormData.ttl.ttl)}) - -
-
- - {value.status === "Accepted" && "keyset_id" in value ? ( - { - onActivateKeyset() - setActivateKeysetConfirmDrawerOpen(false) - }} - submitButtonText="Yes, activate keyset" - trigger={ - } - /> - ) : ( - <> + + ) : ( + <> + )} + {value.status === "Pending" ? ( + { + setOfferFormData(data) + setOfferConfirmDrawerOpen(true) + setOfferFormDrawerOpen(false) + }} + > + + + ) : ( + <> + )} + + { + if (!offerFormData) return + onOfferQuote(offerFormData) + setOfferConfirmDrawerOpen(false) + }} + > +
+ + Effective discount (relative):{" "} + {effectiveDiscount?.mul(new Big("100")).toFixed(2)}% + + + Effective discount (absolute):{" "} + {offerFormData?.discount.gross.value.minus(offerFormData?.discount.net.value).toFixed(0)}{" "} + {offerFormData?.discount.net.currency} + + + Net amount: {offerFormData?.discount.net.value.round(0).toFixed(0)}{" "} + {offerFormData?.discount.net.currency} + + + Valid until: {offerFormData?.ttl.ttl.toDateString()} ( + {offerFormData && humanReadableDuration("en", offerFormData.ttl.ttl)}) + +
+
+ + {value.status === "Accepted" && "keyset_id" in value ? ( + { + onActivateKeyset() + setActivateKeysetConfirmDrawerOpen(false) + }} + submitButtonText="Yes, activate keyset" + trigger={ + + } + /> + ) : ( + <> + )} + + {value.status === "Accepted" && "keyset_id" in value && !ebillPaid && !newKeyset ? ( + { + onRequestToMint() + setRequestToMintConfirmDrawerOpen(false) + }} + submitButtonText="Yes, request to mint" + trigger={ + + } + /> + ) : ( + <> + )} +
+ + {mintRequestResponse && ( +
+

Payment Request

+
+
+ ID + {mintRequestResponse.request_id} +
+
+ Details +
+ {mintRequestResponse.request} +
+
+
+
)} - + ) } @@ -604,11 +694,17 @@ function Quote({ value, isFetching }: { value: InfoReply; isFetching: boolean }) - ID: + Quote ID: {value.id} + + Bill ID: + + {value.bill.id} + + {(value.status === "Offered" || value.status === "Accepted") && "keyset_id" in value ? ( Keyset ID: @@ -700,7 +796,7 @@ function Quote({ value, isFetching }: { value: InfoReply; isFetching: boolean })
- + ) }