import React, { useContext } from 'react' import { Button, Form, Input, Select, Spinner, useForm, VSpace, } from '@sudoplatform/web-ui' import FormItem from 'antd/lib/form/FormItem' import { ProvisionalVirtualCard, ProvisioningState, VirtualCard, } from '@sudoplatform/sudo-virtual-cards' import { useAsync, useAsyncFn } from 'react-use' import { ErrorFeedback } from '../../ErrorFeedback' import { message } from 'antd' import { AppContext } from '../../../containers/AppContext' import { CachePolicy } from '@sudoplatform/sudo-common' import { delay } from '../../../util/delay' interface VirtualCardInputs { cardHolder: string alias: string sudo: string fundingSource: string } interface Props { onVirtualCardProvisioned?: (virtualCard: VirtualCard) => void sudoId: string } export const AddVirtualCardForm: React.FC = ({ onVirtualCardProvisioned, sudoId, }) => { const { virtualCardsClient, profilesClient } = useContext(AppContext) const fundingSourcesResult = useAsync(async () => { return ( await virtualCardsClient.listFundingSources({ cachePolicy: CachePolicy.RemoteOnly, }) ).items }) const [form] = useForm() const pollForProvisionedCard = async ( id: string, interval = 1000, maxNumberOfPolls = 10, ): Promise => { let provisional: ProvisionalVirtualCard | undefined for (let i = 0; i < maxNumberOfPolls; ++i) { provisional = await virtualCardsClient.getProvisionalCard({ id, cachePolicy: CachePolicy.RemoteOnly, }) if ( provisional?.card && provisional.provisioningState === ProvisioningState.Completed ) { return provisional.card } await delay(interval) } return provisional } const isProvisionalCard = ( card: ProvisionalVirtualCard | VirtualCard, ): card is ProvisionalVirtualCard => { return (card as ProvisionalVirtualCard).provisioningState !== undefined } const isVirtualCard = ( card: ProvisionalVirtualCard | VirtualCard, ): card is VirtualCard => { return (card as VirtualCard).last4 !== undefined } const [submitVirtualCardResult, submitVirtualCard] = useAsyncFn( async (input: VirtualCardInputs) => { const ownershipProof = await profilesClient.getOwnershipProof( sudoId, 'sudoplatform.virtual-cards.virtual-card', ) const result = await virtualCardsClient.provisionVirtualCard({ ownershipProofs: [ownershipProof], fundingSourceId: input.fundingSource, currency: 'USD', cardHolder: input.cardHolder, metadata: { alias: input.alias, }, }) if (result.provisioningState === ProvisioningState.Provisioning) { void message.success('Virtual Card Provisioning...') } else if (result.provisioningState === ProvisioningState.Failed) { void message.error('Failed to provision Virtual Card') throw new Error('Failed to provision Virtual Card.') } void pollForProvisionedCard(result.id).then((c) => { if (c) { if ( isProvisionalCard(c) && c.provisioningState === ProvisioningState.Completed && c.card ) { onVirtualCardProvisioned?.(c.card) } else if (isVirtualCard(c)) { onVirtualCardProvisioned?.(c) } } }) }, ) return (
{fundingSourcesResult.loading ? ( <> Loading... ) : fundingSourcesResult.value?.length ? ( ) : ( <>Please add a funding source )} {submitVirtualCardResult.error && ( )}
) }