2020-06-01 19:03:19 +02:00
|
|
|
// @flow
|
2021-05-31 05:19:13 +02:00
|
|
|
import * as ICONS from 'constants/icons';
|
2020-06-01 19:03:19 +02:00
|
|
|
import React from 'react';
|
|
|
|
import Page from 'component/page';
|
|
|
|
import Card from 'component/common/card';
|
|
|
|
import Spinner from 'component/spinner';
|
|
|
|
import hmacSHA256 from 'crypto-js/hmac-sha256';
|
|
|
|
import Base64 from 'crypto-js/enc-base64';
|
|
|
|
import { countries as countryData } from 'country-data';
|
|
|
|
import { FormField } from 'component/common/form';
|
|
|
|
import { SUPPORTED_MOONPAY_COUNTRIES } from 'constants/moonpay';
|
|
|
|
import { useHistory } from 'react-router';
|
|
|
|
import Button from 'component/button';
|
|
|
|
import Nag from 'component/common/nag';
|
2020-06-01 22:53:10 +02:00
|
|
|
import I18nMessage from 'component/i18nMessage';
|
2020-09-02 22:08:37 +02:00
|
|
|
import LbcSymbol from 'component/common/lbc-symbol';
|
2021-05-31 05:19:13 +02:00
|
|
|
import classnames from 'classnames';
|
|
|
|
import WalletSwap from 'component/walletSwap';
|
2020-06-01 19:03:19 +02:00
|
|
|
|
|
|
|
const MOONPAY_KEY = process.env.MOONPAY_SECRET_KEY;
|
|
|
|
const COUNTRIES = Array.from(
|
|
|
|
new Set(
|
|
|
|
countryData.all
|
2021-07-06 20:37:01 +02:00
|
|
|
.filter((country) => country.status !== 'deleted')
|
2021-03-24 17:58:19 +01:00
|
|
|
.map((country) => country.name)
|
2020-06-01 19:03:19 +02:00
|
|
|
.sort((a, b) => {
|
|
|
|
if (a > b) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b > a) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
})
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2021-05-31 05:19:13 +02:00
|
|
|
const TAB = {
|
|
|
|
BUY: 'BUY',
|
|
|
|
SWAP: 'SWAP',
|
|
|
|
};
|
|
|
|
|
2020-06-01 19:03:19 +02:00
|
|
|
type Props = {
|
|
|
|
receiveAddress: ?string,
|
|
|
|
gettingNewAddress: boolean,
|
|
|
|
email: string,
|
|
|
|
user: ?User,
|
|
|
|
doGetNewAddress: () => void,
|
2021-03-24 17:58:19 +01:00
|
|
|
doUserSetCountry: (string) => void,
|
2020-06-01 19:03:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
export default function BuyPage(props: Props) {
|
|
|
|
const { receiveAddress, gettingNewAddress, doGetNewAddress, email, user, doUserSetCountry } = props;
|
2020-06-01 22:53:10 +02:00
|
|
|
const initialCountry = (user && user.country) || '';
|
2021-05-31 05:19:13 +02:00
|
|
|
const [tab, setTab] = React.useState(TAB.BUY);
|
2020-06-01 19:03:19 +02:00
|
|
|
const [url, setUrl] = React.useState();
|
|
|
|
const [country, setCountry] = React.useState(initialCountry);
|
2020-06-01 22:53:10 +02:00
|
|
|
const [showPurchaseScreen, setShowPurchaseScreen] = React.useState(false);
|
2020-06-01 19:03:19 +02:00
|
|
|
const isValid = SUPPORTED_MOONPAY_COUNTRIES.includes(country);
|
|
|
|
const { goBack } = useHistory();
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
if (country) {
|
|
|
|
doUserSetCountry(country);
|
|
|
|
}
|
|
|
|
}, [country, doUserSetCountry, isValid, setShowPurchaseScreen]);
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
if (!receiveAddress && !gettingNewAddress) {
|
|
|
|
doGetNewAddress();
|
|
|
|
}
|
|
|
|
}, [doGetNewAddress, receiveAddress, gettingNewAddress]);
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
if (MOONPAY_KEY && !url && receiveAddress) {
|
2021-10-19 01:37:58 +02:00
|
|
|
let url = `https://buy.moonpay.io?apiKey=pk_live_xNFffrN5NWKy6fu0ggbV8VQIwRieRzy&colorCode=%23257761¤cyCode=lbc&showWalletAddressForm=true&walletAddress=${receiveAddress}`;
|
2021-03-24 17:58:19 +01:00
|
|
|
|
2020-06-01 19:03:19 +02:00
|
|
|
if (email) {
|
|
|
|
url += `&email=${encodeURIComponent(email)}`;
|
|
|
|
}
|
|
|
|
|
2020-12-08 17:33:00 +01:00
|
|
|
url += `&enabledPaymentMethods=${encodeURIComponent('credit_debit_card,sepa_bank_transfer,gbp_bank_transfer')}`;
|
|
|
|
|
2020-06-01 19:03:19 +02:00
|
|
|
const query = new URL(url).search;
|
|
|
|
const signature = Base64.stringify(hmacSHA256(query, MOONPAY_KEY));
|
|
|
|
|
|
|
|
setUrl(`${url}&signature=${encodeURIComponent(signature)}`);
|
|
|
|
}
|
|
|
|
}, [url, setUrl, receiveAddress, email]);
|
|
|
|
|
2020-09-04 19:14:48 +02:00
|
|
|
const title = __('Buy Credits');
|
2020-06-01 22:53:10 +02:00
|
|
|
const subtitle = (
|
|
|
|
<I18nMessage
|
|
|
|
tokens={{
|
|
|
|
learn_more: <Button button="link" label={__('Learn more')} href="https://lbry.com/faq/buy-lbc" />,
|
|
|
|
}}
|
|
|
|
>
|
2020-09-02 22:08:37 +02:00
|
|
|
LBRY, Inc. partners with Moonpay to provide the option to purchase LBRY Credits. %learn_more%.
|
2020-06-01 22:53:10 +02:00
|
|
|
</I18nMessage>
|
|
|
|
);
|
|
|
|
|
2020-06-01 19:03:19 +02:00
|
|
|
return (
|
2020-09-02 22:08:37 +02:00
|
|
|
<Page
|
|
|
|
noSideNavigation
|
2021-05-31 05:19:13 +02:00
|
|
|
className="main--swap"
|
2020-09-02 22:08:37 +02:00
|
|
|
backout={{
|
|
|
|
backoutLabel: __('Done'),
|
2021-05-31 05:19:13 +02:00
|
|
|
title: <LbcSymbol prefix={__('Buy or Swap')} size={28} />,
|
2020-09-02 22:08:37 +02:00
|
|
|
}}
|
|
|
|
>
|
2021-05-31 05:19:13 +02:00
|
|
|
<div className="section">
|
|
|
|
<Button
|
|
|
|
key="tip"
|
|
|
|
icon={ICONS.BUY}
|
|
|
|
label={__('Buy')}
|
|
|
|
button="alt"
|
|
|
|
onClick={() => setTab(TAB.BUY)}
|
|
|
|
className={classnames('button-toggle', { 'button-toggle--active': tab === TAB.BUY })}
|
|
|
|
/>
|
|
|
|
<Button
|
|
|
|
key="boost"
|
|
|
|
icon={ICONS.COIN_SWAP}
|
|
|
|
label={__('Swap')}
|
|
|
|
button="alt"
|
|
|
|
onClick={() => setTab(TAB.SWAP)}
|
|
|
|
className={classnames('button-toggle', { 'button-toggle--active': tab === TAB.SWAP })}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<div className="section">
|
|
|
|
{tab === TAB.SWAP && <WalletSwap />}
|
|
|
|
{tab === TAB.BUY && (
|
|
|
|
<>
|
|
|
|
{!user && (
|
|
|
|
<div className="main--empty">
|
|
|
|
<Spinner delayed />
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{user && (
|
|
|
|
<>
|
|
|
|
{showPurchaseScreen ? (
|
|
|
|
<Card
|
|
|
|
title={title}
|
|
|
|
subtitle={subtitle}
|
|
|
|
actions={
|
|
|
|
url ? (
|
|
|
|
<iframe
|
|
|
|
allow="accelerometer; autoplay; camera; gyroscope; payment"
|
|
|
|
frameBorder="0"
|
|
|
|
src={url}
|
|
|
|
width="100%"
|
|
|
|
>
|
|
|
|
<p>{__('Your browser does not support iframes.')}</p>
|
|
|
|
</iframe>
|
2020-06-01 19:03:19 +02:00
|
|
|
) : (
|
2021-05-31 05:19:13 +02:00
|
|
|
<div className="main--empty">
|
|
|
|
<Spinner delayed />
|
2020-06-01 19:03:19 +02:00
|
|
|
</div>
|
2021-05-31 05:19:13 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<Card
|
|
|
|
title={title}
|
|
|
|
subtitle={subtitle}
|
|
|
|
nag={
|
|
|
|
country &&
|
|
|
|
!isValid && <Nag relative type="helpful" message={"This country isn't supported yet."} />
|
|
|
|
}
|
|
|
|
actions={
|
|
|
|
<div>
|
|
|
|
<div className="section">
|
|
|
|
<FormField
|
|
|
|
label={__('Country')}
|
|
|
|
type="select"
|
|
|
|
name="country-codes"
|
|
|
|
helper={__(
|
|
|
|
'Only some countries are eligible at this time. We are working to make this available to everyone.'
|
|
|
|
)}
|
|
|
|
value={country}
|
|
|
|
onChange={(e) => setCountry(e.target.value)}
|
|
|
|
>
|
|
|
|
<option value="" disabled defaultValue>
|
|
|
|
{__('Select your country')}
|
|
|
|
</option>
|
|
|
|
{COUNTRIES.map((country, index) => (
|
|
|
|
<option key={country} value={country}>
|
|
|
|
{country}
|
|
|
|
</option>
|
|
|
|
))}
|
|
|
|
</FormField>
|
|
|
|
</div>
|
|
|
|
{country && (
|
|
|
|
<div className="section">
|
|
|
|
{isValid ? (
|
|
|
|
<div className="section__actions">
|
|
|
|
<Button
|
|
|
|
button="primary"
|
|
|
|
label={__('Continue')}
|
|
|
|
onClick={() => setShowPurchaseScreen(true)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
) : (
|
|
|
|
<div className="section__actions">
|
|
|
|
<Button button="alt" label={__('Go Back')} onClick={() => goBack()} />
|
|
|
|
<Button
|
|
|
|
button="link"
|
|
|
|
label={__('Try Anyway')}
|
|
|
|
onClick={() => setShowPurchaseScreen(true)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</div>
|
2020-06-01 19:03:19 +02:00
|
|
|
</Page>
|
|
|
|
);
|
|
|
|
}
|