-
-
-
-
-
-
- {' '}
- {__('earned and bound in tips')}
-
-
-
-
-
-
-
-
-
+
-
+
{' '}
- {__('currently staked')}
+ {__('earned and bound in tips')}
-
-
- - {__('... in your publishes')}
- -
-
-
+
+
-
{__('... in your supports')}
-
-
-
-
+
+
+
+
+
+
+
+ {' '}
+ {__('currently staked')}
+
+
+
+ - {__('... in your publishes')}
+ -
+
+
+
+ - {__('... in your supports')}
+ -
+
+
+
+
-
+
diff --git a/ui/constants/icons.js b/ui/constants/icons.js
index a78aaa815..0d771770c 100644
--- a/ui/constants/icons.js
+++ b/ui/constants/icons.js
@@ -60,7 +60,6 @@ export const MENU = 'Menu';
export const BACKUP = 'Database';
export const TRANSACTIONS = 'FileText';
export const LBRY = 'Lbry';
-export const SEND = 'Send';
export const DISCOVER = 'Compass';
export const VISUALIZER_ON = 'Eye';
export const VISUALIZER_OFF = 'EyeOff';
@@ -102,3 +101,6 @@ export const ANALYTICS = 'BarChart2';
export const PURCHASED = 'Key';
export const CIRCLE = 'Circle';
export const PINNED = 'Pinned';
+export const BUY = 'Buy';
+export const SEND = 'Send';
+export const RECEIVE = 'Receive';
diff --git a/ui/constants/moonpay.js b/ui/constants/moonpay.js
new file mode 100644
index 000000000..45f9e6cb9
--- /dev/null
+++ b/ui/constants/moonpay.js
@@ -0,0 +1,62 @@
+export const SUPPORTED_MOONPAY_COUNTRIES = [
+ 'Argentina',
+ 'Australia',
+ 'Austria',
+ 'Belgium',
+ 'Brazil',
+ 'Bulgaria',
+ 'Canada',
+ 'Chile',
+ 'Colombia',
+ 'Croatia',
+ 'Cyprus',
+ 'Czech Republic',
+ 'Denmark',
+ 'Estonia',
+ 'Finland',
+ 'France',
+ 'Germany',
+ 'Greece',
+ 'Hong Kong',
+ 'Hungary',
+ 'Iceland',
+ 'India',
+ 'Indonesia',
+ 'Ireland',
+ 'Israel',
+ 'Italy',
+ 'Japan',
+ 'Kuwait',
+ 'Latvia',
+ 'Liechtenstein',
+ 'Lithuania',
+ 'Luxembourg',
+ 'Malaysia',
+ 'Malta',
+ 'Mauritius',
+ 'Mexico',
+ 'Netherlands',
+ 'New Zealand',
+ 'Norway',
+ 'Philippines',
+ 'Poland',
+ 'Portugal',
+ 'Qatar',
+ 'Romania',
+ 'Russia',
+ 'Saudi Arabia',
+ 'Singapore',
+ 'Slovakia',
+ 'Slovenia',
+ 'South Africa',
+ 'South Korea',
+ 'Spain',
+ 'Sweden',
+ 'Switzerland',
+ 'Taiwan',
+ 'Thailand',
+ 'Turkey',
+ 'United Arab Emirates',
+ 'United Kingdom',
+ 'Viet Nam',
+];
diff --git a/ui/constants/pages.js b/ui/constants/pages.js
index e8b3a8ec5..9f53a7b43 100644
--- a/ui/constants/pages.js
+++ b/ui/constants/pages.js
@@ -37,3 +37,4 @@ exports.WELCOME = 'welcome';
exports.CREATOR_DASHBOARD = 'dashboard';
exports.CHECKOUT = 'checkout';
exports.CODE_2257 = '2257';
+exports.BUY = 'buy';
diff --git a/ui/modal/modalRouter/view.jsx b/ui/modal/modalRouter/view.jsx
index 70202e8ea..58c595ed1 100644
--- a/ui/modal/modalRouter/view.jsx
+++ b/ui/modal/modalRouter/view.jsx
@@ -37,7 +37,7 @@ import ModalMobileNavigation from 'modal/modalMobileNavigation';
import ModalSetReferrer from 'modal/modalSetReferrer';
import ModalRepost from 'modal/modalRepost';
import ModalSignOut from 'modal/modalSignOut';
-import ModalLiquidateSupports from 'modal/modalSupportsLiquidate';
+import ModalSupportsLiquidate from 'modal/modalSupportsLiquidate';
import ModalConfirmAge from 'modal/modalConfirmAge';
import ModalFileSelection from 'modal/modalFileSelection';
@@ -137,12 +137,12 @@ function ModalRouter(props: Props) {
return
;
case MODALS.SIGN_OUT:
return
;
- case MODALS.LIQUIDATE_SUPPORTS:
- return
;
case MODALS.CONFIRM_AGE:
return
;
case MODALS.FILE_SELECTION:
return
;
+ case MODALS.LIQUIDATE_SUPPORTS:
+ return
;
default:
return null;
}
diff --git a/ui/page/buy/index.js b/ui/page/buy/index.js
new file mode 100644
index 000000000..b1770fb4c
--- /dev/null
+++ b/ui/page/buy/index.js
@@ -0,0 +1,16 @@
+import { connect } from 'react-redux';
+import { selectGettingNewAddress, selectReceiveAddress, doGetNewAddress } from 'lbry-redux';
+import { selectUserEmail, selectUser, doUserSetCountry } from 'lbryinc';
+import BuyPage from './view';
+
+const select = state => ({
+ receiveAddress: selectReceiveAddress(state),
+ gettingNewAddress: selectGettingNewAddress(state),
+ email: selectUserEmail(state),
+ user: selectUser(state),
+});
+
+export default connect(select, {
+ doGetNewAddress,
+ doUserSetCountry,
+})(BuyPage);
diff --git a/ui/page/buy/view.jsx b/ui/page/buy/view.jsx
new file mode 100644
index 000000000..38ee47e17
--- /dev/null
+++ b/ui/page/buy/view.jsx
@@ -0,0 +1,161 @@
+// @flow
+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';
+
+const MOONPAY_KEY = process.env.MOONPAY_SECRET_KEY;
+const COUNTRIES = Array.from(
+ new Set(
+ countryData.all
+ .map(country => country.name)
+ .sort((a, b) => {
+ if (a > b) {
+ return 1;
+ }
+
+ if (b > a) {
+ return -1;
+ }
+
+ return 0;
+ })
+ )
+);
+
+type Props = {
+ receiveAddress: ?string,
+ gettingNewAddress: boolean,
+ email: string,
+ user: ?User,
+ doGetNewAddress: () => void,
+ doUserSetCountry: string => void,
+};
+
+export default function BuyPage(props: Props) {
+ const { receiveAddress, gettingNewAddress, doGetNewAddress, email, user, doUserSetCountry } = props;
+ const initialCountry = user && user.country;
+ const [url, setUrl] = React.useState();
+ const [country, setCountry] = React.useState(initialCountry);
+ const [ShowPurchaseScreen, setShowPurchaseScreen] = React.useState(false);
+ const isValid = SUPPORTED_MOONPAY_COUNTRIES.includes(country);
+ const { goBack } = useHistory();
+
+ React.useEffect(() => {
+ if (country) {
+ doUserSetCountry(country);
+ }
+
+ // uncomment to auto show the purchase screen based on their chosen country
+ // if (isValid) {
+ // setShowPurchaseScreen(true);
+ // }
+ }, [country, doUserSetCountry, isValid, setShowPurchaseScreen]);
+
+ React.useEffect(() => {
+ if (!receiveAddress && !gettingNewAddress) {
+ doGetNewAddress();
+ }
+ }, [doGetNewAddress, receiveAddress, gettingNewAddress]);
+
+ React.useEffect(() => {
+ if (MOONPAY_KEY && !url && receiveAddress) {
+ let url = `https://buy.moonpay.io?apiKey=pk_live_xNFffrN5NWKy6fu0ggbV8VQIwRieRzy&colorCode=%23257761¤cyCode=lbc&showWalletAddressForm=true&walletAddress=${receiveAddress}`;
+ if (email) {
+ url += `&email=${encodeURIComponent(email)}`;
+ }
+
+ const query = new URL(url).search;
+ const signature = Base64.stringify(hmacSHA256(query, MOONPAY_KEY));
+
+ setUrl(`${url}&signature=${encodeURIComponent(signature)}`);
+ }
+ }, [url, setUrl, receiveAddress, email]);
+
+ return (
+
+ {!user && (
+
+
+
+ )}
+
+ {user && (
+ <>
+ {ShowPurchaseScreen ? (
+
+ {__('Your browser does not support iframes.')}
+
+ ) : (
+
+
+
+ )
+ }
+ />
+ ) : (
+ }
+ actions={
+
+
+ setCountry(e.target.value)}
+ >
+
+ {COUNTRIES.map((country, index) => (
+
+ ))}
+
+
+ {country && (
+
+ {isValid ? (
+
+
+ ) : (
+
+
+ )}
+
+ )}
+
+ }
+ />
+ )}
+ >
+ )}
+
+ );
+}
diff --git a/ui/page/rewards/view.jsx b/ui/page/rewards/view.jsx
index f71f52152..3d97f837f 100644
--- a/ui/page/rewards/view.jsx
+++ b/ui/page/rewards/view.jsx
@@ -40,11 +40,16 @@ class RewardsPage extends PureComponent
{
if (user && !user.is_reward_approved && rewardsEnabled) {
if (!user.primary_email || !user.has_verified_email || !user.is_identity_verified) {
- return ;
+ return (
+
+
+
+ );
}
return (
@@ -156,7 +161,7 @@ class RewardsPage extends PureComponent {
return (
{this.renderPageHeader()}
- {this.renderUnclaimedRewards()}
+ {this.renderUnclaimedRewards()}
{}
);
diff --git a/ui/page/wallet/index.js b/ui/page/wallet/index.js
index 6d797c4ab..a5897410d 100644
--- a/ui/page/wallet/index.js
+++ b/ui/page/wallet/index.js
@@ -1,11 +1,12 @@
import { connect } from 'react-redux';
+import { selectBalance } from 'lbry-redux';
+import { doOpenModal } from 'redux/actions/app';
import Wallet from './view';
-const select = state => ({});
+const select = state => ({
+ balance: selectBalance(state),
+});
-const perform = dispatch => ({});
-
-export default connect(
- select,
- perform
-)(Wallet);
+export default connect(select, {
+ doOpenModal,
+})(Wallet);
diff --git a/ui/page/wallet/view.jsx b/ui/page/wallet/view.jsx
index 998062e90..0548be781 100644
--- a/ui/page/wallet/view.jsx
+++ b/ui/page/wallet/view.jsx
@@ -1,23 +1,69 @@
// @flow
+import * as ICONS from 'constants/icons';
+import * as PAGES from 'constants/pages';
+import * as MODALS from 'constants/modal_types';
import React from 'react';
import { withRouter } from 'react-router';
import WalletBalance from 'component/walletBalance';
import TxoList from 'component/txoList';
import Page from 'component/page';
+import Yrbl from 'component/yrbl';
+import Button from 'component/button';
+import Spinner from 'component/spinner';
type Props = {
history: { action: string, push: string => void, replace: string => void },
location: { search: string, pathname: string },
+ balance: number,
+ doOpenModal: string => void,
};
const WalletPage = (props: Props) => {
- const { location } = props;
+ const { location, balance, doOpenModal } = props;
const { search } = location;
+ const showIntro = balance === 0;
+ const loading = balance === undefined;
return (
-
-
+ {loading && (
+
+
+
+ )}
+ {!loading && (
+ <>
+ {showIntro ? (
+
+
+
+ There are a lot of ways to get LBC! You can have your friend send you a few, earn rewards, or
+ purchase your own.
+
+
+
+ doOpenModal(MODALS.WALLET_RECEIVE)}
+ />
+
+
+
+ }
+ />
+
+ ) : (
+ <>
+