Skip to content

Commit c7c1544

Browse files
committed
Add request to mint
1 parent 1dfffa6 commit c7c1544

File tree

3 files changed

+196
-105
lines changed

3 files changed

+196
-105
lines changed

src/generated/client/sdk.gen.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// This file is auto-generated by @hey-api/openapi-ts
22

33
import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';
4-
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, RequestToMintResponse} from './types.gen';
4+
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';
5+
56
import { client as _heyApiClient } from './client.gen';
67

78
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
@@ -142,7 +143,7 @@ export const keysetInfo = <ThrowOnError extends boolean = false>(options: Option
142143
*/
143144

144145
export const requestToMint = <ThrowOnError extends boolean = false>(options: Options<RequestToMintData, ThrowOnError>) => {
145-
return (options.client ?? _heyApiClient).post<RequestToMintResponse, unknown, ThrowOnError>({
146+
return (options.client ?? _heyApiClient).post<RequestToMintResponseInfo, unknown, ThrowOnError>({
146147
url: '/v1/admin/treasury/debit/request_to_mint_from_ebill',
147148
...options,
148149
headers: {

src/generated/client/types.gen.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ export type KeysetInfoData = {
507507
// }
508508

509509
export type RequestToMintRequest = {
510-
id: string;
510+
ebill_id: string;
511511
amount: number;
512512
};
513513

@@ -524,10 +524,8 @@ export type KeysetInfoData = {
524524
};
525525

526526
export type RequestToMintData = {
527-
body?: never;
528-
path: {
529-
keyset_id: string;
530-
};
527+
body?: RequestToMintRequest;
528+
path?: never;
531529
query?: never;
532530
url: '/v1/admin/treasury/debit/request_to_mint_from_ebill'
533531
};

src/pages/quotes/QuotePage.tsx

Lines changed: 190 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ import { Button } from "@/components/ui/button"
66
import { Skeleton } from "@/components/ui/skeleton"
77
import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table"
88
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
9-
import { IdentityPublicData, PayeePublicData, InfoReply, AnonPublicData } from "@/generated/client"
9+
import {
10+
IdentityPublicData,
11+
PayeePublicData,
12+
InfoReply,
13+
AnonPublicData,
14+
RequestToMintResponseInfo,
15+
} from "@/generated/client"
1016
import {
1117
adminLookupQuoteOptions,
1218
adminLookupQuoteQueryKey,
1319
adminUpdateQuoteMutation,
1420
} from "@/generated/client/@tanstack/react-query.gen"
15-
import { activateKeyset, keysetInfo } from "@/generated/client/sdk.gen"
21+
import { activateKeyset, keysetInfo, requestToMint } from "@/generated/client/sdk.gen"
1622
import { cn, getInitials } from "@/lib/utils"
1723
import { formatDate, humanReadableDuration } from "@/utils/dates"
1824

@@ -211,12 +217,24 @@ function DenyConfirmDrawer({ children, onSubmit, ...drawerProps }: DenyConfirmDr
211217
)
212218
}
213219

214-
function QuoteActions({ value, isFetching, newKeyset }: { value: InfoReply; isFetching: boolean; newKeyset: boolean }) {
220+
function QuoteActions({
221+
value,
222+
isFetching,
223+
newKeyset,
224+
ebillPaid,
225+
}: {
226+
value: InfoReply
227+
isFetching: boolean
228+
newKeyset: boolean
229+
ebillPaid: boolean
230+
}) {
215231
const [offerFormData, setOfferFormData] = useState<OfferFormResult>()
216232
const [offerFormDrawerOpen, setOfferFormDrawerOpen] = useState(false)
217233
const [offerConfirmDrawerOpen, setOfferConfirmDrawerOpen] = useState(false)
218234
const [denyConfirmDrawerOpen, setDenyConfirmDrawerOpen] = useState(false)
219235
const [activateKeysetConfirmDrawerOpen, setActivateKeysetConfirmDrawerOpen] = useState(false)
236+
const [requestToMintConfirmDrawerOpen, setRequestToMintConfirmDrawerOpen] = useState(false)
237+
const [mintRequestResponse, setMintRequestResponse] = useState<RequestToMintResponseInfo | null>(null)
220238

221239
const effectiveDiscount = useMemo(() => {
222240
if (!offerFormData) return
@@ -293,6 +311,35 @@ function QuoteActions({ value, isFetching, newKeyset }: { value: InfoReply; isFe
293311
},
294312
})
295313

314+
const requestToMintMutation = useMutation({
315+
mutationFn: async () => {
316+
const { data } = await requestToMint({
317+
body: {
318+
ebill_id: value.bill.id,
319+
amount: value.bill.sum,
320+
},
321+
throwOnError: true,
322+
})
323+
console.log(data)
324+
return data
325+
},
326+
onMutate: () => {
327+
toast.loading("Requesting to mint…", { id: `quote-${value.id}-request-to-mint` })
328+
},
329+
onSettled: () => {
330+
toast.dismiss(`quote-${value.id}-request-to-mint`)
331+
},
332+
onError: (error) => {
333+
toast.error("Error while requesting to mint: " + error.message)
334+
console.warn(error)
335+
},
336+
onSuccess: (data) => {
337+
toast.success("Payment request has been created.")
338+
console.log(data)
339+
setMintRequestResponse(data)
340+
},
341+
})
342+
296343
const onDenyQuote = () => {
297344
toast.loading("Denying quote…", { id: `quote-${value.id}-deny` })
298345
denyQuote.mutate({
@@ -325,107 +372,152 @@ function QuoteActions({ value, isFetching, newKeyset }: { value: InfoReply; isFe
325372
const onActivateKeyset = () => {
326373
activateKeysetMutation.mutate()
327374
}
375+
376+
const onRequestToMint = () => {
377+
requestToMintMutation.mutate()
378+
}
328379
return (
329-
<div className="flex items-center gap-2">
330-
{value.status === "Pending" ? (
331-
<DenyConfirmDrawer
332-
title="Confirm denying quote"
333-
open={denyConfirmDrawerOpen}
334-
onOpenChange={setDenyConfirmDrawerOpen}
335-
onSubmit={() => {
336-
onDenyQuote()
337-
setDenyConfirmDrawerOpen(false)
338-
}}
339-
>
340-
<Button
341-
className="flex-1"
342-
disabled={isFetching || denyQuote.isPending || value.status !== "Pending"}
343-
variant={value.status !== "Pending" ? "outline" : "destructive"}
380+
<>
381+
<div className="flex items-center gap-2">
382+
{value.status === "Pending" ? (
383+
<DenyConfirmDrawer
384+
title="Confirm denying quote"
385+
open={denyConfirmDrawerOpen}
386+
onOpenChange={setDenyConfirmDrawerOpen}
387+
onSubmit={() => {
388+
onDenyQuote()
389+
setDenyConfirmDrawerOpen(false)
390+
}}
344391
>
345-
Deny {denyQuote.isPending && <LoaderIcon className="stroke-1 animate-spin" />}
346-
</Button>
347-
</DenyConfirmDrawer>
348-
) : (
349-
<></>
350-
)}
351-
{value.status === "Pending" ? (
352-
<OfferFormDrawer
353-
title="Offer quote"
354-
description="Make an offer to the current holder of this bill"
355-
value={value}
356-
open={offerFormDrawerOpen}
357-
onOpenChange={setOfferFormDrawerOpen}
358-
onSubmit={(data) => {
359-
setOfferFormData(data)
360-
setOfferConfirmDrawerOpen(true)
361-
setOfferFormDrawerOpen(false)
362-
}}
363-
>
364-
<Button className="flex-1" disabled={isFetching || offerQuote.isPending || value.status !== "Pending"}>
365-
Offer {offerQuote.isPending && <LoaderIcon className="stroke-1 animate-spin" />}
366-
</Button>
367-
</OfferFormDrawer>
368-
) : (
369-
<></>
370-
)}
371-
372-
<OfferConfirmDrawer
373-
title="Confirm offering quote"
374-
description="Review your inputs and confirm the offer"
375-
open={offerConfirmDrawerOpen}
376-
onOpenChange={setOfferConfirmDrawerOpen}
377-
onSubmit={() => {
378-
if (!offerFormData) return
379-
onOfferQuote(offerFormData)
380-
setOfferConfirmDrawerOpen(false)
381-
}}
382-
>
383-
<div className="flex flex-col justify-center gap-1 py-8 mb-8">
384-
<span>
385-
<span className="font-bold">Effective discount (relative):</span>{" "}
386-
{effectiveDiscount?.mul(new Big("100")).toFixed(2)}%
387-
</span>
388-
<span>
389-
<span className="font-bold">Effective discount (absolute):</span>{" "}
390-
{offerFormData?.discount.gross.value.minus(offerFormData?.discount.net.value).toFixed(0)}{" "}
391-
{offerFormData?.discount.net.currency}
392-
</span>
393-
<span>
394-
<span className="font-bold">Net amount:</span> {offerFormData?.discount.net.value.round(0).toFixed(0)}{" "}
395-
{offerFormData?.discount.net.currency}
396-
</span>
397-
<span>
398-
<span className="font-bold">Valid until:</span> {offerFormData?.ttl.ttl.toDateString()} (
399-
{offerFormData && humanReadableDuration("en", offerFormData.ttl.ttl)})
400-
</span>
401-
</div>
402-
</OfferConfirmDrawer>
403-
404-
{value.status === "Accepted" && "keyset_id" in value ? (
405-
<ConfirmDrawer
406-
title="Confirm activating keyset"
407-
description="Are you sure you want to activate the keyset for this quote?"
408-
open={activateKeysetConfirmDrawerOpen}
409-
onOpenChange={setActivateKeysetConfirmDrawerOpen}
410-
onSubmit={() => {
411-
onActivateKeyset()
412-
setActivateKeysetConfirmDrawerOpen(false)
413-
}}
414-
submitButtonText="Yes, activate keyset"
415-
trigger={
416392
<Button
417393
className="flex-1"
418-
disabled={isFetching || activateKeysetMutation.isPending || !newKeyset}
419-
variant="default"
394+
disabled={isFetching || denyQuote.isPending || value.status !== "Pending"}
395+
variant={value.status !== "Pending" ? "outline" : "destructive"}
420396
>
421-
Activate Keyset {activateKeysetMutation.isPending && <LoaderIcon className="stroke-1 animate-spin" />}
397+
Deny {denyQuote.isPending && <LoaderIcon className="stroke-1 animate-spin" />}
422398
</Button>
423-
}
424-
/>
425-
) : (
426-
<></>
399+
</DenyConfirmDrawer>
400+
) : (
401+
<></>
402+
)}
403+
{value.status === "Pending" ? (
404+
<OfferFormDrawer
405+
title="Offer quote"
406+
description="Make an offer to the current holder of this bill"
407+
value={value}
408+
open={offerFormDrawerOpen}
409+
onOpenChange={setOfferFormDrawerOpen}
410+
onSubmit={(data) => {
411+
setOfferFormData(data)
412+
setOfferConfirmDrawerOpen(true)
413+
setOfferFormDrawerOpen(false)
414+
}}
415+
>
416+
<Button className="flex-1" disabled={isFetching || offerQuote.isPending || value.status !== "Pending"}>
417+
Offer {offerQuote.isPending && <LoaderIcon className="stroke-1 animate-spin" />}
418+
</Button>
419+
</OfferFormDrawer>
420+
) : (
421+
<></>
422+
)}
423+
424+
<OfferConfirmDrawer
425+
title="Confirm offering quote"
426+
description="Review your inputs and confirm the offer"
427+
open={offerConfirmDrawerOpen}
428+
onOpenChange={setOfferConfirmDrawerOpen}
429+
onSubmit={() => {
430+
if (!offerFormData) return
431+
onOfferQuote(offerFormData)
432+
setOfferConfirmDrawerOpen(false)
433+
}}
434+
>
435+
<div className="flex flex-col justify-center gap-1 py-8 mb-8">
436+
<span>
437+
<span className="font-bold">Effective discount (relative):</span>{" "}
438+
{effectiveDiscount?.mul(new Big("100")).toFixed(2)}%
439+
</span>
440+
<span>
441+
<span className="font-bold">Effective discount (absolute):</span>{" "}
442+
{offerFormData?.discount.gross.value.minus(offerFormData?.discount.net.value).toFixed(0)}{" "}
443+
{offerFormData?.discount.net.currency}
444+
</span>
445+
<span>
446+
<span className="font-bold">Net amount:</span> {offerFormData?.discount.net.value.round(0).toFixed(0)}{" "}
447+
{offerFormData?.discount.net.currency}
448+
</span>
449+
<span>
450+
<span className="font-bold">Valid until:</span> {offerFormData?.ttl.ttl.toDateString()} (
451+
{offerFormData && humanReadableDuration("en", offerFormData.ttl.ttl)})
452+
</span>
453+
</div>
454+
</OfferConfirmDrawer>
455+
456+
{value.status === "Accepted" && "keyset_id" in value ? (
457+
<ConfirmDrawer
458+
title="Confirm activating keyset"
459+
description="Are you sure you want to activate the keyset for this quote?"
460+
open={activateKeysetConfirmDrawerOpen}
461+
onOpenChange={setActivateKeysetConfirmDrawerOpen}
462+
onSubmit={() => {
463+
onActivateKeyset()
464+
setActivateKeysetConfirmDrawerOpen(false)
465+
}}
466+
submitButtonText="Yes, activate keyset"
467+
trigger={
468+
<Button
469+
className="flex-1"
470+
disabled={isFetching || activateKeysetMutation.isPending || !newKeyset}
471+
variant="default"
472+
>
473+
Activate Keyset {activateKeysetMutation.isPending && <LoaderIcon className="stroke-1 animate-spin" />}
474+
</Button>
475+
}
476+
/>
477+
) : (
478+
<></>
479+
)}
480+
481+
{value.status === "Accepted" && "keyset_id" in value && !ebillPaid && !newKeyset ? (
482+
<ConfirmDrawer
483+
title="Confirm requesting to mint"
484+
description="Are you sure you want to request to mint from this e-bill?"
485+
open={requestToMintConfirmDrawerOpen}
486+
onOpenChange={setRequestToMintConfirmDrawerOpen}
487+
onSubmit={() => {
488+
onRequestToMint()
489+
setRequestToMintConfirmDrawerOpen(false)
490+
}}
491+
submitButtonText="Yes, request to mint"
492+
trigger={
493+
<Button className="flex-1" disabled={isFetching || requestToMintMutation.isPending} variant="default">
494+
Request to Pay {requestToMintMutation.isPending && <LoaderIcon className="stroke-1 animate-spin" />}
495+
</Button>
496+
}
497+
/>
498+
) : (
499+
<></>
500+
)}
501+
</div>
502+
503+
{mintRequestResponse && (
504+
<div className="mt-4 p-4 bg-gray-50 rounded-lg">
505+
<h3 className="font-bold mb-2">Payment Request</h3>
506+
<div className="space-y-2">
507+
<div>
508+
<span className="font-bold">ID</span>
509+
<span className="font-mono ml-2">{mintRequestResponse.request_id}</span>
510+
</div>
511+
<div>
512+
<span className="font-bold">Details</span>
513+
<div className="font-mono text-sm mt-1 p-2 bg-white rounded border break-all">
514+
{mintRequestResponse.request}
515+
</div>
516+
</div>
517+
</div>
518+
</div>
427519
)}
428-
</div>
520+
</>
429521
)
430522
}
431523

@@ -706,7 +798,7 @@ function Quote({ value, isFetching }: { value: InfoReply; isFetching: boolean })
706798
</TableBody>
707799
</Table>
708800

709-
<QuoteActions value={value} isFetching={isFetching} newKeyset={newKeyset} />
801+
<QuoteActions value={value} isFetching={isFetching} newKeyset={newKeyset} ebillPaid={ebillPaid ?? false} />
710802
</div>
711803
)
712804
}

0 commit comments

Comments
 (0)