diff --git a/packages/common-components/src/Icons/icons/Bitcoin.icon.tsx b/packages/common-components/src/Icons/icons/Bitcoin.icon.tsx new file mode 100644 index 0000000000..16eea01609 --- /dev/null +++ b/packages/common-components/src/Icons/icons/Bitcoin.icon.tsx @@ -0,0 +1,7 @@ +import * as React from "react" +import createSvgIcon from "../createSvgIcon" +import { ReactComponent as BitcoinSvg } from "../svgs/bitcoin.svg" + +export { BitcoinSvg } + +export default createSvgIcon() diff --git a/packages/common-components/src/Icons/icons/Dai.icon.tsx b/packages/common-components/src/Icons/icons/Dai.icon.tsx new file mode 100644 index 0000000000..57b039c17b --- /dev/null +++ b/packages/common-components/src/Icons/icons/Dai.icon.tsx @@ -0,0 +1,7 @@ +import * as React from "react" +import createSvgIcon from "../createSvgIcon" +import { ReactComponent as DaiSvg } from "../svgs/dai.svg" + +export { DaiSvg } + +export default createSvgIcon() diff --git a/packages/common-components/src/Icons/icons/Ethereum.icon.tsx b/packages/common-components/src/Icons/icons/Ethereum.icon.tsx new file mode 100644 index 0000000000..5c794a8140 --- /dev/null +++ b/packages/common-components/src/Icons/icons/Ethereum.icon.tsx @@ -0,0 +1,7 @@ +import * as React from "react" +import createSvgIcon from "../createSvgIcon" +import { ReactComponent as EthereumSvg } from "../svgs/ethereum.svg" + +export { EthereumSvg } + +export default createSvgIcon() diff --git a/packages/common-components/src/Icons/icons/Usdc.icon.tsx b/packages/common-components/src/Icons/icons/Usdc.icon.tsx new file mode 100644 index 0000000000..cb7eb1b434 --- /dev/null +++ b/packages/common-components/src/Icons/icons/Usdc.icon.tsx @@ -0,0 +1,7 @@ +import * as React from "react" +import createSvgIcon from "../createSvgIcon" +import { ReactComponent as UsdcSvg } from "../svgs/usdc.svg" + +export { UsdcSvg } + +export default createSvgIcon() diff --git a/packages/common-components/src/Icons/index.ts b/packages/common-components/src/Icons/index.ts index 8945407990..92e0271aed 100644 --- a/packages/common-components/src/Icons/index.ts +++ b/packages/common-components/src/Icons/index.ts @@ -6,6 +6,7 @@ export { default as AmexCardIcon, AmexCardSvg } from "./icons/AmexCard.icon" export { default as ArrowLeftIcon, ArrowLeftSvg } from "./icons/ArrowLeft.icon" export { default as ArrowRightIcon, ArrowRightSvg } from "./icons/ArrowRight.icon" export { default as BellIcon, BellSvg } from "./icons/Bell.icon" +export { default as BitcoinIcon, BitcoinSvg } from "./icons/Bitcoin.icon" export { default as BulbIcon, BulbSvg } from "./icons/Bulb.icon" export { default as CaretDownIcon, CaretDownSvg } from "./icons/CaretDown.icon" export { default as CaretUpIcon, CaretUpSvg } from "./icons/CaretUp.icon" @@ -18,6 +19,7 @@ export { default as CopyIcon, CopySvg } from "./icons/Copy.icon" export { default as CreditCardIcon, CreditCardSvg } from "./icons/CreditCard.icon" export { default as CrossIcon, CrossSvg } from "./icons/Cross.icon" export { default as CrossOutlinedIcon, CrossOutlinedSvg } from "./icons/CrossOutlined.icon" +export { default as DaiIcon, DaiSvg } from "./icons/Dai.icon" export { default as DatabaseIcon, DatabaseSvg } from "./icons/Database.icon" export { default as DeleteIcon, DeleteSvg } from "./icons/Delete.icon" export { default as DinersclubCardIcon, DinersclubCardSvg } from "./icons/DinersclubCard.icon" @@ -28,6 +30,7 @@ export { default as DocumentIcon, DocumentSvg } from "./icons/Document.icon" export { default as DownloadIcon, DownloadSvg } from "./icons/Download.icon" export { default as EditIcon, EditSvg } from "./icons/Edit.icon" export { default as EthereumLogoIcon, EthereumLogoSvg } from "./icons/EthereumLogo.icon" +export { default as EthereumIcon, EthereumSvg } from "./icons/Ethereum.icon" export { default as ExclamationCircleIcon, ExclamationCircleSvg } from "./icons/ExclamationCircle.icon" export { default as ExclamationCircleInverseIcon, ExclamationCircleInverseSvg } from "./icons/ExclamationCircleInverse.icon" export { default as ExportIcon, ExportSvg } from "./icons/Export.icon" @@ -75,6 +78,7 @@ export { default as TableIcon, TableSvg } from "./icons/Table.icon" export { default as UpdateIcon, UpdateSvg } from "./icons/Update.icon" export { default as UploadIcon, UploadSvg } from "./icons/Upload.icon" export { default as UnionpayCardIcon, UnionpayCardSvg } from "./icons/UnionpayCard.icon" +export { default as UsdcIcon, UsdcSvg } from "./icons/Usdc.icon" export { default as UserIcon, UserSvg } from "./icons/User.icon" export { default as UserShareIcon, UserShareSvg } from "./icons/UserShare.icon" export { default as VisaCardIcon, VisaCardSvg } from "./icons/VisaCard.icon" diff --git a/packages/common-components/src/Icons/svgs/bitcoin.svg b/packages/common-components/src/Icons/svgs/bitcoin.svg new file mode 100644 index 0000000000..07c7a8dba1 --- /dev/null +++ b/packages/common-components/src/Icons/svgs/bitcoin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/common-components/src/Icons/svgs/dai.svg b/packages/common-components/src/Icons/svgs/dai.svg new file mode 100644 index 0000000000..372bd7662b --- /dev/null +++ b/packages/common-components/src/Icons/svgs/dai.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/common-components/src/Icons/svgs/ethereum.svg b/packages/common-components/src/Icons/svgs/ethereum.svg new file mode 100644 index 0000000000..1b6f4b1a00 --- /dev/null +++ b/packages/common-components/src/Icons/svgs/ethereum.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/common-components/src/Icons/svgs/usdc.svg b/packages/common-components/src/Icons/svgs/usdc.svg new file mode 100644 index 0000000000..c683dce03d --- /dev/null +++ b/packages/common-components/src/Icons/svgs/usdc.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/common-components/src/Modal/Modal.tsx b/packages/common-components/src/Modal/Modal.tsx index 3f156cd5e1..f94adbff93 100644 --- a/packages/common-components/src/Modal/Modal.tsx +++ b/packages/common-components/src/Modal/Modal.tsx @@ -70,7 +70,7 @@ const useStyles = makeStyles( position: "absolute", zIndex: 2, "& svg": { - stroke: palette.common?.black.main + stroke: "var(--gray10)" }, "&.right": { transform: "translate(-50%, 50%)", diff --git a/packages/common-components/src/ProgressBar/CircularProgressBar.tsx b/packages/common-components/src/ProgressBar/CircularProgressBar.tsx index 00d5b9fea4..b9e80f2407 100644 --- a/packages/common-components/src/ProgressBar/CircularProgressBar.tsx +++ b/packages/common-components/src/ProgressBar/CircularProgressBar.tsx @@ -50,6 +50,21 @@ const useStyles = makeStyles((theme: ITheme) => }, error: { stroke: theme.palette.error.main + }, + label: { + top: 0, + left: 0, + bottom: 0, + right: 0, + position: "absolute", + display: "flex", + alignItems: "center", + justifyContent: "center", + fontSize: 12 + }, + wrapper: { + position: "relative", + display: "inline-flex" } }) ) @@ -60,6 +75,7 @@ export type ProgressBarVariant = "primary" | "secondary" export interface ICircularProgressBarProps { className?: string + label?: string progress: number size?: ProgressBarSize variant?: ProgressBarVariant @@ -75,7 +91,8 @@ const CircularProgressBar: React.FC = ({ variant, showBackdrop = true, width, - className + className, + label }) => { const strokeWidth = size === "small" ? 2 : size === "medium" ? 3 : 4 const radius = width @@ -97,28 +114,31 @@ const CircularProgressBar: React.FC = ({ }) return ( - - {showBackdrop && ( +
+ {label && {label}} + + {showBackdrop && ( + + )} + - )} - - - + +
) } diff --git a/packages/common-components/src/stories/ProgressBar.stories.tsx b/packages/common-components/src/stories/ProgressBar.stories.tsx index 758e497482..aa92672ef3 100644 --- a/packages/common-components/src/stories/ProgressBar.stories.tsx +++ b/packages/common-components/src/stories/ProgressBar.stories.tsx @@ -1,5 +1,5 @@ import React, { useState } from "react" -import { withKnobs, select, boolean, number } from "@storybook/addon-knobs" +import { withKnobs, select, boolean, number, text } from "@storybook/addon-knobs" import { ProgressBar, CircularProgressBar } from "../ProgressBar" export default { @@ -57,6 +57,7 @@ export const CircularProgressBarDemo = (): React.ReactNode => { [undefined, "small", "medium", "large"], undefined )} + label={text("label", "")} showBackdrop={boolean("backdrop", true)} width={number("width", 20)} progress={progress} diff --git a/packages/files-ui/package.json b/packages/files-ui/package.json index 7b8c7ccc64..4cbbae30ef 100644 --- a/packages/files-ui/package.json +++ b/packages/files-ui/package.json @@ -6,8 +6,8 @@ "@babel/core": "^7.12.10", "@babel/runtime": "^7.0.0", "@chainsafe/browser-storage-hooks": "^1.0.1", - "@chainsafe/files-api-client": "^1.18.22", - "@chainsafe/web3-context": "1.1.4", + "@chainsafe/files-api-client": "1.18.25", + "@chainsafe/web3-context": "1.3.1", "@emeraldpay/hashicon-react": "^0.5.1", "@lingui/core": "^3.7.2", "@lingui/react": "^3.7.2", @@ -51,6 +51,7 @@ "react-scripts": "3.4.4", "react-swipeable": "^6.0.1", "react-toast-notifications": "^2.4.0", + "react-qr-code":"2.0.3", "react-zoom-pan-pinch": "^1.6.1", "remark-gfm": "^1.0.0", "typescript": "~4.0.5", diff --git a/packages/files-ui/src/App.tsx b/packages/files-ui/src/App.tsx index 5301d37c85..7446e8ebf5 100644 --- a/packages/files-ui/src/App.tsx +++ b/packages/files-ui/src/App.tsx @@ -120,6 +120,12 @@ const App = () => { onboardConfig={onboardConfig} checkNetwork={false} cacheWalletSelection={canUseLocalStorage} + tokensToWatch={{ + 1: [ + { address: "0x6b175474e89094c44da98b954eedeac495271d0f" }, + { address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" } + ] + }} > createStyles({ root: { @@ -35,7 +36,8 @@ type ChangeModalSlides = "select" | "paymentMethod" | "confirmPlan" | "planSuccess" | -"downgradeDetails" +"downgradeDetails" | +"cryptoPayment" const getPrice = (plan: Product, recurrence?: ProductPriceRecurringInterval) => { return plan.prices.find(price => price?.recurring?.interval === recurrence)?.unit_amount || 0 @@ -47,9 +49,11 @@ interface IChangeProductModal { const ChangeProductModal = ({ onClose }: IChangeProductModal) => { const classes = useStyles() + const { desktop } = useThemeSwitcher() const { getAvailablePlans, changeSubscription, currentSubscription } = useBilling() const [selectedPlan, setSelectedPlan] = useState() const [selectedPrice, setSelectedPrice] = useState() + const [selectedPaymentMethod, setSelectedPaymentMethod] = useState() const [slide, setSlide] = useState("select") const [plans, setPlans] = useState() const [isLoadingChangeSubscription, setIsLoadingChangeSubscription] = useState(false) @@ -82,8 +86,8 @@ const ChangeProductModal = ({ onClose }: IChangeProductModal) => { { {slide === "planDetails" && selectedPlan && ( { - setSlide("select") - }} + goToSelectPlan={() => setSlide("select")} onSelectPlanPrice={(planPrice: ProductPrice) => { setSelectedPrice(planPrice) setSlide("paymentMethod") }} /> )} - {slide === "paymentMethod" && ( - { setSlide("planDetails") }} - onSelectPaymentMethod={() => { + onSelectPaymentMethod={(paymentMethod) => { + setSelectedPaymentMethod(paymentMethod) setSlide("confirmPlan") }} /> - )} - {slide === "confirmPlan" && selectedPlan && selectedPrice && ( - { - setSlide("select") - }} - goToPlanDetails={() => { - setSlide("planDetails") - }} - goToPaymentMethod={() => { - setSlide("paymentMethod") - }} - loadingChangeSubscription={isLoadingChangeSubscription} - onChangeSubscription={handleChangeSubscription} - isSubscriptionError={isSubscriptionError} - /> - )} - {slide === "planSuccess" && selectedPlan && selectedPrice && ( - { + setSlide("select") + }} + goToPaymentMethod={() => { + setSlide("paymentMethod") + }} + loadingChangeSubscription={isLoadingChangeSubscription} + onChangeSubscription={selectedPaymentMethod === "creditCard" ? handleChangeSubscription : () => setSlide("cryptoPayment")} + isSubscriptionError={isSubscriptionError} + paymentMethod={selectedPaymentMethod} + /> + } + {slide === "cryptoPayment" && selectedPlan && selectedPrice && + - )} + goBack={() => setSlide("confirmPlan")}/> + } + {slide === "planSuccess" && selectedPlan && selectedPrice && + } ) } diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/ConfirmPlan.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/ConfirmPlan.tsx index 61c4c78b7d..02c5f2852a 100644 --- a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/ConfirmPlan.tsx +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/ConfirmPlan.tsx @@ -5,7 +5,7 @@ import { Product, ProductPrice } from "@chainsafe/files-api-client" import { Button, CreditCardIcon, Divider, formatBytes, Typography } from "@chainsafe/common-components" import { t, Trans } from "@lingui/macro" import dayjs from "dayjs" -import { useBilling } from "../../../../../Contexts/BillingContext" +import { PaymentMethod, useBilling } from "../../../../../Contexts/BillingContext" import clsx from "clsx" const useStyles = makeStyles(({ constants, palette }: CSFTheme) => @@ -94,11 +94,11 @@ interface IConfirmPlan { plan: Product planPrice: ProductPrice goToSelectPlan: () => void - goToPlanDetails: () => void goToPaymentMethod: () => void onChangeSubscription: () => void loadingChangeSubscription: boolean isSubscriptionError: boolean + paymentMethod: PaymentMethod } const ConfirmPlan = ({ @@ -108,7 +108,8 @@ const ConfirmPlan = ({ goToPaymentMethod, onChangeSubscription, loadingChangeSubscription, - isSubscriptionError + isSubscriptionError, + paymentMethod }: IConfirmPlan) => { const classes = useStyles() const { defaultCard } = useBilling() @@ -170,31 +171,74 @@ const ConfirmPlan = ({ -
- - Payment method - -
- - Edit payment method - -
-
- {defaultCard && -
- - - •••• •••• •••• {defaultCard.last_four_digit} - -
+ {paymentMethod === "creditCard" && defaultCard && + <> +
+ + Payment method + +
+ + Edit payment method + +
+
+
+ + + •••• •••• •••• {defaultCard.last_four_digit} + +
+ + } + {paymentMethod === "crypto" && + <> +
+ + Pay with Crypto + +
+ + Edit payment + +
+
+
+
+
+
+ + Accepted currencies + +
+ + DAI, USDC, ETH or BTC + +
+
+ }
- Confirm plan change + {paymentMethod === "creditCard" + ? Confirm plan change + : Proceed to payment }
diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/CryptoPayment.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/CryptoPayment.tsx new file mode 100644 index 0000000000..7e6b22da83 --- /dev/null +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/CryptoPayment.tsx @@ -0,0 +1,492 @@ +import React, { useCallback, useEffect, useMemo, useRef, useState } from "react" +import { makeStyles, createStyles, debounce } from "@chainsafe/common-theme" +import { CSFTheme } from "../../../../../Themes/types" +import { Product, ProductPrice, UpdateSubscriptionResponse } from "@chainsafe/files-api-client" +import { + BitcoinIcon, + Button, + CircularProgressBar, + CopyIcon, + DaiIcon, + Divider, + EthereumIcon, + Loading, + Typography, + UsdcIcon +} from "@chainsafe/common-components" +import { Trans } from "@lingui/macro" +import dayjs from "dayjs" +import duration from "dayjs/plugin/duration" +import { useBilling } from "../../../../../Contexts/BillingContext" +import { useFilesApi } from "../../../../../Contexts/FilesApiContext" +import QRCode from "react-qr-code" +import { useWeb3 } from "@chainsafe/web3-context" +import { utils } from "ethers" +import clsx from "clsx" + +dayjs.extend(duration) + +const useStyles = makeStyles(({ constants, palette, zIndex, animation, breakpoints }: CSFTheme) => + createStyles({ + root: { + margin: `${constants.generalUnit * 2}px ${constants.generalUnit * 2}px` + }, + heading: { + marginTop: constants.generalUnit * 3, + marginBottom: constants.generalUnit * 2 + }, + subheading: { + marginBottom: constants.generalUnit * 3 + }, + boldText: { + fontWeight: "bold" + }, + normalWeightText: { + fontWeight: "normal" + }, + rowBox: { + display: "flex", + alignItems: "center", + padding: `${constants.generalUnit * 0.5}px 0px` + }, + middleRowBox: { + display: "flex", + alignItems: "center", + padding: `${constants.generalUnit * 0.5}px 0px` + }, + pushRightBox: { + display: "flex", + flexDirection: "column", + alignItems: "flex-end", + flex: 1 + }, + buttons: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-end", + "& > *": { + marginLeft: constants.generalUnit + } + }, + bottomSection: { + display: "flex", + flexDirection: "row", + justifyContent: "flex-end", + alignItems: "center", + margin: `${constants.generalUnit * 3}px 0px` + }, + divider: { + margin: `${constants.generalUnit}px 0` + }, + textButton: { + color: palette.primary.background, + cursor: "pointer", + textDecoration: "underline" + }, + creditCardIcon: { + marginRight: constants.generalUnit, + fill: palette.additional["gray"][9] + }, + featuresBox: { + marginTop: constants.generalUnit, + marginBottom: constants.generalUnit * 2 + }, + creditCardRow: { + display: "flex", + alignItems: "center", + marginTop: constants.generalUnit, + marginBottom: constants.generalUnit + }, + featureSeparator: { + marginBottom: constants.generalUnit + }, + error: { + marginTop: constants.generalUnit, + color: palette.error.main + }, + qrCode: { + display: "flex", + justifyContent: "center" + }, + qrCodeLabel: { + display: "flex", + justifyContent: "center", + textAlign: "center", + color: "#AFAFAF" + }, + availableCurrencies: { + display: "flex", + flexDirection: "row", + flexWrap: "wrap", + justifyContent: "space-between" + }, + currencyButton: { + width: "calc(50% - 8px)", + backgroundColor: "var(--gray4)", + color: "var(--gray10)", + borderRadius: 10, + marginTop: 4, + marginBottom: 4, + "&:hover": { + backgroundColor: "var(--gray4)", + color: "var(--gray10)" + } + }, + currencyIcon: { + "& > svg": { + fill: "var(--gray10)", + height: 16 + } + }, + copiedFlag: { + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + left: "50%", + bottom: "calc(100% + 8px)", + position: "absolute", + transform: "translate(-50%, 0%)", + zIndex: zIndex?.layer1, + transitionDuration: `${animation.transform}ms`, + opacity: 0, + visibility: "hidden", + backgroundColor: palette.additional["gray"][9], + color: palette.additional["gray"][1], + padding: `${constants.generalUnit / 2}px ${constants.generalUnit}px`, + borderRadius: 2, + "&:after": { + transitionDuration: `${animation.transform}ms`, + content: "''", + position: "absolute", + top: "100%", + left: "50%", + transform: "translate(-50%,0)", + width: 0, + height: 0, + borderLeft: "5px solid transparent", + borderRight: "5px solid transparent", + borderTop: `5px solid ${palette.additional["gray"][9]}` + }, + "&.active": { + opacity: 1, + visibility: "visible" + } + }, + copyIcon: { + fontSize: "16px", + fill: palette.additional["gray"][9], + [breakpoints.down("md")]: { + fontSize: "18px", + fill: palette.additional["gray"][9] + } + }, + copyRow: { + cursor: "pointer", + borderRadius: 10, + backgroundColor: "var(--gray4)", + padding: "5px 10px", + "& > span": { + width: "100%", + overflow: "hidden", + whiteSpace: "nowrap", + textOverflow: "ellipsis" + } + }, + loadingContainer: { + margin: `${constants.generalUnit * 4}px 0`, + display: "flex", + justifyContent: "center" + } + }) +) + +interface ICryptoPayment { + plan: Product + planPrice: ProductPrice + goBack: () => void +} + +const iconMap: { [key: string]: React.FC } = { + ethereum: EthereumIcon, + bitcoin: BitcoinIcon, + dai: DaiIcon, + usdc: UsdcIcon +} + +const symbolMap: { [key: string]: string } = { + ethereum: "ETH", + bitcoin: "BTC", + dai: "DAI", + usdc: "USDC" +} + +const CryptoPayment = ({ goBack, planPrice }: ICryptoPayment) => { + const classes = useStyles() + const { selectWallet } = useFilesApi() + const { isReady, network, provider, wallet, tokens, switchNetwork, checkIsReady, ethBalance } = useWeb3() + const { filesApiClient } = useFilesApi() + const { currentSubscription } = useBilling() + const [subResponse, setSubResponse] = useState() + const [error, setError] = useState(undefined) + const [cryptoChargeLoading, setCryptoChargeLoading] = useState(false) + const [transferActive, setTransferActive] = useState(false) + const [timeRemaining, setTimeRemaining] = useState() + const pageLoadTimestamp = useRef(dayjs().unix()) + + const [copiedDestinationAddress, setCopiedDestinationAddress] = useState(false) + const [copiedAmount, setCopiedAmount] = useState(false) + const debouncedSwitchCopiedDestinationAddress = debounce(() => setCopiedDestinationAddress(false), 3000) + const debouncedSwitchCopiedAmount = debounce(() => setCopiedAmount(false), 3000) + + useEffect(() => { + if (!currentSubscription) return undefined + + setCryptoChargeLoading(true) + filesApiClient.updateSubscription(currentSubscription.id, { + price_id: planPrice.id, + payment_method: "crypto" + }).then((response) => { + setSubResponse(response) + pageLoadTimestamp.current = dayjs().unix() + }).catch((error) => { + console.error(error) + setError(`There was a problem creating a charge ${error}`) + }).finally(() => setCryptoChargeLoading(false)) + }, [currentSubscription, filesApiClient, planPrice.id]) + + const cryptoPayment = useMemo(() => subResponse?.invoice?.crypto, [subResponse]) + const currencies = useMemo(() => cryptoPayment?.payment_methods.map(c => c.currency), [cryptoPayment]) + const [selectedCurrency, setSelectedCurrency] = useState(undefined) + + useEffect(() => { + const timer = setInterval(() => { + if (cryptoPayment) { + setTimeRemaining(dayjs.duration(cryptoPayment.expires_at - dayjs().unix(), "s").format("mm:ss")) + } + }, 1000) + + return () => { + timer && clearInterval(timer) + } + }, [cryptoPayment]) + + const selectedPaymentMethod = useMemo(() => { + return cryptoPayment && selectedCurrency + ? cryptoPayment.payment_methods.find(p => p.currency === selectedCurrency) + : undefined + }, [cryptoPayment, selectedCurrency]) + + const onCopyDestinationAddress = useCallback(() => { + if (selectedPaymentMethod) { + navigator.clipboard.writeText(selectedPaymentMethod.address) + .then(() => { + setCopiedDestinationAddress(true) + debouncedSwitchCopiedDestinationAddress() + }).catch(console.error) + } + }, [debouncedSwitchCopiedDestinationAddress, selectedPaymentMethod]) + + const onCopyAmount = useCallback(() => { + if (selectedPaymentMethod) { + navigator.clipboard.writeText(selectedPaymentMethod.amount) + .then(() => { + setCopiedAmount(true) + debouncedSwitchCopiedAmount() + }).catch(console.error) + } + }, [debouncedSwitchCopiedAmount, selectedPaymentMethod]) + + const isBalanceSufficient = useMemo(() => { + const selectedPaymentMethod = cryptoPayment?.payment_methods.find(p => p.currency === selectedCurrency) + if (selectedCurrency === "bitcoin") { + return false + } else if (selectedCurrency === "ethereum") { + return ethBalance && selectedPaymentMethod && ethBalance > Number(selectedPaymentMethod.amount) + } else { + const token = Object.values(tokens).find(t => t.symbol?.toLowerCase() === selectedCurrency) + return token && selectedPaymentMethod && token.balance >= Number(selectedPaymentMethod.amount) + } + }, [tokens, ethBalance, selectedCurrency, cryptoPayment]) + + const handlePayment = useCallback(async () => { + if (!provider || !selectedCurrency) return + const selectedPaymentMethod = cryptoPayment?.payment_methods.find(p => p.currency === selectedCurrency) + if (!selectedPaymentMethod) return + + const signer = provider.getSigner() + try { + setTransferActive(true) + if (selectedCurrency === "ethereum") { + await (await signer.sendTransaction({ + to: selectedPaymentMethod.address, + value: utils.parseEther(selectedPaymentMethod.amount) + })).wait(1) + } else { + const token = Object.values(tokens).find(t => t.symbol?.toLowerCase() === selectedCurrency) + if (!token || !token.transfer) return + // TODO Set loading state here + await (await token.transfer( + selectedPaymentMethod.address, + utils.parseUnits(selectedPaymentMethod.amount, token.decimals) + )).wait(1) + } + } catch (error) { + console.error(error) + } finally { + setTransferActive(false) + } + }, [cryptoPayment, provider, selectedCurrency, tokens]) + + const handleSwitchNetwork = useCallback(async () => { + await switchNetwork(1) + await checkIsReady() + }, [checkIsReady, switchNetwork]) + + return ( +
+
+ + Pay with crypto + + {cryptoPayment &&
+ +
} +
+ {cryptoChargeLoading &&
+ +
} + {error && + + Failed to create a charge + + } + {cryptoPayment && + <> +
+ Total +
+ + {subResponse?.invoice?.currency?.toUpperCase()} {subResponse?.invoice?.amount} + +
+
+ + {!selectedCurrency && currencies && + <> + Select a cryptocurrency +
+ {currencies.map(c => { + const CurrencyIcon = iconMap[c] || null + return + })} +
+ + } + {selectedCurrency && selectedPaymentMethod && + <> +
+ +
+
+ + Only send {selectedCurrency} to this address + +
+ + Destination Address +
+ {selectedPaymentMethod.address} +
+ +
+ + + Copied! + + +
+
+
+ Total Amount +
+ + {selectedPaymentMethod.amount} {symbolMap[selectedCurrency]} + +
+ +
+ + + Copied! + + +
+
+
+ + } + + } +
+
+ + {selectedCurrency && selectedCurrency !== "bitcoin" && !isReady && + + } + {selectedCurrency && selectedCurrency !== "bitcoin" && isReady && network !== 1 && + + } + {selectedCurrency && selectedCurrency !== "bitcoin" && isReady && network === 1 && + + } +
+
+
+ ) +} + +export default CryptoPayment \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/DowngradeDetails.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/DowngradeDetails.tsx index 966530dacb..3f97cdbe6a 100644 --- a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/DowngradeDetails.tsx +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/DowngradeDetails.tsx @@ -164,7 +164,7 @@ const DowngradeDetails = ({ plan, goBack, goToPlanDetails, shouldCancelPlan, onC
@@ -174,4 +177,4 @@ const PlanDetails = ({ goBack, onSelectPaymentMethod }: IPaymentMethodProps) => ) } -export default PlanDetails \ No newline at end of file +export default PaymentMethodSelector \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PlanDetails.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PlanDetails.tsx index 79c198fc8a..f08023aa43 100644 --- a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PlanDetails.tsx +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PlanDetails.tsx @@ -73,7 +73,8 @@ interface IPlanDetails { const PlanDetails = ({ plan, goToSelectPlan, onSelectPlanPrice }: IPlanDetails) => { const classes = useStyles() const monthlyPrice = plan.prices.find((price) => price.recurring.interval === "month") - const yearlyPrice = plan.prices.find((price) => price.recurring.interval === "year") + // TODO Revert this to year when testing is complete + const yearlyPrice = plan.prices.find((price) => price.recurring.interval === "day") const currentPlanStorage = formatBytes(Number(monthlyPrice?.metadata?.storage_size_bytes), 2) const [billingPeriod, setBillingPeriod] = useState<"monthly" | "yearly">(monthlyPrice ? "monthly" : "yearly") @@ -189,7 +190,7 @@ const PlanDetails = ({ plan, goToSelectPlan, onSelectPlanPrice }: IPlanDetails)
diff --git a/packages/files-ui/src/Contexts/BillingContext.tsx b/packages/files-ui/src/Contexts/BillingContext.tsx index d3c7354536..b16c2613a5 100644 --- a/packages/files-ui/src/Contexts/BillingContext.tsx +++ b/packages/files-ui/src/Contexts/BillingContext.tsx @@ -4,9 +4,11 @@ import { ReactNode, useEffect, useState } from "react" import { Card, CurrentSubscription, InvoiceResponse, Product } from "@chainsafe/files-api-client" import { useCallback } from "react" import { t } from "@lingui/macro" -import { PaymentMethod } from "@stripe/stripe-js" +import { PaymentMethod as StripePaymentMethod } from "@stripe/stripe-js" import { useFiles } from "./FilesContext" +export type PaymentMethod = "crypto" | "creditCard" + type BillingContextProps = { children: ReactNode | ReactNode[] } @@ -19,7 +21,7 @@ interface IBillingContext { fetchCurrentSubscription: () => void getAvailablePlans: () => Promise deleteCard: (card: Card) => Promise - updateDefaultCard: (id: PaymentMethod["id"]) => Promise + updateDefaultCard: (id: StripePaymentMethod["id"]) => Promise invoices?: InvoiceResponse[] cancelCurrentSubscription: () => Promise } @@ -120,7 +122,7 @@ const BillingProvider = ({ children }: BillingContextProps) => { }) }, [filesApiClient]) - const updateDefaultCard = useCallback((id: PaymentMethod["id"]) => + const updateDefaultCard = useCallback((id: StripePaymentMethod["id"]) => filesApiClient.updateDefaultCard({ id }) , [filesApiClient]) diff --git a/packages/files-ui/src/locales/de/messages.po b/packages/files-ui/src/locales/de/messages.po index 4a3a215228..89bcd34d37 100644 --- a/packages/files-ui/src/locales/de/messages.po +++ b/packages/files-ui/src/locales/de/messages.po @@ -40,6 +40,9 @@ msgstr "Es existiert bereits eine Datei mit demselben Namen" msgid "Accept" msgstr "Akzeptieren" +msgid "Accepted currencies" +msgstr "" + msgid "Access your billing history in settings or view your" msgstr "" @@ -178,6 +181,9 @@ msgstr "" msgid "Confirmation" msgstr "" +msgid "Connect Wallet" +msgstr "" + msgid "Connect Wallet to Files" msgstr "Wallet mit Dateien verbinden" @@ -280,6 +286,9 @@ msgstr "Löschen" msgid "Delete selected" msgstr "" +msgid "Destination Address" +msgstr "" + msgid "Device awaiting confirmation" msgstr "Gerät wartet auf Bestätigung" @@ -316,6 +325,9 @@ msgstr "" msgid "Drop to upload files" msgstr "" +msgid "Edit payment" +msgstr "" + msgid "Edit payment method" msgstr "" @@ -343,6 +355,9 @@ msgstr "" msgid "Failed to change subscription" msgstr "" +msgid "Failed to create a charge" +msgstr "" + msgid "Failed to get signature" msgstr "Signatur kann nicht abgerufen werden" @@ -454,6 +469,9 @@ msgstr "" msgid "Info" msgstr "Infos" +msgid "Insufficient balance" +msgstr "" + msgid "I’m done saving my backup secret phrase" msgstr "Ich bin fertig mit dem Speichern meines Sixherungsgeheimsatzes" @@ -574,6 +592,9 @@ msgstr "" msgid "One sec, getting files ready…" msgstr "" +msgid "Only send {selectedCurrency} to this address" +msgstr "" + msgid "Only you can see this." msgstr "Nur Sie können dies sehen." @@ -616,6 +637,15 @@ msgstr "Passwort:" msgid "Passwords must match" msgstr "Passwörter müssen übereinstimmen" +msgid "Pay with Crypto" +msgstr "" + +msgid "Pay with crypto" +msgstr "" + +msgid "Pay with {0}" +msgstr "" + msgid "Payment and Subscriptions" msgstr "" @@ -652,6 +682,9 @@ msgstr "Vorherige" msgid "Privacy Policy" msgstr "Datenschutzrichtlinie" +msgid "Proceed to payment" +msgstr "" + msgid "Profile and Display" msgstr "Profil und Anzeige" @@ -859,6 +892,9 @@ msgstr "" msgid "Subscription Plan" msgstr "" +msgid "Switch Network" +msgstr "" + msgid "Switch Plan" msgstr "" @@ -946,6 +982,9 @@ msgstr "" msgid "Total" msgstr "" +msgid "Total Amount" +msgstr "" + msgid "Try again" msgstr "Erneut versuchen" diff --git a/packages/files-ui/src/locales/en/messages.po b/packages/files-ui/src/locales/en/messages.po index cc56290b6d..342347daee 100644 --- a/packages/files-ui/src/locales/en/messages.po +++ b/packages/files-ui/src/locales/en/messages.po @@ -40,6 +40,9 @@ msgstr "A file with the same name already exists" msgid "Accept" msgstr "Accept" +msgid "Accepted currencies" +msgstr "Accepted currencies" + msgid "Access your billing history in settings or view your" msgstr "Access your billing history in settings or view your" @@ -178,6 +181,9 @@ msgstr "Confirm plan downgrade" msgid "Confirmation" msgstr "Confirmation" +msgid "Connect Wallet" +msgstr "Connect Wallet" + msgid "Connect Wallet to Files" msgstr "Connect Wallet to Files" @@ -280,6 +286,9 @@ msgstr "Delete" msgid "Delete selected" msgstr "Delete selected" +msgid "Destination Address" +msgstr "Destination Address" + msgid "Device awaiting confirmation" msgstr "Device awaiting confirmation" @@ -316,6 +325,9 @@ msgstr "Downloads failed" msgid "Drop to upload files" msgstr "Drop to upload files" +msgid "Edit payment" +msgstr "Edit payment" + msgid "Edit payment method" msgstr "Edit payment method" @@ -343,6 +355,9 @@ msgstr "Failed to add payment method" msgid "Failed to change subscription" msgstr "Failed to change subscription" +msgid "Failed to create a charge" +msgstr "Failed to create a charge" + msgid "Failed to get signature" msgstr "Failed to get signature" @@ -457,6 +472,9 @@ msgstr "If you think this file does not comply with our <0>Terms of Service, msgid "Info" msgstr "Info" +msgid "Insufficient balance" +msgstr "Insufficient balance" + msgid "I’m done saving my backup secret phrase" msgstr "I’m done saving my backup secret phrase" @@ -577,6 +595,9 @@ msgstr "OK" msgid "One sec, getting files ready…" msgstr "One sec, getting files ready…" +msgid "Only send {selectedCurrency} to this address" +msgstr "Only send {selectedCurrency} to this address" + msgid "Only you can see this." msgstr "Only you can see this." @@ -619,6 +640,15 @@ msgstr "Password:" msgid "Passwords must match" msgstr "Passwords must match" +msgid "Pay with Crypto" +msgstr "Pay with Crypto" + +msgid "Pay with crypto" +msgstr "Pay with crypto" + +msgid "Pay with {0}" +msgstr "Pay with {0}" + msgid "Payment and Subscriptions" msgstr "Payment and Subscriptions" @@ -655,6 +685,9 @@ msgstr "Previous" msgid "Privacy Policy" msgstr "Privacy Policy" +msgid "Proceed to payment" +msgstr "Proceed to payment" + msgid "Profile and Display" msgstr "Profile and Display" @@ -862,6 +895,9 @@ msgstr "Stored by miner" msgid "Subscription Plan" msgstr "Subscription Plan" +msgid "Switch Network" +msgstr "Switch Network" + msgid "Switch Plan" msgstr "Switch Plan" @@ -949,6 +985,9 @@ msgstr "This website uses cookies that help the website function and track inter msgid "Total" msgstr "Total" +msgid "Total Amount" +msgstr "Total Amount" + msgid "Try again" msgstr "Try again" diff --git a/packages/files-ui/src/locales/es/messages.po b/packages/files-ui/src/locales/es/messages.po index 942ea8db0b..23a93cd822 100644 --- a/packages/files-ui/src/locales/es/messages.po +++ b/packages/files-ui/src/locales/es/messages.po @@ -41,6 +41,9 @@ msgstr "Ya existe un archivo con el mismo nombre" msgid "Accept" msgstr "" +msgid "Accepted currencies" +msgstr "" + msgid "Access your billing history in settings or view your" msgstr "" @@ -179,6 +182,9 @@ msgstr "" msgid "Confirmation" msgstr "" +msgid "Connect Wallet" +msgstr "" + msgid "Connect Wallet to Files" msgstr "Conectar monedero a archivos" @@ -281,6 +287,9 @@ msgstr "Borrar" msgid "Delete selected" msgstr "" +msgid "Destination Address" +msgstr "" + msgid "Device awaiting confirmation" msgstr "Dispositivo pendiente de confirmación" @@ -317,6 +326,9 @@ msgstr "" msgid "Drop to upload files" msgstr "" +msgid "Edit payment" +msgstr "" + msgid "Edit payment method" msgstr "" @@ -344,6 +356,9 @@ msgstr "" msgid "Failed to change subscription" msgstr "" +msgid "Failed to create a charge" +msgstr "" + msgid "Failed to get signature" msgstr "No se pudo obtener la firma" @@ -458,6 +473,9 @@ msgstr "" msgid "Info" msgstr "Info" +msgid "Insufficient balance" +msgstr "" + msgid "I’m done saving my backup secret phrase" msgstr "" @@ -578,6 +596,9 @@ msgstr "" msgid "One sec, getting files ready…" msgstr "" +msgid "Only send {selectedCurrency} to this address" +msgstr "" + msgid "Only you can see this." msgstr "" @@ -620,6 +641,15 @@ msgstr "Contraseña:" msgid "Passwords must match" msgstr "Las contraseñas deben coincidir" +msgid "Pay with Crypto" +msgstr "" + +msgid "Pay with crypto" +msgstr "" + +msgid "Pay with {0}" +msgstr "" + msgid "Payment and Subscriptions" msgstr "" @@ -656,6 +686,9 @@ msgstr "Anterior" msgid "Privacy Policy" msgstr "Política de privacidad" +msgid "Proceed to payment" +msgstr "" + msgid "Profile and Display" msgstr "Perfil y pantalla" @@ -863,6 +896,9 @@ msgstr "Almacenado por el minero" msgid "Subscription Plan" msgstr "" +msgid "Switch Network" +msgstr "" + msgid "Switch Plan" msgstr "" @@ -950,6 +986,9 @@ msgstr "" msgid "Total" msgstr "" +msgid "Total Amount" +msgstr "" + msgid "Try again" msgstr "Intentar otra vez" diff --git a/packages/files-ui/src/locales/fr/messages.po b/packages/files-ui/src/locales/fr/messages.po index f93732c9fc..eac45074fb 100644 --- a/packages/files-ui/src/locales/fr/messages.po +++ b/packages/files-ui/src/locales/fr/messages.po @@ -5,8 +5,7 @@ msgstr "" "POT-Creation-Date: 2021-04-23 11:05+0200\n" "PO-Revision-Date: 2022-01-14 07:55+0000\n" "Last-Translator: Maxime Leroy \n" -"Language-Team: French \n" +"Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" @@ -42,6 +41,9 @@ msgstr "Un fichier avec ce nom existe déjà" msgid "Accept" msgstr "Accepter" +msgid "Accepted currencies" +msgstr "" + msgid "Access your billing history in settings or view your" msgstr "" @@ -97,8 +99,7 @@ msgid "Approve" msgstr "Accepter" msgid "Are you sure? This will delete your default payment method." -msgstr "" -"Êtes-vous sûr(e) ? Ceci va supprimer votre moyen de paiement par défaut." +msgstr "Êtes-vous sûr(e) ? Ceci va supprimer votre moyen de paiement par défaut." msgid "Backup secret phrase" msgstr "Phrase secrète de sauvegarde" @@ -139,7 +140,6 @@ msgstr "Annuler" msgid "Card added" msgstr "Carte ajoutée" -#, fuzzy msgid "Card inputs invalid" msgstr "Carte invalide" @@ -149,14 +149,12 @@ msgstr "Carte mise à jour" msgid "Change Password" msgstr "Changer le mot de passe" -#, fuzzy msgid "Change Plan" msgstr "Changer de formule" msgid "Change password" msgstr "Changer le mot de passe" -#, fuzzy msgid "Change plan" msgstr "Changer de formule" @@ -178,13 +176,15 @@ msgstr "Confirmer le mot de passe :" msgid "Confirm plan change" msgstr "Confirmer le changement de formule" -#, fuzzy msgid "Confirm plan downgrade" msgstr "Confirmer l'augmentation de la formule" msgid "Confirmation" msgstr "Confirmation" +msgid "Connect Wallet" +msgstr "" + msgid "Connect Wallet to Files" msgstr "Connecter un wallet à Files" @@ -287,6 +287,9 @@ msgstr "Supprimer" msgid "Delete selected" msgstr "Supprimer la sélection" +msgid "Destination Address" +msgstr "" + msgid "Device awaiting confirmation" msgstr "Appareil en attente de confirmation" @@ -323,6 +326,9 @@ msgstr "Les téléchargements ont échoué" msgid "Drop to upload files" msgstr "Déposer pour téléverser un fichier" +msgid "Edit payment" +msgstr "" + msgid "Edit payment method" msgstr "Modifier les méthodes de paiement" @@ -350,6 +356,9 @@ msgstr "Échec de l'ajout d'une méthode de paiement" msgid "Failed to change subscription" msgstr "Échec de changement de souscription" +msgid "Failed to create a charge" +msgstr "" + msgid "Failed to get signature" msgstr "Échec de l’obtention de la signature" @@ -464,6 +473,9 @@ msgstr "Si vous pensez que ce fichier n'est pas conforme à nos <0>Conditions de msgid "Info" msgstr "Infos" +msgid "Insufficient balance" +msgstr "" + msgid "I’m done saving my backup secret phrase" msgstr "Phrase de sauvegarde secrète enregistrée" @@ -584,6 +596,9 @@ msgstr "OK" msgid "One sec, getting files ready…" msgstr "Les fichiers sont presque prêts…" +msgid "Only send {selectedCurrency} to this address" +msgstr "" + msgid "Only you can see this." msgstr "Vous seul(e) pouvez voir ceci." @@ -626,6 +641,15 @@ msgstr "Mot de passe :" msgid "Passwords must match" msgstr "Les mots de passes de correspondent pas" +msgid "Pay with Crypto" +msgstr "" + +msgid "Pay with crypto" +msgstr "" + +msgid "Pay with {0}" +msgstr "" + msgid "Payment and Subscriptions" msgstr "Paiements et souscriptions" @@ -662,6 +686,9 @@ msgstr "Précédent" msgid "Privacy Policy" msgstr "Politique de confidentialité" +msgid "Proceed to payment" +msgstr "" + msgid "Profile and Display" msgstr "Profil et affichage" @@ -866,10 +893,12 @@ msgstr "Créer une équipe" msgid "Stored by miner" msgstr "Sauvegardé par le mineur" -#, fuzzy msgid "Subscription Plan" msgstr "Formule souscrite" +msgid "Switch Network" +msgstr "" + msgid "Switch Plan" msgstr "Changer de formule" @@ -957,6 +986,9 @@ msgstr "Ce site web utilise des cookies qui l'aident à fonctionner et à suivre msgid "Total" msgstr "Total" +msgid "Total Amount" +msgstr "" + msgid "Try again" msgstr "Essayer de nouveau" @@ -1093,22 +1125,16 @@ msgid "You would lose the following features:" msgstr "Vous perdriez ces fonctionnalités :" msgid "You've got a payment due. Until you've settled up, we've placed your account in restricted mode" -msgstr "" -"Vous avez un paiement en retard. Tant qu'il n'a pas été réglé, l'accès à " -"votre compte a été restreint" +msgstr "Vous avez un paiement en retard. Tant qu'il n'a pas été réglé, l'accès à votre compte a été restreint" msgid "Your content exceeds the {planStorageCapacity} storage capacity for this plan." -msgstr "" -"Votre contenu dépasse la capacité de stockage de {planStorageCapacity} de " -"cette formule." +msgstr "Votre contenu dépasse la capacité de stockage de {planStorageCapacity} de cette formule." msgid "Your plan" msgstr "Votre formule" msgid "Your recovery key can be used to restore your account in place of your backup secret phrase." -msgstr "" -"Votre clé de récupération vous permet de récupérer l'accès à votre compte à " -"la place de la phrase secrète." +msgstr "Votre clé de récupération vous permet de récupérer l'accès à votre compte à la place de la phrase secrète." msgid "can-edit" msgstr "peut-modifier" @@ -1135,9 +1161,7 @@ msgid "{0, plural, one {Encrypting and uploading {1} file} other {Encrypting and msgstr "{0, plural, one {Chiffrement et téléversement de {1} fichier} other {Chiffrement et téléversements {2} fichiers}}" msgid "{0, plural, one {You are about to delete {1} item.} other {You are about to delete {2} items.}}" -msgstr "" -"{0, plural, one {Vous êtes sur le point de supprimer {1} élément.} other {" -"Vous êtes sur le point de supprimer {2} éléments.}}" +msgstr "{0, plural, one {Vous êtes sur le point de supprimer {1} élément.} other {Vous êtes sur le point de supprimer {2} éléments.}}" msgid "{0} cancelled" msgstr "{0} annulé(s)" diff --git a/packages/files-ui/src/locales/no/messages.po b/packages/files-ui/src/locales/no/messages.po index c7816b0375..a31e6e0992 100644 --- a/packages/files-ui/src/locales/no/messages.po +++ b/packages/files-ui/src/locales/no/messages.po @@ -40,6 +40,9 @@ msgstr "" msgid "Accept" msgstr "" +msgid "Accepted currencies" +msgstr "" + msgid "Access your billing history in settings or view your" msgstr "" @@ -178,6 +181,9 @@ msgstr "" msgid "Confirmation" msgstr "" +msgid "Connect Wallet" +msgstr "" + msgid "Connect Wallet to Files" msgstr "" @@ -280,6 +286,9 @@ msgstr "Slett" msgid "Delete selected" msgstr "" +msgid "Destination Address" +msgstr "" + msgid "Device awaiting confirmation" msgstr "" @@ -316,6 +325,9 @@ msgstr "" msgid "Drop to upload files" msgstr "" +msgid "Edit payment" +msgstr "" + msgid "Edit payment method" msgstr "" @@ -343,6 +355,9 @@ msgstr "" msgid "Failed to change subscription" msgstr "" +msgid "Failed to create a charge" +msgstr "" + msgid "Failed to get signature" msgstr "" @@ -454,6 +469,9 @@ msgstr "" msgid "Info" msgstr "Info" +msgid "Insufficient balance" +msgstr "" + msgid "I’m done saving my backup secret phrase" msgstr "" @@ -574,6 +592,9 @@ msgstr "" msgid "One sec, getting files ready…" msgstr "" +msgid "Only send {selectedCurrency} to this address" +msgstr "" + msgid "Only you can see this." msgstr "Kun du kan se dette." @@ -616,6 +637,15 @@ msgstr "Passord:" msgid "Passwords must match" msgstr "Passordene må samsvare" +msgid "Pay with Crypto" +msgstr "" + +msgid "Pay with crypto" +msgstr "" + +msgid "Pay with {0}" +msgstr "" + msgid "Payment and Subscriptions" msgstr "" @@ -652,6 +682,9 @@ msgstr "Forrige" msgid "Privacy Policy" msgstr "Personvernspraksis" +msgid "Proceed to payment" +msgstr "" + msgid "Profile and Display" msgstr "Profil og visning" @@ -859,6 +892,9 @@ msgstr "" msgid "Subscription Plan" msgstr "" +msgid "Switch Network" +msgstr "" + msgid "Switch Plan" msgstr "" @@ -946,6 +982,9 @@ msgstr "" msgid "Total" msgstr "" +msgid "Total Amount" +msgstr "" + msgid "Try again" msgstr "Prøv igjen" diff --git a/packages/storage-ui/package.json b/packages/storage-ui/package.json index 11e8c3294c..fdcb40ec2b 100644 --- a/packages/storage-ui/package.json +++ b/packages/storage-ui/package.json @@ -6,8 +6,8 @@ "@babel/core": "^7.12.10", "@babel/runtime": "^7.0.0", "@chainsafe/browser-storage-hooks": "^1.0.1", - "@chainsafe/files-api-client": "^1.18.22", - "@chainsafe/web3-context": "1.1.4", + "@chainsafe/files-api-client": "1.18.25", + "@chainsafe/web3-context": "1.3.0", "@lingui/core": "^3.7.2", "@lingui/react": "^3.7.2", "@sentry/react": "^5.28.0", diff --git a/yarn.lock b/yarn.lock index f6085a8ef0..63961a54d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1925,19 +1925,28 @@ resolved "https://registry.yarnpkg.com/@chainsafe/browser-storage-hooks/-/browser-storage-hooks-1.0.1.tgz#26d32cde1999914db755a631e2643823c54959f7" integrity sha512-Q4b5gQAZnsRXKeADspd5isqfwwhhXjDk70y++YadufA6EZ3tf340oW0OVszp74KaGEw+CAYFGQR4X7bzpZ3x9Q== -"@chainsafe/files-api-client@^1.18.22": - version "1.18.22" - resolved "https://registry.yarnpkg.com/@chainsafe/files-api-client/-/files-api-client-1.18.22.tgz#7e66a43f5c8b4234a53745a2be8172c32a6f0b9d" - integrity sha512-m3RfBMcWKOITyH0goMl7jxg8NY//3N2cglzKS64ksrWhULKeaCARZxe5Auo8NXEfIlTkQCKmazHoozl146UR/g== +"@chainsafe/files-api-client@1.18.25": + version "1.18.25" + resolved "https://registry.yarnpkg.com/@chainsafe/files-api-client/-/files-api-client-1.18.25.tgz#e30398ad1b2033735528a97c3d129c8e734a65f1" + integrity sha512-nHARiVcspMZZ54sUs02w8baj0DXh4I1bPOyyOSGKOmy8gcHN1yxUx7XHmq21+lICU7Vv+ziddDY6bGYyHTSKuw== dependencies: "@redocly/openapi-cli" "^1.0.0-beta.58" - "@redocly/openapi-core" "^1.0.0-beta.58" + "@redocly/openapi-core" "^1.0.0-beta.69" redoc-cli "^0.12.3" -"@chainsafe/web3-context@1.1.4": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@chainsafe/web3-context/-/web3-context-1.1.4.tgz#ce0f140af8ccf93af1a189fbdbd6f018b9bf5fb7" - integrity sha512-UADJ98UGneLQzWFKRKb3nHgWnEPEyFTkVqieWQ88fwtTX2SUV2zGVQGlzmui/0L8TnvxQc40vDHXAZ/4fqoGcQ== +"@chainsafe/web3-context@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@chainsafe/web3-context/-/web3-context-1.3.0.tgz#e546f160145dce12e00845d53f1a00165f6a96b2" + integrity sha512-o3Y0m7OLIgwvXCbdnzadwYtGlW9CGLTRSGWaQllfwMrMoPorqdMuraWgRDszejk/367q5dh2KqSZjCTfHNMSOw== + dependencies: + bignumber.js "^9.0.1" + +"@chainsafe/web3-context@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@chainsafe/web3-context/-/web3-context-1.3.1.tgz#13a121a89685cec5bb458e781438aaca6ee9e85f" + integrity sha512-XF+N6guQjjEwjq+8JRJqoBKDTRpXALBES916sjxR3R0rKRhjhQ3mNnGdDilTfVikwQz3/XrZg0blb2OsirQ+KA== + dependencies: + bignumber.js "^9.0.1" "@chaitanyapotti/random-id@^1.0.3": version "1.0.3" @@ -4499,6 +4508,16 @@ require-from-string "^2.0.2" uri-js "^4.2.2" +"@redocly/ajv@^8.6.4": + version "8.6.4" + resolved "https://registry.yarnpkg.com/@redocly/ajv/-/ajv-8.6.4.tgz#94053e7a9d4146d1a4feacd3813892873f229a85" + integrity sha512-y9qNj0//tZtWB2jfXNK3BX18BSBp9zNR7KE7lMysVHwbZtY392OJCjm6Rb/h4UHH2r1AqjNEHFD6bRn+DqU9Mw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + "@redocly/openapi-cli@^1.0.0-beta.58": version "1.0.0-beta.61" resolved "https://registry.yarnpkg.com/@redocly/openapi-cli/-/openapi-cli-1.0.0-beta.61.tgz#03dfbf058b2bf85922a0e19adaa2856f111d1b14" @@ -4532,7 +4551,7 @@ node-fetch "^2.6.1" yaml-ast-parser "0.0.43" -"@redocly/openapi-core@^1.0.0-beta.58", "@redocly/openapi-core@^1.0.0-beta.61": +"@redocly/openapi-core@^1.0.0-beta.61": version "1.0.0-beta.61" resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.0.0-beta.61.tgz#d5fa05a4f625c234d5d83d65986f6d3dba68336a" integrity sha512-/OgtozUxy7SvHVBZ3Iygu6brDTOFTOlkzpDQyykpa0lK2cPBeYjkJP5foBlHKeHl+TvxfPuzh1CSGSShSc+IBg== @@ -4547,6 +4566,22 @@ node-fetch "^2.6.1" yaml-ast-parser "0.0.43" +"@redocly/openapi-core@^1.0.0-beta.69": + version "1.0.0-beta.73" + resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.0.0-beta.73.tgz#12dd8cf1490ee7ec61d712e12fc1c7ff5a1eca6f" + integrity sha512-1wmKGJp+lvhNFDEfTzjB6QlyEPNyozSiDb4sfr+R97pcGa+6YdSmgItPl5P/21Y0fBZYku9Uo1n0rhFVdr20EQ== + dependencies: + "@redocly/ajv" "^8.6.4" + "@types/node" "^14.11.8" + colorette "^1.2.0" + js-levenshtein "^1.1.6" + js-yaml "^4.1.0" + lodash.isequal "^4.5.0" + minimatch "^3.0.4" + node-fetch "^2.6.1" + pluralize "^8.0.0" + yaml-ast-parser "0.0.43" + "@redocly/react-dropdown-aria@^2.0.11": version "2.0.12" resolved "https://registry.yarnpkg.com/@redocly/react-dropdown-aria/-/react-dropdown-aria-2.0.12.tgz#2e3af2b1b8e9123487109400d6117f0d4a8445a6" @@ -7352,6 +7387,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + aria-query@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" @@ -16174,6 +16214,13 @@ js-yaml@^3.14.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -19237,6 +19284,11 @@ pkg-up@3.1.0, pkg-up@^3.1.0: dependencies: find-up "^3.0.0" +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + plurals-cldr@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/plurals-cldr/-/plurals-cldr-1.0.4.tgz#534e4784f80679d3b0b39b0fb6cc46645fcf5de8" @@ -20919,6 +20971,14 @@ react-popper@^2.2.4: react-fast-compare "^3.0.1" warning "^4.0.2" +react-qr-code@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/react-qr-code/-/react-qr-code-2.0.3.tgz#cc80785e08f817d1ab066ca4035262f77d049648" + integrity sha512-6GDH0l53lksf2JgZwwcoS0D60a1OAal/GQRyNFkMBW19HjSqvtD5S20scmSQsKl+BgWM85Wd5DCcUYoHd+PZnQ== + dependencies: + prop-types "^15.7.2" + qr.js "0.0.0" + react-qr-reader@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/react-qr-reader/-/react-qr-reader-2.2.1.tgz#dc89046d1c1a1da837a683dd970de5926817d55b"