Skip to content

Commit

Permalink
Handle successful local Crypto Payment (#1976)
Browse files Browse the repository at this point in the history
* close dialog once payment tx has been mined

* remove console logs

* add success screen

* add success modal

* lingui extract

* Apply suggestions from code review

Co-authored-by: Thibaut Sardan <33178835+Tbaut@users.noreply.github.com>

* lingui extract

* missing brace

* whitespace

* make ConfirmPlan methods nullable

* update success text for crypto

* lingui extract

* disable payment confirmation if no card is available

Co-authored-by: Thibaut Sardan <33178835+Tbaut@users.noreply.github.com>
Co-authored-by: GitHub Actions <actions@github.com>
Co-authored-by: Tanmoy Basak Anjan <tanmoy3399@gmail.com>
  • Loading branch information
4 people committed Mar 3, 2022
1 parent 38b8376 commit b6cd6ba
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import PaymentMethodSelector from "./PaymentMethodSelector"
import ConfirmPlan from "../Common/ConfirmPlan"
import { useBilling } from "../../../../../Contexts/BillingContext"
import { Product, ProductPrice, ProductPriceRecurringInterval } from "@chainsafe/files-api-client"
import PlanSuccess from "./PlanSuccess"
import PlanSuccess from "../Common/PlanSuccess"
import DowngradeDetails from "./DowngradeDetails"
import { PaymentMethod } from "../../../../../Contexts/BillingContext"
import CryptoPayment from "../Common/CryptoPayment"
Expand Down Expand Up @@ -156,7 +156,7 @@ const ChangeProductModal = ({ onClose }: IChangeProductModal) => {
plans={plans}
/>
)}
{ slide === "downgradeDetails" && selectedPlan && (
{slide === "downgradeDetails" && selectedPlan && (
<DowngradeDetails
goBack={() => {setSlide("select")}}
goToPlanDetails={() => setSlide("planDetails")}
Expand Down Expand Up @@ -209,12 +209,14 @@ const ChangeProductModal = ({ onClose }: IChangeProductModal) => {
/>}
{slide === "cryptoPayment" && <CryptoPayment
planPrice={selectedPrice}
onSuccess={() => setSlide("planSuccess")}
onClose={onClose}
/>}
{slide === "planSuccess" && selectedPlan && selectedPrice && <PlanSuccess
{slide === "planSuccess" && selectedPlan && selectedPrice && selectedPaymentMethod && <PlanSuccess
onClose={onClose}
plan={selectedPlan}
planPrice={selectedPrice}
paymentMethod={selectedPaymentMethod}
/>}
</Modal>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ const useStyles = makeStyles(({ constants, palette }: CSFTheme) =>
interface IConfirmPlan {
plan: Product
planPrice: ProductPrice
goToSelectPlan: () => void
goToPaymentMethod: () => void
goToSelectPlan?: () => void
goToPaymentMethod?: () => void
onChangeSubscription: () => void
loadingChangeSubscription: boolean
paymentMethod: PaymentMethod
Expand Down Expand Up @@ -176,6 +176,7 @@ const ConfirmPlan = ({
component="p"
className={classes.textButton}
onClick={goToSelectPlan}
disabled={!goToSelectPlan}
data-cy="link-edit-plan"
>
<Trans>Edit plan</Trans>
Expand Down Expand Up @@ -218,6 +219,7 @@ const ConfirmPlan = ({
component="p"
className={classes.textButton}
onClick={goToPaymentMethod}
disabled={!goToPaymentMethod}
data-cy="link-edit-payment-method"
>
<Trans>Edit payment method</Trans>
Expand Down Expand Up @@ -452,7 +454,7 @@ const ConfirmPlan = ({
<Button
variant="primary"
loading={loadingChangeSubscription || !checkSubscriptionUpdate}
disabled={loadingChangeSubscription || !checkSubscriptionUpdate}
disabled={loadingChangeSubscription || !checkSubscriptionUpdate || (paymentMethod === "creditCard" && !defaultCard)}
onClick={onChangeSubscription}
testId="confirm-plan-change"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ const useStyles = makeStyles(({ constants, palette, zIndex, animation, breakpoin
interface ICryptoPayment {
planPrice?: ProductPrice
onClose: () => void
onSuccess: () => void
}

const iconMap: { [key: string]: React.FC<any> } = {
Expand All @@ -242,7 +243,7 @@ const symbolMap: { [key: string]: string } = {
usdc: "USDC"
}

const CryptoPayment = ({ planPrice, onClose }: ICryptoPayment) => {
const CryptoPayment = ({ planPrice, onClose, onSuccess }: ICryptoPayment) => {
const classes = useStyles()
const { selectWallet } = useFilesApi()
const { isReady, network, provider, wallet, tokens, switchNetwork, checkIsReady, ethBalance } = useWeb3()
Expand Down Expand Up @@ -358,27 +359,32 @@ const CryptoPayment = ({ planPrice, onClose }: ICryptoPayment) => {
if (!provider || !selectedCurrency || !selectedPaymentMethod) return

const signer = provider.getSigner()
let transferSuccess = false
try {
setTransferActive(true)
if (selectedCurrency === "ethereum") {
await (await signer.sendTransaction({
to: selectedPaymentMethod.address,
value: utils.parseEther(selectedPaymentMethod.amount)
})).wait(1)
})).wait(5)
} else {
const token = Object.values(tokens).find(t => t.symbol?.toLowerCase() === selectedCurrency)
if (!token || !token.transfer) return
await (await token.transfer(
selectedPaymentMethod.address,
utils.parseUnits(selectedPaymentMethod.amount, token.decimals)
)).wait(1)
)).wait(5)
}
await fetchCurrentSubscription()
transferSuccess = true
onSuccess()
} catch (error) {
console.error(error)
} finally {
setTransferActive(false)
transferSuccess && onClose()
}
}, [provider, selectedCurrency, selectedPaymentMethod, tokens])
}, [fetchCurrentSubscription, onClose, onSuccess, provider, selectedCurrency, selectedPaymentMethod, tokens])

const handleSwitchNetwork = useCallback(async () => {
await switchNetwork(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Button, CheckCircleIcon, CheckIcon, Divider, formatBytes, Link, Typogr
import { Trans } from "@lingui/macro"
import { ROUTE_LINKS } from "../../../../FilesRoutes"
import clsx from "clsx"
import { PaymentMethod } from "../../../../../Contexts/BillingContext"

const useStyles = makeStyles(({ constants, palette }: CSFTheme) =>
createStyles({
Expand Down Expand Up @@ -84,10 +85,11 @@ const useStyles = makeStyles(({ constants, palette }: CSFTheme) =>
interface IPlanSuccess {
plan: Product
planPrice: ProductPrice
paymentMethod: PaymentMethod
onClose: () => void
}

const PlanSuccess = ({ plan, onClose, planPrice }: IPlanSuccess) => {
const PlanSuccess = ({ plan, onClose, planPrice, paymentMethod }: IPlanSuccess) => {
const classes = useStyles()
const newPlanCapacity = formatBytes(Number(planPrice?.metadata?.storage_size_bytes), 2)

Expand Down Expand Up @@ -164,6 +166,16 @@ const PlanSuccess = ({ plan, onClose, planPrice }: IPlanSuccess) => {
</Link>
</Typography>
</div>
{paymentMethod === "crypto" &&
<div className={classes.rowBox}>
<Typography>
<Trans>
Crypto payments may take a few minutes to be processed.
The subscription update will reflect on next login.
</Trans>
</Typography>
</div>
}
<section className={classes.bottomSection}>
<div className={classes.buttons}>
<Button
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useMemo, useState } from "react"
import React, { useCallback, useEffect, useMemo, useState } from "react"
import { makeStyles, createStyles, useThemeSwitcher } from "@chainsafe/common-theme"
import { CSFTheme } from "../../../../../Themes/types"
import { Modal } from "@chainsafe/common-components"
Expand All @@ -7,6 +7,7 @@ import { useBilling } from "../../../../../Contexts/BillingContext"
import { useFilesApi } from "../../../../../Contexts/FilesApiContext"
import ConfirmPlan from "../Common/ConfirmPlan"
import { formatSubscriptionError } from "../utils/formatSubscriptionError"
import PlanSuccess from "../Common/PlanSuccess"

const useStyles = makeStyles(({ constants, breakpoints }: CSFTheme) =>
createStyles({
Expand All @@ -27,6 +28,8 @@ const useStyles = makeStyles(({ constants, breakpoints }: CSFTheme) =>
})
)

type PayInvoiceModalSlides = "confirmPlan" | "planSuccess" | "cryptoPayment"

interface IChangeProductModal {
invoiceId: string
onClose: () => void
Expand All @@ -40,14 +43,19 @@ const PayInvoiceModal = ({ onClose, invoiceId }: IChangeProductModal) => {
const invoiceToPay = useMemo(() => invoices?.find(i => i.uuid === invoiceId), [invoices, invoiceId])
const [payingInvoice, setPayingInvoice] = useState(false)
const [errorMessage, setErrorMessage] = useState<string | undefined>()
const [slide, setSlide] = useState<PayInvoiceModalSlides | undefined>()

const payInvoice = useCallback(() => {
if (!invoiceToPay) return

try {
setPayingInvoice(true)
setErrorMessage(undefined)
filesApiClient.payInvoice(invoiceToPay.uuid).then(refreshInvoices)
filesApiClient.payInvoice(invoiceToPay.uuid)
.then(() => {
setSlide("planSuccess")
refreshInvoices()
})
} catch (error: any) {
const errorMessage = formatSubscriptionError(error)
setErrorMessage(errorMessage)
Expand All @@ -56,6 +64,15 @@ const PayInvoiceModal = ({ onClose, invoiceId }: IChangeProductModal) => {
}
}, [filesApiClient, invoiceToPay, refreshInvoices])

useEffect(() => {
if (!slide) {
setSlide(invoiceToPay?.payment_method === "crypto"
? "cryptoPayment"
: "confirmPlan"
)
}
}, [invoiceToPay, slide])

if (!invoiceToPay) return null

return (
Expand All @@ -71,18 +88,23 @@ const PayInvoiceModal = ({ onClose, invoiceId }: IChangeProductModal) => {
testId="cryptoPayment"
onClose={onClose}
>
{invoiceToPay?.payment_method === "crypto"
? <CryptoPayment onClose={onClose}/>
: <ConfirmPlan
plan={{ ...invoiceToPay.product, prices: [invoiceToPay?.product.price] }}
planPrice={invoiceToPay?.product.price}
goToSelectPlan={() => undefined }
goToPaymentMethod={() => undefined }
onChangeSubscription={payInvoice}
loadingChangeSubscription={payingInvoice}
subscriptionErrorMessage={errorMessage}
paymentMethod={invoiceToPay.payment_method === "stripe" ? "creditCard" : "crypto"}
/>
{slide === "cryptoPayment" && <CryptoPayment
onClose={onClose}
onSuccess={() => setSlide("planSuccess")}
/>}
{slide === "confirmPlan" && <ConfirmPlan
plan={{ ...invoiceToPay.product, prices: [invoiceToPay.product.price] }}
planPrice={invoiceToPay.product.price}
onChangeSubscription={payInvoice}
loadingChangeSubscription={payingInvoice}
subscriptionErrorMessage={errorMessage}
paymentMethod={invoiceToPay.payment_method === "stripe" ? "creditCard" : "crypto"}
/>}
{slide === "planSuccess" && <PlanSuccess
plan={{ ...invoiceToPay.product, prices: [invoiceToPay.product.price] }}
planPrice={invoiceToPay.product.price}
onClose={onClose}
paymentMethod={invoiceToPay.payment_method === "stripe" ? "creditCard" : "crypto"}/>
}
</Modal>
)
Expand Down
3 changes: 3 additions & 0 deletions packages/files-ui/src/locales/de/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ msgstr ""
msgid "Credit Card is expiring soon"
msgstr ""

msgid "Crypto payments may take a few minutes to be processed. The subscription update will reflect on next login."
msgstr ""

msgid "DAI, USDC, ETH or BTC"
msgstr ""

Expand Down
3 changes: 3 additions & 0 deletions packages/files-ui/src/locales/en/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ msgstr "Create your public username in <0>Settings</0>!"
msgid "Credit Card is expiring soon"
msgstr "Credit Card is expiring soon"

msgid "Crypto payments may take a few minutes to be processed. The subscription update will reflect on next login."
msgstr "Crypto payments may take a few minutes to be processed. The subscription update will reflect on next login."

msgid "DAI, USDC, ETH or BTC"
msgstr "DAI, USDC, ETH or BTC"

Expand Down
3 changes: 3 additions & 0 deletions packages/files-ui/src/locales/es/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ msgstr ""
msgid "Credit Card is expiring soon"
msgstr ""

msgid "Crypto payments may take a few minutes to be processed. The subscription update will reflect on next login."
msgstr ""

msgid "DAI, USDC, ETH or BTC"
msgstr ""

Expand Down
3 changes: 3 additions & 0 deletions packages/files-ui/src/locales/fr/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ msgstr "Créez votre nom d'utilisateur public dans <0>Paramètres</0> !"
msgid "Credit Card is expiring soon"
msgstr "La carte de crédit va bientôt expirer"

msgid "Crypto payments may take a few minutes to be processed. The subscription update will reflect on next login."
msgstr ""

msgid "DAI, USDC, ETH or BTC"
msgstr "DAI, USDC, ETH ou BTC"

Expand Down
3 changes: 3 additions & 0 deletions packages/files-ui/src/locales/no/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ msgstr ""
msgid "Credit Card is expiring soon"
msgstr ""

msgid "Crypto payments may take a few minutes to be processed. The subscription update will reflect on next login."
msgstr ""

msgid "DAI, USDC, ETH or BTC"
msgstr ""

Expand Down

0 comments on commit b6cd6ba

Please sign in to comment.