From 0280c36a3bf807c9d15b9fd46ab1731e679515f3 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Fri, 20 Oct 2023 15:53:12 +0100 Subject: [PATCH 1/7] initiate onbaord --- src/common/components/wallet-ecency/index.tsx | 12 +- src/common/components/wallet-menu/index.tsx | 13 +- src/common/pages/sign-up.tsx | 428 +++++++++--------- 3 files changed, 218 insertions(+), 235 deletions(-) diff --git a/src/common/components/wallet-ecency/index.tsx b/src/common/components/wallet-ecency/index.tsx index 5cb740d8f82..cd7ead7be94 100644 --- a/src/common/components/wallet-ecency/index.tsx +++ b/src/common/components/wallet-ecency/index.tsx @@ -201,9 +201,9 @@ export const WalletEcency = (props: Props) => { useEffect(() => { setIsMounted(true); - if (!global.usePrivate) { - history.push("/"); - } + // if (!global.usePrivate) { + // history.push("/"); + // } let user = history.location.pathname.split("/")[1]; user = user.replace('@','') global.isElectron && initiateOnElectron(user); @@ -276,9 +276,9 @@ export const WalletEcency = (props: Props) => { fetchPoints(account.name, filter); } - if (!global.usePrivate) { - return null; - } + // if (!global.usePrivate) { + // return null; + // } const isMyPage = activeUser && activeUser.username === account.name; diff --git a/src/common/components/wallet-menu/index.tsx b/src/common/components/wallet-menu/index.tsx index 6908b13cc7b..51683fb7cbd 100644 --- a/src/common/components/wallet-menu/index.tsx +++ b/src/common/components/wallet-menu/index.tsx @@ -22,14 +22,13 @@ export default class WalletMenu extends Component { const logo = global.isElectron ? "./img/logo-small-transparent.png" : require('../../img/logo-small-transparent.png'); return ( + //REMOVE USE PRIVATE FOR POINTS
- {global.usePrivate && ( - - Ecency - Points - ecency - - )} + + Community + Points + ecency + Hive Wallet diff --git a/src/common/pages/sign-up.tsx b/src/common/pages/sign-up.tsx index eef551b3eaa..74a6827e604 100644 --- a/src/common/pages/sign-up.tsx +++ b/src/common/pages/sign-up.tsx @@ -1,15 +1,11 @@ -import React, { Component } from "react"; - +import React, { useState, useRef, useEffect } from "react"; import { connect } from "react-redux"; - -import { Button, Form, FormControl, Spinner, Row, Col } from "react-bootstrap"; - +import { Button, Form, FormControl, Spinner } from "react-bootstrap"; import { PageProps, pageMapDispatchToProps, pageMapStateToProps, } from "./common"; - import Meta from "../components/meta"; import Theme from "../components/theme/index"; import NavBar from "../components/navbar/index"; @@ -17,250 +13,238 @@ import NavBarElectron from "../../desktop/app/components/navbar"; import Feedback, { error } from "../components/feedback"; import ScrollToTop from "../components/scroll-to-top"; import defaults from "../constants/defaults.json"; - import { getAvailibleAccounts, signUp } from "../api/private-api"; - import { _t } from "../i18n"; - import { hiveSvg } from "../img/svg"; import { handleInvalid, handleOnInput } from "../util/input-util"; import { Community } from "../store/communities/types"; import { windowExists } from "../../server/util"; +import { Global } from "../store/global/types"; -interface State { - username: string; - lockReferral: boolean; - inProgress: boolean; - done: boolean; - availibleAccounts: number; - signUpResponse: any; - communities: Community[]; +interface Props { + global: Global + communities: Community[] } -class SignUpPage extends Component { - form = React.createRef(); +const SignUpPage = (props: Props | any) => { + const form = useRef(null); + const { global, communities } = props; - state: State = { - username: "", - lockReferral: false, - inProgress: false, - done: false, - communities: [], - availibleAccounts: 0, - signUpResponse: null, - }; + const [username, setUsername] = useState("") + const [email, setEmail] = useState("") + const [lockReferral, setLockReferral] = useState(false) + const [inProgress, setInProgress] = useState(false) + const [community, setCommunity] = useState(null); + const [newUserData, setNewUserData]: any = useState(null); + const [step, setStep] = useState(1) - componentDidMount() { - const { global } = this.props; - getAvailibleAccounts(global.baseApiUrl) - .then((response) => { - this.setState({ ...this.state, availibleAccounts: response.count }); - if (!response.count) { - if (windowExists) { - window.location.replace("https://signup.hive.io/"); - } - } - }) - .catch((e) => { - if (windowExists) { - window.location.replace("https://signup.hive.io/"); - } - }); - } + useEffect(()=> { + console.log(props) + getCurrentCommunity() + }, []) - usernameChanged = ( - e: React.ChangeEvent - ) => { + + const usernameChanged = (e: { target: { value: any; }; }) => { const { value: username } = e.target; - this.setState({ username: username.toLowerCase() }); + setUsername(username.toLowerCase()); + }; + const emailChanged = (e: { target: { value: any; }; }) => { + const { value: email } = e.target; + setEmail(email.toLowerCase()); }; - submit = () => { - const { username } = this.state; - const { global } = this.props; - this.setState({ ...this.state, inProgress: true }); - signUp(username, global.baseApiUrl) - .then(({ data }) => { - if (!data.success) { - error(data.message); - return; - } - - this.setState({ inProgress: false, signUpResponse: data }); - }) - .catch((e) => { - console.error(e); - this.setState({ inProgress: false }); - error("Couldn't create account"); - }); + // const submit = () => { + // const { global } = props; + // setInProgress(true); + // signUp(username, global.baseApiUrl) + // .then(({ data }) => { + // if (!data.success) { + // error(data.message); + // return; + // } + // setInProgress(false); + // setSignUpResponse(data) + // }) + // .catch((e) => { + // console.error(e); + // setInProgress(false); + // }); + // }; + + const createAccount = async () => { + setStep(2) }; - render() { - const { global, communities } = this.props; + const getCurrentCommunity = () => { const currCommunity = communities.find( - (community) => community.name === global.hive_id + (community: { name: any; }) => community.name === global.hive_id ); + setCommunity(currCommunity) + } - // Meta config - const metaProps = { - title: `Welcome to ${currCommunity?.title}`, - }; - - const { username, inProgress, done, availibleAccounts, signUpResponse } = - this.state; - const spinner = ( - - ); - let containerClasses = global.isElectron - ? "app-content sign-up-page mb-lg-0 mt-0 pt-6" - : "app-content sign-up-page mb-lg-0"; + // Meta config + const metaProps = { + title: `Welcome to ${community?.title}`, + }; - return ( - <> - - - - - {global.isElectron - ? NavBarElectron({ - ...this.props, - }) - : NavBar({ ...this.props })} -
- {signUpResponse && ( -
-

- Username: {signUpResponse.result.username} -

-
    -
  • - Owner: {signUpResponse.result.keys.owner} -
  • -
  • - Owner (public):{" "} - {signUpResponse.result.keys.ownerPubkey} -
  • -
  • - Active: {signUpResponse.result.keys.active} -
  • -
  • - Active (public):{" "} - {signUpResponse.result.keys.activePubkey} -
  • -
  • - Posting: {signUpResponse.result.keys.posting} -
  • -
  • - Posting (public):{" "} - {signUpResponse.result.keys.postingPubkey} -
  • -
  • - Memo: {signUpResponse.result.keys.memo} -
  • -
  • - Memo (public): {signUpResponse.result.keys.memoPubkey} -
  • -
-
- - This info is important to setting up your "HIVE Keychain" - client, copy this info somewhere safe - -
+ const spinner = ( + + ); + let containerClasses = global.isElectron + ? "app-content sign-up-page mb-lg-0 mt-0 pt-6" + : "app-content sign-up-page mb-lg-0"; + + return ( + <> + + + + + {global.isElectron + ? NavBarElectron({ + ...props, + }) + : NavBar({ ...props })} +
+ {step == 1 &&
+
+
Welcome to {community?.title}
+
{_t("sign-up.description")}
+
+ Ecency + {hiveSvg}
- )} -
-
-
- Welcome to {currCommunity?.title} -
-
{_t("sign-up.description")}
-
- Ecency - {hiveSvg} -
- {(() => { - // A test helper to simulate a successful form response. - // const done = true; - // const email = "loremipsum@gmail.com"; - - return ( -
-
{ - e.preventDefault(); - e.stopPropagation(); - - if (!this.form.current?.checkValidity()) { - return; + {(() => { + return ( +
+ { + e.preventDefault(); + e.stopPropagation(); + + // if (!form.current?.checkValidity()) { + // return; + // } + + createAccount(); + }} + > + + + handleInvalid(e, "sign-up.", "validation-username") } - - this.submit(); - }} - > - - - handleInvalid(e, "sign-up.", "validation-username") - } - onInput={handleOnInput} - /> - -
- -
- - - + + {/*
+ There are {availibleAccounts} free accounts left! +
*/} +
+ ); + })()}
-
- - ); - } +
} + {newUserData && step == 2 && ( +
+

+ Username: {newUserData.result.username} +

+
    +
  • + Owner: {newUserData.result.keys.owner} +
  • +
  • + Owner (public): {newUserData.result.keys.ownerPubkey} +
  • +
  • + Active: {newUserData.result.keys.active} +
  • +
  • + Active (public): {newUserData.result.keys.activePubkey} +
  • +
  • + Posting: {newUserData.result.keys.posting} +
  • +
  • + Posting (public): {newUserData.result.keys.postingPubkey} +
  • +
  • + Memo: {newUserData.result.keys.memo} +
  • +
  • + Memo (public): {newUserData.result.keys.memoPubkey} +
  • +
+
+ + This info is important for setting up your "HIVE Keychain" client, + copy this info somewhere safe + +
+
+ )} +
+ + ); } export default connect(pageMapStateToProps, pageMapDispatchToProps)(SignUpPage); From 14117d2db24abbce8437662d813264caee516ba2 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Sun, 22 Oct 2023 05:59:37 +0100 Subject: [PATCH 2/7] generate account keys --- src/common/api/operations.ts | 70 +++++++++++++++++- src/common/helper/onboard.ts | 49 +++++++++++++ src/common/img/svg.tsx | 14 ++++ src/common/pages/_sign-up.scss | 56 ++++++++++++--- src/common/pages/sign-up.tsx | 128 +++++++++++++++++---------------- 5 files changed, 246 insertions(+), 71 deletions(-) create mode 100644 src/common/helper/onboard.ts diff --git a/src/common/api/operations.ts b/src/common/api/operations.ts index b7688d0bc5a..668d4a5a273 100644 --- a/src/common/api/operations.ts +++ b/src/common/api/operations.ts @@ -20,6 +20,7 @@ import {hotSign} from "../helper/hive-signer"; import {_t} from "../i18n"; import { TransactionType } from "../components/buy-sell-hive"; +import { KeyTypes } from "../helper/onboard"; export interface MetaData { links?: string[]; @@ -1088,4 +1089,71 @@ export const hiveNotifySetLastRead = (username: string): Promise => hiveClient.broadcast.updateAccount(update, ownerKey) +export const updatePassword = ( + update: AccountUpdateOperation[1], + ownerKey: PrivateKey + ): Promise => +hiveClient.broadcast.updateAccount(update, ownerKey); + +export const createHiveAccount = async (username: string, newUser: string, keys: KeyTypes) => { + return new Promise(async (resolve, reject) => { + const op_name = "account_create"; + const memoKey = keys.memo + const activeKey = keys.active + const postingKey = keys.posting + + const owner = { + weight_threshold: 1, + account_auths: [], + key_auths: [[keys.ownerPubkey, 1]] + }; + const active = { + weight_threshold: 1, + account_auths: [], + key_auths: [[keys.activePubkey, 1]] + }; + const posting = { + weight_threshold: 1, + account_auths: [["ecency.app", 1]], + key_auths: [[keys.postingPubkey, 1]] + }; + + const ops = []; + const params = { + creator: username, + new_account_name: newUser, + owner, + active, + posting, + memo_key: keys.memoPubkey, + json_metadata: "", + extensions: [], + fee: "3.000 HIVE" + }; + + const operation = [op_name, params]; + ops.push(operation); + + try { + const response = await keychain.broadcast(username, [operation], "Active"); + if (response) { + resolve(response); + } else { + reject("Account creation failed"); + } + } catch (err) { + console.log(err); + reject(err); + } + + try { + await keychain.addAccount(newUser, { + active: activeKey, + posting: postingKey, + memo: memoKey + }) + } catch (error) { + console.log(error) + } + }); + }; diff --git a/src/common/helper/onboard.ts b/src/common/helper/onboard.ts new file mode 100644 index 00000000000..633bac0cd1a --- /dev/null +++ b/src/common/helper/onboard.ts @@ -0,0 +1,49 @@ +import { KeyRole, PrivateKey } from "@hiveio/dhive"; +const { randomBytes } = require("crypto"); + +export interface KeyTypes { + active?: string; + activePubkey: string; + memo?: string; + memoPubkey: string; + owner?: string; + ownerPubkey: string; + posting?: string; + postingPubkey: string; + } + +export const getPrivateKeys = (username: any, password: any) => { + const roles: Array = ["owner", "active", "posting", "memo"]; + type keysType = { + owner: string; + active: string; + posting: string; + memo: string; + ownerPubkey: string; + activePubkey: string; + postingPubkey: string; + memoPubkey: string; + }; + + let privKeys: keysType = { + owner: "", + active: "", + posting: "", + memo: "", + ownerPubkey: "", + activePubkey: "", + postingPubkey: "", + memoPubkey: "" + }; + roles.forEach((role) => { + privKeys[role] = PrivateKey.fromLogin(username, password, role).toString(); + privKeys[`${role}Pubkey`] = PrivateKey.from(privKeys[role]).createPublic().toString(); + }); + + return privKeys; +}; + +export const generatePassword = async (length: number) => { + const password = `P${PrivateKey.fromSeed(randomBytes(length).toString("hex")).toString()}`; + return password; +}; diff --git a/src/common/img/svg.tsx b/src/common/img/svg.tsx index c7b19f45931..f8025ca84a0 100644 --- a/src/common/img/svg.tsx +++ b/src/common/img/svg.tsx @@ -1419,3 +1419,17 @@ export const listView = ( ); + +export const downloadSvg = ( + + + + +); diff --git a/src/common/pages/_sign-up.scss b/src/common/pages/_sign-up.scss index bfe544580df..325febadfc6 100644 --- a/src/common/pages/_sign-up.scss +++ b/src/common/pages/_sign-up.scss @@ -1,5 +1,7 @@ .sign-up-page { display: flex; + justify-content: center; + align-items: center; @media (max-width: $md-break) { flex-direction: column; @@ -7,22 +9,59 @@ } .success-info { - width: 50%; - background-color: $white-three; + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + width: max-content; + background-color: $dark-three; padding: 2rem; border-radius: 1rem; color: $steel-grey; word-break: break-all; - ul { - padding-left: 0.125rem; - list-style: none; - li { - padding: 0 0.25rem; - font-size: 1rem; + .account-details{ + display: flex; + justify-content: center; + flex-direction: column; + gap: 5px; + } + + .account-password{ + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + + .password{ + display: flex; + align-items: center; + gap: 3px; + + .icon{ + cursor: pointer; + } } } + .account-link{ + display: flex; + flex-direction: column; + align-items: center; + + .link{ + display: flex; + align-items: center; + gap: 3px; + + .icon{ + cursor: pointer; + } + } + } + + } + @media (max-width: $md-break) { margin-bottom: 2rem; } @@ -161,6 +200,5 @@ line-height: 22px; } } - } } } diff --git a/src/common/pages/sign-up.tsx b/src/common/pages/sign-up.tsx index 74a6827e604..ffdfdc4e289 100644 --- a/src/common/pages/sign-up.tsx +++ b/src/common/pages/sign-up.tsx @@ -20,6 +20,10 @@ import { handleInvalid, handleOnInput } from "../util/input-util"; import { Community } from "../store/communities/types"; import { windowExists } from "../../server/util"; import { Global } from "../store/global/types"; +import { createHiveAccount } from "../api/operations"; +import { generatePassword, getPrivateKeys } from "../helper/onboard"; +import { KeyTypes } from "../helper/onboard"; +import { downloadSvg, copyContent } from "../img/svg"; interface Props { global: Global @@ -35,14 +39,35 @@ const SignUpPage = (props: Props | any) => { const [lockReferral, setLockReferral] = useState(false) const [inProgress, setInProgress] = useState(false) const [community, setCommunity] = useState(null); - const [newUserData, setNewUserData]: any = useState(null); - const [step, setStep] = useState(1) + const [newUserKeys, setNewUserKeys]: any = useState(null); + const [accountPassword, setAccountPassword] = useState("") + const [step, setStep] = useState(1); + const [error, setError] = useState(""); useEffect(()=> { console.log(props) getCurrentCommunity() }, []) + useEffect(()=> { + initiateAccount() + }, [step]) + + const initiateAccount = async () => { + if(!username || !email) { + return; + } + + const password: Promise = generatePassword(32); + const keys: KeyTypes = getPrivateKeys(username, password); + setNewUserKeys((prev: any) => ({ ...prev, ...keys })); + setAccountPassword(await password) + console.log(newUserKeys) + console.log("keys", keys) + + // setStep(2) + + } const usernameChanged = (e: { target: { value: any; }; }) => { const { value: username } = e.target; @@ -53,26 +78,8 @@ const SignUpPage = (props: Props | any) => { setEmail(email.toLowerCase()); }; - // const submit = () => { - // const { global } = props; - // setInProgress(true); - // signUp(username, global.baseApiUrl) - // .then(({ data }) => { - // if (!data.success) { - // error(data.message); - // return; - // } - // setInProgress(false); - // setSignUpResponse(data) - // }) - // .catch((e) => { - // console.error(e); - // setInProgress(false); - // }); - // }; - const createAccount = async () => { - setStep(2) + }; const getCurrentCommunity = () => { @@ -113,7 +120,7 @@ const SignUpPage = (props: Props | any) => {
{step == 1 &&
-
Welcome to {community?.title}
+
Create a Hive acoount
{_t("sign-up.description")}
{ // return; // } - createAccount(); + setStep(2); }} > @@ -194,52 +201,51 @@ const SignUpPage = (props: Props | any) => { {_t("sign-up.login-text-2")}
- - {/*
- There are {availibleAccounts} free accounts left! -
*/}
); })()}
} - {newUserData && step == 2 && ( + {newUserKeys && step == 2 && (

- Username: {newUserData.result.username} + Confirm Account Information

-
    -
  • - Owner: {newUserData.result.keys.owner} -
  • -
  • - Owner (public): {newUserData.result.keys.ownerPubkey} -
  • -
  • - Active: {newUserData.result.keys.active} -
  • -
  • - Active (public): {newUserData.result.keys.activePubkey} -
  • -
  • - Posting: {newUserData.result.keys.posting} -
  • -
  • - Posting (public): {newUserData.result.keys.postingPubkey} -
  • -
  • - Memo: {newUserData.result.keys.memo} -
  • -
  • - Memo (public): {newUserData.result.keys.memoPubkey} -
  • -
-
- - This info is important for setting up your "HIVE Keychain" client, - copy this info somewhere safe - -
+
+ + Username: {username} + + + Email: {email} + + + Active Public key: {newUserKeys?.activePubkey} + + + Owner Public key: {newUserKeys?.ownerPubkey} + + + Posting Public Key: {newUserKeys?.postingPubkey} + + + Memo Public Key: {newUserKeys?.memoPubkey} + +
+
+ Make sure you copy and save ypur acc password securely +
+ {accountPassword} + {copyContent} +
+
+ +
+

Copy Link below and SEND to a friend

+
+ https://test.com/create-account + {copyContent} +
+
)}
From ee160d40ef0ee6c8eb45902ea05538da3e6f5fe1 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Mon, 23 Oct 2023 12:40:06 +0100 Subject: [PATCH 3/7] key downloads and onboard url --- package.json | 1 + src/common/app.tsx | 7 ++ .../components/onboard-friend/index.scss | 19 +++ .../components/onboard-friend/index.tsx | 110 ++++++++++++++++++ src/common/i18n/locales/en-US.json | 58 +++++++++ src/common/pages/_sign-up.scss | 3 +- src/common/pages/sign-up.tsx | 96 ++++++++++++--- src/common/routes.ts | 1 + src/common/util/b64.ts | 18 ++- src/style/_components.scss | 1 + yarn.lock | 2 +- 11 files changed, 295 insertions(+), 21 deletions(-) create mode 100644 src/common/components/onboard-friend/index.scss create mode 100644 src/common/components/onboard-friend/index.tsx diff --git a/package.json b/package.json index 7f8e3db815e..040cad93c99 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "i18next": "^19.4.4", "i18next-browser-languagedetector": "^4.2.0", "immutability-helper": "^3.0.2", + "js-base64": "^3.7.5", "js-cookie": "^2.2.1", "medium-zoom": "^1.0.6", "moment": "^2.26.0", diff --git a/src/common/app.tsx b/src/common/app.tsx index 3417b4fd210..45c78677c93 100644 --- a/src/common/app.tsx +++ b/src/common/app.tsx @@ -12,6 +12,7 @@ import AuthContainer from "./pages/auth"; import SubmitContainer from "./pages/submit"; import MarketPage from "./pages/market"; import SignUpContainer from "./pages/sign-up"; +import OnboardFriend from "./components/onboard-friend"; import NotFound from "./components/404"; import Tracker from "./tracker"; @@ -133,6 +134,12 @@ const App = ({ setLang }: any) => { path={routes.SIGN_UP} component={SignUpContainer} /> + { + const form = useRef(null); + const { global, communities } = props; + + const [username, setUsername] = useState("") + const [urlInfo, seturlInfo] = useState(null) + const [community, setCommunity] = useState(null); + const [step, setStep] = useState(1); + const [error, setError] = useState(""); + + useEffect(() => { + let decodedObj; + try { + console.log(props.match.params.hash); + if (props.match.params.hash) { + const decodedHash = decodeURIComponent(props.match.params.hash); + decodedObj = JSON.parse(decodedHash); + } + } catch (error) { + console.log(error); + } + seturlInfo(decodedObj); + console.log(decodedObj); // Log the decoded object here + }, []); + + + // Meta config + const metaProps = { + title: `Welcome to ${community?.title}`, + }; + + const spinner = ( + + ); + let containerClasses = global.isElectron + ? "app-content sign-up-page mb-lg-0 mt-0 pt-6" + : "app-content sign-up-page mb-lg-0"; + + return ( + <> + + + + + {global.isElectron + ? NavBarElectron({ + ...props, + }) + : NavBar({ ...props })} +
+
+
You are creating an account for a friend
+
+ {urlInfo && ( +
+ Username: {urlInfo.username} + Public posting: {urlInfo.keys.postingpubkey} + Public Owner: {urlInfo.keys.ownerpubkey} + Public active: {urlInfo.keys.activepubkey} + Memo active: {urlInfo.keys.memopubkey} +
+ )} +
+
+ +
+
+
+ + ); +} + +export default connect(pageMapStateToProps, pageMapDispatchToProps)(OnboardFriend); diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index ca9834fbe48..4e93f3a30cc 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -173,6 +173,64 @@ "login-text-1": "Do you have an account?", "login-text-2": "Login" }, + "onboard": { + "description-active-user": "You can create account for a friend.", + "description-visitor": "You can ask a friend to create an account for you.", + "creating-description": "Pay with hive or account credit", + "asking-description": "Copy account link and send to friend.", + "username": "Username:", + "email": "Email:", + "referral": "Referral:", + "copy-key": "Make sure you copy or download your keys.", + "download-keys": "Download Keys", + "create-account-hive": "Pay with HIVE", + "create-account-credit": "Pay with Account Credits ({{n}})", + "confirm-details": "Confirm Details", + "share": "(You can send code to a friend) Copy code", + "copy-link": "Account link copied successfully", + "click-link": "Click here to continue", + "continue": "Continue", + "public-active": "Public Active key:", + "public-memo": "Public Memo key:", + "public-owner": "Public Owner key:", + "public-posting": "Public Posting key:", + "login-warning": "Login to create an account for Friend!", + "pay-fee": "Pay Account Fee", + "modal-title": "Are you sure?", + "modal-confirm": "Confirm", + "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", + "recommend": "We recommend that,", + "recommend-print": "PRINT this file out and store it securely.", + "recommend-use": "NEVER use your password/owner key on untrusted apps.", + "recommend-save": "Save all your keys within a password manager, as you will need them frequently.", + "recommend-third-party": "Don't keep this file within the reach of a third party.", + "account-info": "Your Hive Account Information;", + "keys-use": "What your keys can be used for;", + "owner-private": "Owner private key:", + "active-private": "Active private key:", + "posting-private": "Posting private key:", + "memo-private": "Memo private key:", + "owner": "Owner key:", + "active": "Active key:", + "posting": "Posting key:", + "memo": "Memo key:", + "owner-use": "Change Password, Change Keys, Recover Account", + "active-use": "Transfer Funds, Power up/down, Voting Witnesses/Proposals", + "posting-use": "Post, Comment, Vote, Reblog, Follow, Profile updates", + "memo-use": "Send/View encrypted messages on transfers", + "copy-tooltip": "Copy password", + "regenerate-password": "Regenerate password", + "copy-password": "Password copied successfully", + "copy-info-message": "Copy Link below and SEND to a friend", + "success-message": "You successfully created the account ", + "sign-title": "Sign transaction with ", + "failed-title": "Failed", + "failed-subtitle": "Transaction failed", + "failed-message": "Failed to create account", + "try-again": "Try again", + "sign-header-title": "Sign transaction", + "sign-sub-title": "Sign your transaction" + }, "trending-tags": { "title": "Topics" }, diff --git a/src/common/pages/_sign-up.scss b/src/common/pages/_sign-up.scss index 325febadfc6..76c98d9f108 100644 --- a/src/common/pages/_sign-up.scss +++ b/src/common/pages/_sign-up.scss @@ -14,7 +14,8 @@ align-items: center; gap: 10px; width: max-content; - background-color: $dark-three; + background-color: #161d26; + // background-color: $dark-three; padding: 2rem; border-radius: 1rem; color: $steel-grey; diff --git a/src/common/pages/sign-up.tsx b/src/common/pages/sign-up.tsx index ffdfdc4e289..0adb6f7aee6 100644 --- a/src/common/pages/sign-up.tsx +++ b/src/common/pages/sign-up.tsx @@ -10,20 +10,21 @@ import Meta from "../components/meta"; import Theme from "../components/theme/index"; import NavBar from "../components/navbar/index"; import NavBarElectron from "../../desktop/app/components/navbar"; -import Feedback, { error } from "../components/feedback"; +import Feedback, { success, error } from "../components/feedback"; import ScrollToTop from "../components/scroll-to-top"; import defaults from "../constants/defaults.json"; -import { getAvailibleAccounts, signUp } from "../api/private-api"; import { _t } from "../i18n"; import { hiveSvg } from "../img/svg"; import { handleInvalid, handleOnInput } from "../util/input-util"; import { Community } from "../store/communities/types"; -import { windowExists } from "../../server/util"; import { Global } from "../store/global/types"; import { createHiveAccount } from "../api/operations"; import { generatePassword, getPrivateKeys } from "../helper/onboard"; import { KeyTypes } from "../helper/onboard"; import { downloadSvg, copyContent } from "../img/svg"; +import { b64uEnc } from "../util/b64"; +import { Link } from "react-router-dom"; +import clipboard from "../util/clipboard"; interface Props { global: Global @@ -36,16 +37,17 @@ const SignUpPage = (props: Props | any) => { const [username, setUsername] = useState("") const [email, setEmail] = useState("") - const [lockReferral, setLockReferral] = useState(false) + const [urlHash, setUrlHash] = useState("") const [inProgress, setInProgress] = useState(false) const [community, setCommunity] = useState(null); const [newUserKeys, setNewUserKeys]: any = useState(null); const [accountPassword, setAccountPassword] = useState("") const [step, setStep] = useState(1); const [error, setError] = useState(""); + const [isDownloaded, setIsDownloaded] = useState(false) useEffect(()=> { - console.log(props) + console.log(props.match) getCurrentCommunity() }, []) @@ -60,12 +62,24 @@ const SignUpPage = (props: Props | any) => { const password: Promise = generatePassword(32); const keys: KeyTypes = getPrivateKeys(username, password); + console.log(keys) setNewUserKeys((prev: any) => ({ ...prev, ...keys })); setAccountPassword(await password) - console.log(newUserKeys) - console.log("keys", keys) + const dataToEncode = { + username, + keys: { + activePubKey: keys.activePubkey, + postingPubKey: keys.postingPubkey, + ownerPubKey: keys.ownerPubkey, + memoPubKey: keys.memoPubkey + } + } - // setStep(2) + const stringifiedData = JSON.stringify(dataToEncode); + const hash = encodeURIComponent(stringifiedData) + setUrlHash(hash) + // console.log(JSON.parse(b64uDec(hash))) + console.log("stringifiedData", stringifiedData) } @@ -78,10 +92,6 @@ const SignUpPage = (props: Props | any) => { setEmail(email.toLowerCase()); }; - const createAccount = async () => { - - }; - const getCurrentCommunity = () => { const currCommunity = communities.find( (community: { name: any; }) => community.name === global.hive_id @@ -89,6 +99,55 @@ const SignUpPage = (props: Props | any) => { setCommunity(currCommunity) } + const splitUrl = (url: string) => { + return url.slice(0, 50); + }; + + const downloadKeys = async () => { + if (newUserKeys) { + setIsDownloaded(false); + const element = document.createElement("a"); + const keysToFile = ` + ${_t("onboard.file-warning")} + + ${_t("onboard.recommend")} + 1. ${_t("onboard.recommend-print")} + 2. ${_t("onboard.recommend-use")} + 3. ${_t("onboard.recommend-save")} + 4. ${_t("onboard.recommend-third-party")} + + ${_t("onboard.account-info")} + + Username: ${username} + + Password: ${accountPassword} + + ${_t("onboard.owner-private")} ${newUserKeys.owner} + + ${_t("onboard.active-private")} ${newUserKeys.active} + + ${_t("onboard.posting-private")} ${newUserKeys.posting} + + ${_t("onboard.memo-private")} ${newUserKeys.memo} + + + ${_t("onboard.keys-use")} + ${_t("onboard.owner")} ${_t("onboard.owner-use")} + ${_t("onboard.active")} ${_t("onboard.active-use")} + ${_t("onboard.posting")} ${_t("onboard.posting-use")} + ${_t("onboard.memo")} ${_t("onboard.memo-use")}`; + + const file = new Blob([keysToFile.replace(/\n/g, "\r\n")], { + type: "text/plain" + }); + element.href = URL.createObjectURL(file); + element.download = `${username}_hive_keys.txt`; + document.body.appendChild(element); + element.click(); + setIsDownloaded(true); + } + }; + // Meta config const metaProps = { title: `Welcome to ${community?.title}`, @@ -238,14 +297,17 @@ const SignUpPage = (props: Props | any) => { {copyContent}
- -
+ + {isDownloaded &&

Copy Link below and SEND to a friend

- https://test.com/create-account - {copyContent} + {splitUrl(`${window.origin}/onboard-friend/${urlHash}`)} + { + clipboard(`${window.origin}/onboard-friend/${urlHash}`); + success("Account link copied successfully") + }}>{copyContent}
-
+
}
)}
diff --git a/src/common/routes.ts b/src/common/routes.ts index 40f541dcd5f..349020f3656 100644 --- a/src/common/routes.ts +++ b/src/common/routes.ts @@ -9,6 +9,7 @@ export default { GUESTS: `/guest-posts`, CONTRIBUTE: `/contribute`, SIGN_UP: `/signup`, + ONBOARD: `/onboard-friend/:hash`, WHITE_PAPER: `/whitepaper`, MARKET: `/market`, PRIVACY: `/privacy-policy`, diff --git a/src/common/util/b64.ts b/src/common/util/b64.ts index 4363c91e5b3..f6f31c87fd2 100644 --- a/src/common/util/b64.ts +++ b/src/common/util/b64.ts @@ -1,4 +1,18 @@ -const b64uLookup = {'/': '_', _: '/', '+': '-', '-': '+', '=': '.', '.': '='}; +import { Base64 } from "js-base64"; -export const b64uEnc = (str: string): string => btoa(str).replace(/([+\/=])/g, m => b64uLookup[m]); +// const b64uLookup = { "/": "_", _: "/", "+": "-", "-": "+", "=": ".", ".": "=" }; +const b64uLookup: { [key: string]: string } = { + "/": "_", + "_": "/", + "+": "-", + "-": "+", + "=": ".", + ".": "=", +}; + +export const b64uEnc = (str: string): string => + Base64.encode(str).replace(/(\+|\/|=)/g, (m) => b64uLookup[m]); + +export const b64uDec = (str: string): any => + Base64.decode(str).replace(/(-|_|\.)/g, (m) => b64uLookup[m]); \ No newline at end of file diff --git a/src/style/_components.scss b/src/style/_components.scss index b55d143a6d4..cb780604a6f 100644 --- a/src/style/_components.scss +++ b/src/style/_components.scss @@ -119,6 +119,7 @@ @import "../common/components/converts/"; @import "../common/components/open-orders-list/"; @import "../common/components/savings-withdraw/"; +@import "../common/components/onboard-friend/"; @import "../desktop/app/components/navbar"; @import "../desktop/app/components/updater"; diff --git a/yarn.lock b/yarn.lock index 50125090c16..22b9d542992 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6868,7 +6868,7 @@ js-base64@^2.1.8: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== -js-base64@^3.7.2: +js-base64@^3.7.2, js-base64@^3.7.5: version "3.7.5" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca" integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA== From d74d13ae73c4937d2d7010d70f271d62e210ad54 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Wed, 25 Oct 2023 22:07:58 +0100 Subject: [PATCH 4/7] fix account creation and BA user --- src/common/api/breakaway.ts | 17 ++++ src/common/api/operations.ts | 94 +++++++++---------- .../components/onboard-friend/index.tsx | 83 ++++++++++------ src/common/helper/keychain.ts | 7 +- src/common/pages/sign-up.tsx | 78 ++++++++------- src/common/util/b64.ts | 12 ++- 6 files changed, 173 insertions(+), 118 deletions(-) create mode 100644 src/common/api/breakaway.ts diff --git a/src/common/api/breakaway.ts b/src/common/api/breakaway.ts new file mode 100644 index 00000000000..0077a3672ec --- /dev/null +++ b/src/common/api/breakaway.ts @@ -0,0 +1,17 @@ +import axios from "axios" + +const baUrl = "https://breakaway-points-system-api.onrender.com" + +export const createBreakawayUser = async (username: string, community: string)=> { + try { + const data = { + username, + community + } + const resp = await axios.post(`${baUrl}/signup-keychain`, data) + return resp; + } catch (err) { + console.log(err) + return err; + } +} \ No newline at end of file diff --git a/src/common/api/operations.ts b/src/common/api/operations.ts index 668d4a5a273..ba9f9f52328 100644 --- a/src/common/api/operations.ts +++ b/src/common/api/operations.ts @@ -1,6 +1,6 @@ import hs from "hivesigner"; -import {PrivateKey, Operation, TransactionConfirmation, AccountUpdateOperation, CustomJsonOperation} from '@hiveio/dhive'; +import {PrivateKey, Operation, OperationName, TransactionConfirmation, AccountUpdateOperation, CustomJsonOperation} from '@hiveio/dhive'; import {Parameters} from 'hive-uri'; @@ -1095,65 +1095,59 @@ export const updatePassword = ( ): Promise => hiveClient.broadcast.updateAccount(update, ownerKey); -export const createHiveAccount = async (username: string, newUser: string, keys: KeyTypes) => { - return new Promise(async (resolve, reject) => { - const op_name = "account_create"; - const memoKey = keys.memo - const activeKey = keys.active - const postingKey = keys.posting - - const owner = { +export const createHiveAccount = async (data: any, creator_account: string) => { + + try { + const { username, keys } = data; + + const account = { + name: username, + ...keys, + active: false + }; + console.log(account) + + const op_name: OperationName = "account_create"; + + const owner = { weight_threshold: 1, account_auths: [], - key_auths: [[keys.ownerPubkey, 1]] - }; - const active = { + key_auths: [[account.ownerPubKey, 1]] + }; + const active = { weight_threshold: 1, account_auths: [], - key_auths: [[keys.activePubkey, 1]] - }; - const posting = { + key_auths: [[account.activePubKey, 1]] + }; + const posting = { weight_threshold: 1, account_auths: [["ecency.app", 1]], - key_auths: [[keys.postingPubkey, 1]] - }; - - const ops = []; - const params = { - creator: username, - new_account_name: newUser, + key_auths: [[account.postingPubKey, 1]] + }; + const ops: Array = []; + const params: any = { + creator: creator_account, + new_account_name: account.name, owner, active, posting, - memo_key: keys.memoPubkey, + memo_key: account.memoPubKey, json_metadata: "", extensions: [], fee: "3.000 HIVE" - }; - - const operation = [op_name, params]; - ops.push(operation); - - try { - const response = await keychain.broadcast(username, [operation], "Active"); - if (response) { - resolve(response); - } else { - reject("Account creation failed"); - } - } catch (err) { + }; + const operation: Operation = [op_name, params]; + ops.push(operation); + try { + + const response = await keychain.broadcast(creator_account, [operation], "Active"); + console.log(response) + return response; + } catch (err: any) { + console.log(err); + return err; + } + } catch (err) { console.log(err); - reject(err); - } - - try { - await keychain.addAccount(newUser, { - active: activeKey, - posting: postingKey, - memo: memoKey - }) - } catch (error) { - console.log(error) - } - }); - }; + } +}; \ No newline at end of file diff --git a/src/common/components/onboard-friend/index.tsx b/src/common/components/onboard-friend/index.tsx index 6efbd05504c..6ddf869d752 100644 --- a/src/common/components/onboard-friend/index.tsx +++ b/src/common/components/onboard-friend/index.tsx @@ -12,10 +12,13 @@ import { _t } from "../../i18n"; import { Global } from "../../store/global/types"; import { Community } from "../../store/communities/types"; import { createHiveAccount } from "../../api/operations"; -import { KeyTypes } from "../../helper/onboard"; -import { b64uDec, b64uEnc } from "../../util/b64"; +import { hexDec } from "../../util/b64"; +import { ActiveUser } from "../../store/active-user/types"; +import { Link } from "react-router-dom"; +import { createBreakawayUser } from "../../api/breakaway"; interface Props { + activeUser: ActiveUser global: Global communities: Community[] } @@ -23,52 +26,60 @@ interface Props { interface AccountInfo { username: string; keys: { - postingpubkey: string; - ownerpubkey: string; - activepubkey: string; - memopubkey: string; + postingPubKey: string; + ownerPubKey: string; + activePubKey: string; + memoPubKey: string; } } const OnboardFriend = (props: Props | any) => { const form = useRef(null); - const { global, communities } = props; + const { global, communities, activeUser } = props; - const [username, setUsername] = useState("") const [urlInfo, seturlInfo] = useState(null) const [community, setCommunity] = useState(null); - const [step, setStep] = useState(1); - const [error, setError] = useState(""); + const [step, setStep] = useState("confirm"); + const [msg, setMsg] = useState(""); useEffect(() => { let decodedObj; try { - console.log(props.match.params.hash); if (props.match.params.hash) { - const decodedHash = decodeURIComponent(props.match.params.hash); + const decodedHash = hexDec(props.match.params.hash); decodedObj = JSON.parse(decodedHash); } } catch (error) { console.log(error); } seturlInfo(decodedObj); - console.log(decodedObj); // Log the decoded object here }, []); - - // Meta config + const createAccount = async ()=> { + try { + const response: any = await createHiveAccount({ + username: urlInfo?.username, + keys: urlInfo?.keys + }, + activeUser?.username + ); + if (response.success === true) { + setStep("success"); + await createBreakawayUser(urlInfo!.username, "Rally") + setMsg(response.message) + } else { + setStep("fail") + setMsg(response.message) + } + } catch (error) { + console.log(error) + }; + }; + const metaProps = { title: `Welcome to ${community?.title}`, }; - const spinner = ( - - ); let containerClasses = global.isElectron ? "app-content sign-up-page mb-lg-0 mt-0 pt-6" : "app-content sign-up-page mb-lg-0"; @@ -85,24 +96,36 @@ const OnboardFriend = (props: Props | any) => { }) : NavBar({ ...props })}
+ { !activeUser ?

You must be logged in to create an account

:
+ {step=== "confirm" && <>
You are creating an account for a friend
{urlInfo && (
Username: {urlInfo.username} - Public posting: {urlInfo.keys.postingpubkey} - Public Owner: {urlInfo.keys.ownerpubkey} - Public active: {urlInfo.keys.activepubkey} - Memo active: {urlInfo.keys.memopubkey} + Public posting: {urlInfo.keys.postingPubKey} + Public Owner: {urlInfo.keys.ownerPubKey} + Public active: {urlInfo.keys.activePubKey} + Memo active: {urlInfo.keys.memoPubKey}
)}
- +
-
-
+ } + {step === "success" && + <> +

{msg}

+ Visist @{urlInfo?.username}'s profile + } + {step === "fail" && <> +

{msg}

+ + } + } + ); } diff --git a/src/common/helper/keychain.ts b/src/common/helper/keychain.ts index 0573e79c361..3f500119f0b 100644 --- a/src/common/helper/keychain.ts +++ b/src/common/helper/keychain.ts @@ -13,8 +13,8 @@ type AuthorityTypes = "Posting" | "Active" | "Memo"; type Keys = { active: any, posting: any, memo: any }; -export const handshake = (): Promise => - new Promise((resolve) => { +export const handshake = (): Promise => + new Promise((resolve) => { window.hive_keychain?.requestHandshake(() => { resolve(); }); @@ -85,7 +85,8 @@ export const broadcast = (account: string, operations: any[], key: AuthorityType new Promise((resolve, reject) => { window.hive_keychain?.requestBroadcast(account, operations, key, (resp) => { if (!resp.success) { - reject({message: "Operation cancelled"}); + reject(resp); + // reject({message: "Operation cancelled"}); } resolve(resp); diff --git a/src/common/pages/sign-up.tsx b/src/common/pages/sign-up.tsx index 0adb6f7aee6..56f4b42e2e8 100644 --- a/src/common/pages/sign-up.tsx +++ b/src/common/pages/sign-up.tsx @@ -18,25 +18,27 @@ import { hiveSvg } from "../img/svg"; import { handleInvalid, handleOnInput } from "../util/input-util"; import { Community } from "../store/communities/types"; import { Global } from "../store/global/types"; -import { createHiveAccount } from "../api/operations"; import { generatePassword, getPrivateKeys } from "../helper/onboard"; import { KeyTypes } from "../helper/onboard"; import { downloadSvg, copyContent } from "../img/svg"; -import { b64uEnc } from "../util/b64"; +import { hexEnc } from "../util/b64"; import { Link } from "react-router-dom"; import clipboard from "../util/clipboard"; +import { ActiveUser } from "../store/active-user/types"; interface Props { - global: Global - communities: Community[] + activeUser: ActiveUser; + global: Global + communities: Community[] } const SignUpPage = (props: Props | any) => { const form = useRef(null); - const { global, communities } = props; + const { global, communities, activeUser } = props; const [username, setUsername] = useState("") const [email, setEmail] = useState("") + const [referral, setReferral] = useState("") const [urlHash, setUrlHash] = useState("") const [inProgress, setInProgress] = useState(false) const [community, setCommunity] = useState(null); @@ -47,7 +49,6 @@ const SignUpPage = (props: Props | any) => { const [isDownloaded, setIsDownloaded] = useState(false) useEffect(()=> { - console.log(props.match) getCurrentCommunity() }, []) @@ -60,11 +61,10 @@ const SignUpPage = (props: Props | any) => { return; } - const password: Promise = generatePassword(32); + const password: string = await generatePassword(32); const keys: KeyTypes = getPrivateKeys(username, password); - console.log(keys) setNewUserKeys((prev: any) => ({ ...prev, ...keys })); - setAccountPassword(await password) + setAccountPassword(password) const dataToEncode = { username, keys: { @@ -76,22 +76,25 @@ const SignUpPage = (props: Props | any) => { } const stringifiedData = JSON.stringify(dataToEncode); - const hash = encodeURIComponent(stringifiedData) + const hash = hexEnc(stringifiedData) setUrlHash(hash) - // console.log(JSON.parse(b64uDec(hash))) - console.log("stringifiedData", stringifiedData) - } const usernameChanged = (e: { target: { value: any; }; }) => { const { value: username } = e.target; setUsername(username.toLowerCase()); }; + const emailChanged = (e: { target: { value: any; }; }) => { const { value: email } = e.target; setEmail(email.toLowerCase()); }; + const referralChanged = (e: { target: { value: any; }; }) => { + const { value: email } = e.target; + setReferral(email.toLowerCase()); + }; + const getCurrentCommunity = () => { const currCommunity = communities.find( (community: { name: any; }) => community.name === global.hive_id @@ -148,7 +151,6 @@ const SignUpPage = (props: Props | any) => { } }; - // Meta config const metaProps = { title: `Welcome to ${community?.title}`, }; @@ -198,11 +200,6 @@ const SignUpPage = (props: Props | any) => { onSubmit={(e) => { e.preventDefault(); e.stopPropagation(); - - // if (!form.current?.checkValidity()) { - // return; - // } - setStep(2); }} > @@ -222,11 +219,10 @@ const SignUpPage = (props: Props | any) => { handleInvalid(e, "sign-up.", "validation-username") @@ -234,6 +230,19 @@ const SignUpPage = (props: Props | any) => { onInput={handleOnInput} /> + + + handleInvalid(e, "sign-up.", "validation-username") + } + onInput={handleOnInput} + /> +
- Make sure you copy and save ypur acc password securely + Make sure you copy and save your account password securely
- {accountPassword} - {copyContent} + {accountPassword}... + { + clipboard(accountPassword) + success("Password copied successfully") + }}>{copyContent}
{isDownloaded &&
-

Copy Link below and SEND to a friend

-
- {splitUrl(`${window.origin}/onboard-friend/${urlHash}`)} - { - clipboard(`${window.origin}/onboard-friend/${urlHash}`); - success("Account link copied successfully") - }}>{copyContent} -
+ {!activeUser ? <> +

Copy Link below and SEND to a friend

+
+ {splitUrl(`${window.origin}/onboard-friend/${urlHash}`)}... + { + clipboard(`${window.origin}/onboard-friend/${urlHash}`); + success("Account link copied successfully") + }}>{copyContent} +
+ : Click here to continue}
} )} diff --git a/src/common/util/b64.ts b/src/common/util/b64.ts index f6f31c87fd2..192a10a7c45 100644 --- a/src/common/util/b64.ts +++ b/src/common/util/b64.ts @@ -1,7 +1,5 @@ import { Base64 } from "js-base64"; -// const b64uLookup = { "/": "_", _: "/", "+": "-", "-": "+", "=": ".", ".": "=" }; - const b64uLookup: { [key: string]: string } = { "/": "_", "_": "/", @@ -15,4 +13,12 @@ export const b64uEnc = (str: string): string => Base64.encode(str).replace(/(\+|\/|=)/g, (m) => b64uLookup[m]); export const b64uDec = (str: string): any => - Base64.decode(str).replace(/(-|_|\.)/g, (m) => b64uLookup[m]); \ No newline at end of file + Base64.decode(str).replace(/(-|_|\.)/g, (m) => b64uLookup[m]); + + export const hexEnc = (str: string): string => { + return str.split('').map((char) => char.charCodeAt(0).toString(16)).join(''); + }; + + export const hexDec = (hexString: string): string => { + return hexString.match(/.{1,2}/g)?.map((byte) => String.fromCharCode(parseInt(byte, 16))).join('') || ''; + }; \ No newline at end of file From 963f6eb027e3e04d1873556eda1249c6f7f605b0 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Thu, 26 Oct 2023 19:51:58 +0100 Subject: [PATCH 5/7] fix translations --- src/common/api/breakaway.ts | 7 ++-- .../components/onboard-friend/index.tsx | 29 ++++++++------- src/common/i18n/locales/en-US.json | 7 ++-- src/common/pages/sign-up.tsx | 35 +++++++++++-------- 4 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/common/api/breakaway.ts b/src/common/api/breakaway.ts index 0077a3672ec..6ef94409fc9 100644 --- a/src/common/api/breakaway.ts +++ b/src/common/api/breakaway.ts @@ -1,12 +1,15 @@ import axios from "axios" +// const baUrl = "http://localhost:4000" const baUrl = "https://breakaway-points-system-api.onrender.com" -export const createBreakawayUser = async (username: string, community: string)=> { +export const createBreakawayUser = async (username: string, community: string, referral: string, email: string)=> { try { const data = { username, - community + community, + referral, + email } const resp = await axios.post(`${baUrl}/signup-keychain`, data) return resp; diff --git a/src/common/components/onboard-friend/index.tsx b/src/common/components/onboard-friend/index.tsx index 6ddf869d752..ead987c9c3c 100644 --- a/src/common/components/onboard-friend/index.tsx +++ b/src/common/components/onboard-friend/index.tsx @@ -16,15 +16,18 @@ import { hexDec } from "../../util/b64"; import { ActiveUser } from "../../store/active-user/types"; import { Link } from "react-router-dom"; import { createBreakawayUser } from "../../api/breakaway"; +import { getAccount } from "../../api/hive"; interface Props { activeUser: ActiveUser - global: Global - communities: Community[] + global: Global + communities: Community[] } interface AccountInfo { username: string; + referral: string; + email: string; keys: { postingPubKey: string; ownerPubKey: string; @@ -34,7 +37,6 @@ interface AccountInfo { } const OnboardFriend = (props: Props | any) => { - const form = useRef(null); const { global, communities, activeUser } = props; const [urlInfo, seturlInfo] = useState(null) @@ -48,6 +50,7 @@ const OnboardFriend = (props: Props | any) => { if (props.match.params.hash) { const decodedHash = hexDec(props.match.params.hash); decodedObj = JSON.parse(decodedHash); + console.log(props) } } catch (error) { console.log(error); @@ -65,7 +68,7 @@ const OnboardFriend = (props: Props | any) => { ); if (response.success === true) { setStep("success"); - await createBreakawayUser(urlInfo!.username, "Rally") + await createBreakawayUser(urlInfo!.username, props.global.hive_id, urlInfo!.referral, urlInfo!.email) setMsg(response.message) } else { setStep("fail") @@ -96,23 +99,23 @@ const OnboardFriend = (props: Props | any) => { }) : NavBar({ ...props })}
- { !activeUser ?

You must be logged in to create an account

: + { !activeUser ?

{_t("onboard.login-warning")}

:
{step=== "confirm" && <> -
You are creating an account for a friend
+
{_t("onboard.creating-for-a-friend")}
{urlInfo && (
- Username: {urlInfo.username} - Public posting: {urlInfo.keys.postingPubKey} - Public Owner: {urlInfo.keys.ownerPubKey} - Public active: {urlInfo.keys.activePubKey} - Memo active: {urlInfo.keys.memoPubKey} + {_t("onboard.username")} {urlInfo.username} + {_t("onboard.public-posting")} {urlInfo.keys.postingPubKey} + {_t("onboard.public-owner")} {urlInfo.keys.ownerPubKey} + {_t("onboard.public-active")} {urlInfo.keys.activePubKey} + {_t("onboard.public-memo")} {urlInfo.keys.memoPubKey}
)}
- +
} {step === "success" && @@ -122,7 +125,7 @@ const OnboardFriend = (props: Props | any) => { } {step === "fail" && <>

{msg}

- + }
}
diff --git a/src/common/i18n/locales/en-US.json b/src/common/i18n/locales/en-US.json index 4e93f3a30cc..b999973b1c1 100644 --- a/src/common/i18n/locales/en-US.json +++ b/src/common/i18n/locales/en-US.json @@ -175,13 +175,13 @@ }, "onboard": { "description-active-user": "You can create account for a friend.", - "description-visitor": "You can ask a friend to create an account for you.", "creating-description": "Pay with hive or account credit", "asking-description": "Copy account link and send to friend.", "username": "Username:", "email": "Email:", "referral": "Referral:", "copy-key": "Make sure you copy or download your keys.", + "key-copied": "Password copied successfully", "download-keys": "Download Keys", "create-account-hive": "Pay with HIVE", "create-account-credit": "Pay with Account Credits ({{n}})", @@ -194,10 +194,10 @@ "public-memo": "Public Memo key:", "public-owner": "Public Owner key:", "public-posting": "Public Posting key:", - "login-warning": "Login to create an account for Friend!", + "login-warning": "You must be Logged in to create an account for Friend!", "pay-fee": "Pay Account Fee", "modal-title": "Are you sure?", - "modal-confirm": "Confirm", + "confirm": "Confirm", "file-warning": "Please handle your password & private keys with extra caution. Your account will no longer be accessible if you loose your password. We do not keep copy of it, it is confidential only you have access to it.", "recommend": "We recommend that,", "recommend-print": "PRINT this file out and store it securely.", @@ -222,6 +222,7 @@ "regenerate-password": "Regenerate password", "copy-password": "Password copied successfully", "copy-info-message": "Copy Link below and SEND to a friend", + "creating-for-a-friend": "You are creating an account for a friend.", "success-message": "You successfully created the account ", "sign-title": "Sign transaction with ", "failed-title": "Failed", diff --git a/src/common/pages/sign-up.tsx b/src/common/pages/sign-up.tsx index 56f4b42e2e8..ee1bb08b867 100644 --- a/src/common/pages/sign-up.tsx +++ b/src/common/pages/sign-up.tsx @@ -67,6 +67,8 @@ const SignUpPage = (props: Props | any) => { setAccountPassword(password) const dataToEncode = { username, + email, + referral, keys: { activePubKey: keys.activePubkey, postingPubKey: keys.postingPubkey, @@ -220,7 +222,7 @@ const SignUpPage = (props: Props | any) => { { { {newUserKeys && step == 2 && (

- Confirm Account Information + {_t("onboard.confirm-details")}

- Username: {username} + {_t("onboard.username")} {username} - Email: {email} + {_t("onboard.email")} {email} - Active Public key: {newUserKeys?.activePubkey} + {_t("onboard.refferal")} {referral} - Owner Public key: {newUserKeys?.ownerPubkey} + {_t("onboard.public-active")} {newUserKeys?.activePubkey} - Posting Public Key: {newUserKeys?.postingPubkey} + {_t("onboard.public-owner")} {newUserKeys?.ownerPubkey} - Memo Public Key: {newUserKeys?.memoPubkey} + {_t("onboard.public-posting")} {newUserKeys?.postingPubkey} + + + {_t("onboard.public-memo")} {newUserKeys?.memoPubkey}
- Make sure you copy and save your account password securely + {_t("onboard.copy-key")}
{accountPassword}... { clipboard(accountPassword) - success("Password copied successfully") + success(_t("onboard.key-copied")) }}>{copyContent}
- + {isDownloaded &&
{!activeUser ? <> -

Copy Link below and SEND to a friend

+

{_t("onboard.copy-info-message")}

{splitUrl(`${window.origin}/onboard-friend/${urlHash}`)}... { clipboard(`${window.origin}/onboard-friend/${urlHash}`); - success("Account link copied successfully") + success(_t("onboard.copy-link")) }}>{copyContent}
- : Click here to continue} + : {_t("onboard.click-link")}}
}
)} From 3e4e9a6d715fc2e2b2e90c3e2f2d1c9c4ae196e6 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Mon, 30 Oct 2023 12:06:07 +0100 Subject: [PATCH 6/7] create account with acc token --- src/common/api/hive.ts | 1 + src/common/api/operations.ts | 63 ++++++++++++++++++- .../components/onboard-friend/index.scss | 6 ++ .../components/onboard-friend/index.tsx | 44 +++++++++++-- src/common/pages/sign-up.tsx | 61 +++++++++++------- src/common/store/accounts/types.ts | 1 + 6 files changed, 149 insertions(+), 27 deletions(-) diff --git a/src/common/api/hive.ts b/src/common/api/hive.ts index 5a06261c433..0a1757aa371 100644 --- a/src/common/api/hive.ts +++ b/src/common/api/hive.ts @@ -184,6 +184,7 @@ export const getAccounts = (usernames: string[]): Promise => { voting_manabar: x.voting_manabar, voting_power: x.voting_power, downvote_manabar: x.downvote_manabar, + pending_claimed_accounts: x.pending_claimed_accounts, __loaded: true, }; diff --git a/src/common/api/operations.ts b/src/common/api/operations.ts index ba9f9f52328..cff747727dc 100644 --- a/src/common/api/operations.ts +++ b/src/common/api/operations.ts @@ -1150,4 +1150,65 @@ export const createHiveAccount = async (data: any, creator_account: string) => { } catch (err) { console.log(err); } -}; \ No newline at end of file +}; + +// Create account with credit +export const createAccountWithCredit = async (data: any, creator_account: string) => { + try { + const { username, keys } = data; + + const account = { + name: username, + ...keys, + active: false + }; + + let tokens: any = await hiveClient.database.getAccounts([creator_account]); + console.log(tokens) + tokens = tokens[0]?.pending_claimed_accounts; + + let fee = null; + let op_name: OperationName = "create_claimed_account"; + + const owner = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.ownerPubKey, 1]] + }; + const active = { + weight_threshold: 1, + account_auths: [], + key_auths: [[account.activePubKey, 1]] + }; + const posting = { + weight_threshold: 1, + account_auths: [["ecency.app", 1]], + key_auths: [[account.postingPubKey, 1]] + }; + const ops: Array = []; + const params: any = { + creator: creator_account, + new_account_name: account.name, + owner, + active, + posting, + memo_key: account.memoPubKey, + json_metadata: "", + extensions: [] + }; + + if (fee) params.fee = fee; + const operation: Operation = [op_name, params]; + ops.push(operation); + try { + const newAccount = await keychain.broadcast(creator_account, [operation], "Active"); + return newAccount; + } catch (err: any) { + return err; + } + } catch (err) { + console.log(err); + return err; + } + }; + \ No newline at end of file diff --git a/src/common/components/onboard-friend/index.scss b/src/common/components/onboard-friend/index.scss index c61799a0989..8a3276b7bff 100644 --- a/src/common/components/onboard-friend/index.scss +++ b/src/common/components/onboard-friend/index.scss @@ -16,4 +16,10 @@ display: flex; flex-direction: column; gap: 15px; + } + + .create-buttons{ + display: flex; + margin-top: 5px; + gap: 10px; } \ No newline at end of file diff --git a/src/common/components/onboard-friend/index.tsx b/src/common/components/onboard-friend/index.tsx index ead987c9c3c..584de93612e 100644 --- a/src/common/components/onboard-friend/index.tsx +++ b/src/common/components/onboard-friend/index.tsx @@ -11,12 +11,12 @@ import ScrollToTop from "../scroll-to-top"; import { _t } from "../../i18n"; import { Global } from "../../store/global/types"; import { Community } from "../../store/communities/types"; -import { createHiveAccount } from "../../api/operations"; +import { createHiveAccount, createAccountWithCredit } from "../../api/operations"; import { hexDec } from "../../util/b64"; import { ActiveUser } from "../../store/active-user/types"; import { Link } from "react-router-dom"; import { createBreakawayUser } from "../../api/breakaway"; -import { getAccount } from "../../api/hive"; +import { getAccounts } from "../../api/hive"; interface Props { activeUser: ActiveUser @@ -43,6 +43,7 @@ const OnboardFriend = (props: Props | any) => { const [community, setCommunity] = useState(null); const [step, setStep] = useState("confirm"); const [msg, setMsg] = useState(""); + const [token, setToken] = useState(0) useEffect(() => { let decodedObj; @@ -50,13 +51,39 @@ const OnboardFriend = (props: Props | any) => { if (props.match.params.hash) { const decodedHash = hexDec(props.match.params.hash); decodedObj = JSON.parse(decodedHash); - console.log(props) } } catch (error) { console.log(error); } seturlInfo(decodedObj); + getAccountTokens(); }, []); + + const getAccountTokens = async ()=>{ + const acc = await getAccounts([activeUser?.username!]); + setToken(acc[0]?.pending_claimed_accounts) + } + + const accountWithCredit = async () => { + try { + const response: any = await createAccountWithCredit({ + username: urlInfo?.username, + keys: urlInfo?.keys + }, + activeUser?.username + ) + if (response.success === true) { + setStep("success"); + await createBreakawayUser(urlInfo!.username, props.global.hive_id, urlInfo!.referral, urlInfo!.email) + setMsg(response.message) + } else { + setStep("fail") + setMsg(response.message) + } + } catch (error) { + + } + } const createAccount = async ()=> { try { @@ -114,8 +141,15 @@ const OnboardFriend = (props: Props | any) => { )} -
- +
+ +
} {step === "success" && diff --git a/src/common/pages/sign-up.tsx b/src/common/pages/sign-up.tsx index ee1bb08b867..fbe65b575ac 100644 --- a/src/common/pages/sign-up.tsx +++ b/src/common/pages/sign-up.tsx @@ -25,6 +25,7 @@ import { hexEnc } from "../util/b64"; import { Link } from "react-router-dom"; import clipboard from "../util/clipboard"; import { ActiveUser } from "../store/active-user/types"; +import { getAccount } from "../api/hive"; interface Props { activeUser: ActiveUser; @@ -61,30 +62,44 @@ const SignUpPage = (props: Props | any) => { return; } - const password: string = await generatePassword(32); - const keys: KeyTypes = getPrivateKeys(username, password); - setNewUserKeys((prev: any) => ({ ...prev, ...keys })); - setAccountPassword(password) - const dataToEncode = { - username, - email, - referral, - keys: { - activePubKey: keys.activePubkey, - postingPubKey: keys.postingPubkey, - ownerPubKey: keys.ownerPubkey, - memoPubKey: keys.memoPubkey + try { + const password: string = await generatePassword(32); + const keys: KeyTypes = getPrivateKeys(username, password); + setNewUserKeys((prev: any) => ({ ...prev, ...keys })); + setAccountPassword(password) + const dataToEncode = { + username, + email, + referral, + keys: { + activePubKey: keys.activePubkey, + postingPubKey: keys.postingPubkey, + ownerPubKey: keys.ownerPubkey, + memoPubKey: keys.memoPubkey + } } + + const stringifiedData = JSON.stringify(dataToEncode); + const hash = hexEnc(stringifiedData) + setUrlHash(hash) + } catch (err) { + console.log(err) } - - const stringifiedData = JSON.stringify(dataToEncode); - const hash = hexEnc(stringifiedData) - setUrlHash(hash) } - const usernameChanged = (e: { target: { value: any; }; }) => { + + const usernameChanged = async (e: { target: { value: any; }; }) => { + setInProgress(true) const { value: username } = e.target; setUsername(username.toLowerCase()); + const existingAccount = await getAccount(username) + + if (existingAccount){ + setError("username not available"); + } else { + setError("") + } + setInProgress(false) }; const emailChanged = (e: { target: { value: any; }; }) => { @@ -202,10 +217,14 @@ const SignUpPage = (props: Props | any) => { onSubmit={(e) => { e.preventDefault(); e.stopPropagation(); + if(error){ + return; + } setStep(2); }} - > - + > + + {error && {error}} { {_t("onboard.email")} {email} - {_t("onboard.refferal")} {referral} + {_t("onboard.referral")} {referral} {_t("onboard.public-active")} {newUserKeys?.activePubkey} diff --git a/src/common/store/accounts/types.ts b/src/common/store/accounts/types.ts index cf1c20fb27b..e92f2450387 100644 --- a/src/common/store/accounts/types.ts +++ b/src/common/store/accounts/types.ts @@ -62,6 +62,7 @@ export interface FullAccount { }; profile?: AccountProfile; follow_stats?: AccountFollowStats; + pending_claimed_accounts: number; __loaded?: true; } From 51939fc8099a8439b64f53c8c0b6212663e83915 Mon Sep 17 00:00:00 2001 From: Adesojisouljay Date: Thu, 2 Nov 2023 16:46:01 +0100 Subject: [PATCH 7/7] create offchain and Ui improvements --- src/common/api/breakaway.ts | 20 +- .../components/offchain-users/index.tsx | 197 ++++++++++ src/common/img/hive-logo.jpeg | Bin 0 -> 6375 bytes src/common/img/solanaLogo.png | Bin 0 -> 2128 bytes src/common/img/spklogo.png | Bin 0 -> 3365 bytes src/common/pages/_sign-up.scss | 179 +++++---- src/common/pages/sign-up.tsx | 346 ++++++++++-------- 7 files changed, 518 insertions(+), 224 deletions(-) create mode 100644 src/common/components/offchain-users/index.tsx create mode 100644 src/common/img/hive-logo.jpeg create mode 100644 src/common/img/solanaLogo.png create mode 100644 src/common/img/spklogo.png diff --git a/src/common/api/breakaway.ts b/src/common/api/breakaway.ts index 6ef94409fc9..dfabbeec35e 100644 --- a/src/common/api/breakaway.ts +++ b/src/common/api/breakaway.ts @@ -17,4 +17,22 @@ export const createBreakawayUser = async (username: string, community: string, r console.log(err) return err; } -} \ No newline at end of file +} + +export const createSolanaUser = async (email: string, password: string, solanaWalletAddress: string) => { + try { + const data = { + email, + password, + solanaWalletAddress, + }; + + const resp = await axios.post(`${baUrl}/offchain-users/register`, data); + + return resp.data; + } catch (err) { + console.log(err); + + return { err } + } +}; diff --git a/src/common/components/offchain-users/index.tsx b/src/common/components/offchain-users/index.tsx new file mode 100644 index 00000000000..3dbb3fe9dc4 --- /dev/null +++ b/src/common/components/offchain-users/index.tsx @@ -0,0 +1,197 @@ +import React, { useState, useRef } from 'react' +import { _t } from '../../i18n'; +import { Button, Form } from 'react-bootstrap'; +import { handleInvalid, handleOnInput } from "../../util/input-util"; +import { createSolanaUser } from '../../api/breakaway'; +import { Link } from 'react-router-dom'; +import axios from "axios" + +const spkLogo = require("../../img/spklogo.png"); +const solanaLogo = require("../../img/solanaLogo.png"); + +export const OffchainUser = (props: any) => { + const { inProgress, spinner, step, setStep, setInProgress } = props; + const form = useRef(null); + + const [username, setUsername] = useState("") + const [email, setEmail] = useState("") + const [solanaAddress, setSolanaAddress] = useState("") + const [error, setError] = useState(""); + const [password, setPassword] = useState(""); + const [confirmPassword, setConfirmPassword] = useState(""); + + const emailChanged =(e: { target: { value: React.SetStateAction; }; })=>{ + setEmail(e.target.value) + } + + const solanaAddressChanged =(e: { target: { value: React.SetStateAction; }; })=>{ + setSolanaAddress(e.target.value) + } + + const passwordChanged =(e: { target: { value: React.SetStateAction; }; })=>{ + setPassword(e.target.value) + } + + const createSolUser = async ()=> { + setInProgress(true) + console.log(email, password, solanaAddress) + if (!email || !password || !solanaAddress) { + setError("Some fields missing"); + return; + } + if(password !== confirmPassword){ + setError("Password do not match"); + return; + } else{ + setError("") + } + + try { + const res: any = await createSolanaUser(email, password, solanaAddress); + console.log(res.err.response.data.message) + if(res.success){ + setStep(2) + setError("") + } else { + setStep(2) + setError(res.err.response.data.message) + } + } catch (error) { + console.log(error) + } + setInProgress(false) + } + + return ( + <> + {step === 1 &&
+
+
Register with Solana
+
{_t("sign-up.description")}
+ {/*
+ SpkNetwork + Solana +
*/} + {(() => { + return ( +
+
+ + + handleInvalid(e, "sign-up.", "validation-username") + } + onInput={handleOnInput} + /> + + + + handleInvalid(e, "sign-up.", "validation-username") + } + onInput={handleOnInput} + /> + + + + handleInvalid(e, "sign-up.", "validation-username") + } + onInput={handleOnInput} + /> + + + setConfirmPassword(e.target.value)} + required={true} + onInvalid={(e: any) => + handleInvalid(e, "sign-up.", "validation-username") + } + onInput={handleOnInput} + /> + +
+ +
+
+ + +
+ ); + })()} +
+
} + {step == 2 && !error && ( +
+
+

+ Account created succesfully +

+ Login +
+
+ )} + {step == 2 && error && ( +
+
+

+ {error} +

+ +
+
+ )} + + ) +} diff --git a/src/common/img/hive-logo.jpeg b/src/common/img/hive-logo.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..84dfacaf896e38c5fe4d069f480f618fe094f16c GIT binary patch literal 6375 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 literal 0 HcmV?d00001 diff --git a/src/common/img/spklogo.png b/src/common/img/spklogo.png new file mode 100644 index 0000000000000000000000000000000000000000..e33568e1544d4634fdc2172c5c4d99179750c236 GIT binary patch literal 3365 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 literal 0 HcmV?d00001 diff --git a/src/common/pages/_sign-up.scss b/src/common/pages/_sign-up.scss index 76c98d9f108..7f206768c4b 100644 --- a/src/common/pages/_sign-up.scss +++ b/src/common/pages/_sign-up.scss @@ -1,67 +1,76 @@ .sign-up-page { + height: 100vh; display: flex; justify-content: center; align-items: center; + margin: auto; @media (max-width: $md-break) { flex-direction: column; align-items: center; } - .success-info { - display: flex; - flex-direction: column; - align-items: center; - gap: 10px; - width: max-content; - background-color: #161d26; - // background-color: $dark-three; - padding: 2rem; - border-radius: 1rem; - color: $steel-grey; - word-break: break-all; - - .account-details{ - display: flex; - justify-content: center; - flex-direction: column; - gap: 5px; - } - - .account-password{ + .success-wrapper{ + justify-self: center; + align-self: center; + display: flex; + justify-content: center; + width: 100%; + .success-info { display: flex; flex-direction: column; align-items: center; gap: 10px; - - .password{ + width: max-content; + background-color: #161d26; + // background-color: $dark-three; + padding: 2rem; + border-radius: 1rem; + color: $steel-grey; + word-break: break-all; + + .account-details{ + display: flex; + justify-content: center; + flex-direction: column; + gap: 5px; + } + + .account-password{ display: flex; + flex-direction: column; align-items: center; - gap: 3px; - - .icon{ - cursor: pointer; + gap: 10px; + + .password{ + display: flex; + align-items: center; + gap: 3px; + + .icon{ + cursor: pointer; + } } } - } - - .account-link{ - display: flex; - flex-direction: column; - align-items: center; - - .link{ + + .account-link{ display: flex; + flex-direction: column; align-items: center; - gap: 3px; - - .icon{ - cursor: pointer; + + .link{ + display: flex; + align-items: center; + gap: 3px; + + .icon{ + cursor: pointer; + } } } - } - - } + + } + } @media (max-width: $md-break) { margin-bottom: 2rem; @@ -69,9 +78,8 @@ } .sign-up { - max-width: 1400px; width: 100%; - margin: auto; + display: flex; @media (min-width: $xl-break) { display: flex; @@ -96,16 +104,15 @@ } .the-form { - margin: 0 auto; - @media (min-width: $xl-break) { - width: 50%; - } + width: 100%; + display: flex; + flex-direction: column; + gap: 20px; .form-title { font-size: 28px; font-weight: 500; text-align: center; - margin-bottom: 10px; @media (min-width: $xl-break) { font-size: 32px; @@ -117,27 +124,6 @@ text-align: center; } - .form-icons { - text-align: center; - margin: 22px 0 12px 16px; - - @media (min-width: $xl-break) { - margin: 56px 0; - } - - img, svg { - height: 44px; - } - - img { - margin-right: 60px; - } - - svg { - color: #D2323E; - } - } - .form-image { margin-bottom: 6px; text-align: center; @@ -182,11 +168,14 @@ } .form-content { - max-width: 460px; + width: 70%; + display: flex; + flex-direction: column; + gap: 20px; margin: auto; - + form { - margin-bottom: 26px; + gap: 20px; } .form-do-login, .form-bottom-description, .form-faq { @@ -203,3 +192,47 @@ } } } + +.wrapper{ + display: flex; + justify-self: center; + align-items: center; + width: 100%; + + .account-types{ + flex: 1; + display: flex; + padding: 20px; + align-items: center; + flex-direction: column; + gap: 20px; + justify-content: flex-end; + + img{ + width: 30px; + height: 30px; + border-radius: 50%; + object-fit: cover; + } + .account-type{ + display: flex; + justify-content: center; + align-items: center; + gap: 20px; + border: 1px solid rgb(69, 63, 109); + width: 400px; + padding: 10px; + cursor: pointer; + + span{ + font-size: 18px; + font-weight: bold; + } + } + } + + .account-sign-up{ + display: flex; + flex: 1; + } +} \ No newline at end of file diff --git a/src/common/pages/sign-up.tsx b/src/common/pages/sign-up.tsx index fbe65b575ac..1a4519e4681 100644 --- a/src/common/pages/sign-up.tsx +++ b/src/common/pages/sign-up.tsx @@ -26,6 +26,10 @@ import { Link } from "react-router-dom"; import clipboard from "../util/clipboard"; import { ActiveUser } from "../store/active-user/types"; import { getAccount } from "../api/hive"; +import { OffchainUser } from "../components/offchain-users"; + +const HiveLogo = require("../img/hive-logo.jpeg"); +const solanaLogo = require("../img/solanaLogo.png"); interface Props { activeUser: ActiveUser; @@ -48,6 +52,7 @@ const SignUpPage = (props: Props | any) => { const [step, setStep] = useState(1); const [error, setError] = useState(""); const [isDownloaded, setIsDownloaded] = useState(false) + const [accountType, setAccountType] = useState("Hive"); useEffect(()=> { getCurrentCommunity() @@ -87,7 +92,6 @@ const SignUpPage = (props: Props | any) => { } } - const usernameChanged = async (e: { target: { value: any; }; }) => { setInProgress(true) const { value: username } = e.target; @@ -168,6 +172,10 @@ const SignUpPage = (props: Props | any) => { } }; + const handleAccountTypeClick = (type: string) => { + setAccountType(type); + }; + const metaProps = { title: `Welcome to ${community?.title}`, }; @@ -195,159 +203,197 @@ const SignUpPage = (props: Props | any) => { ...props, }) : NavBar({ ...props })} -
- {step == 1 &&
-
-
Create a Hive acoount
-
{_t("sign-up.description")}
-
- Ecency - {hiveSvg} -
- {(() => { - return ( -
-
{ - e.preventDefault(); - e.stopPropagation(); - if(error){ - return; - } - setStep(2); - }} - > - - {error && {error}} - - handleInvalid(e, "sign-up.", "validation-username") - } - onInput={handleOnInput} - /> - - - - handleInvalid(e, "sign-up.", "validation-username") - } - onInput={handleOnInput} - /> - - - - handleInvalid(e, "sign-up.", "validation-username") - } - onInput={handleOnInput} - /> - -
- -
-
- - -
- ); - })()} -
-
} - {newUserKeys && step == 2 && ( -
-

- {_t("onboard.confirm-details")} -

-
- - {_t("onboard.username")} {username} - - - {_t("onboard.email")} {email} - - - {_t("onboard.referral")} {referral} - - - {_t("onboard.public-active")} {newUserKeys?.activePubkey} - - - {_t("onboard.public-owner")} {newUserKeys?.ownerPubkey} +
+
+ {step === 1 &&
+

Sign up with

+
handleAccountTypeClick("Hive")} + > + Solana + + Hive - - {_t("onboard.public-posting")} {newUserKeys?.postingPubkey} - - - {_t("onboard.public-memo")} {newUserKeys?.memoPubkey} +
+
handleAccountTypeClick("Solana")} + > + Solana + + Solana -
-
- {_t("onboard.copy-key")} -
- {accountPassword}... - { - clipboard(accountPassword) - success(_t("onboard.key-copied")) - }}>{copyContent}
-
- - {isDownloaded &&
- {!activeUser ? <> -

{_t("onboard.copy-info-message")}

-
- {splitUrl(`${window.origin}/onboard-friend/${urlHash}`)}... - { - clipboard(`${window.origin}/onboard-friend/${urlHash}`); - success(_t("onboard.copy-link")) - }}>{copyContent} -
- : {_t("onboard.click-link")}}
} -
- )} +
+ {accountType === "Hive" && <> + {step == 1 &&
+
+
Create a Hive acoount
+
{_t("sign-up.description")}
+ + {(() => { + return ( +
+
{ + e.preventDefault(); + e.stopPropagation(); + if(error){ + return; + } + setStep(2); + }} + > + + {error && {error}} + + handleInvalid(e, "sign-up.", "validation-username") + } + onInput={handleOnInput} + /> + + + + handleInvalid(e, "sign-up.", "validation-username") + } + onInput={handleOnInput} + /> + + + + handleInvalid(e, "sign-up.", "validation-username") + } + onInput={handleOnInput} + /> + +
+ +
+
+ + +
+ ); + })()} +
+
} + {newUserKeys && step == 2 &&
+
+

+ {_t("onboard.confirm-details")} +

+
+ + {_t("onboard.username")} {username} + + + {_t("onboard.email")} {email} + + + {_t("onboard.referral")} {referral} + + + {_t("onboard.public-active")} {newUserKeys?.activePubkey} + + + {_t("onboard.public-owner")} {newUserKeys?.ownerPubkey} + + + {_t("onboard.public-posting")} {newUserKeys?.postingPubkey} + + + {_t("onboard.public-memo")} {newUserKeys?.memoPubkey} + +
+
+ {_t("onboard.copy-key")} +
+ {accountPassword}... + { + clipboard(accountPassword) + success(_t("onboard.key-copied")) + }}>{copyContent} +
+
+ + {isDownloaded &&
+ {!activeUser ? <> +

{_t("onboard.copy-info-message")}

+
+ {splitUrl(`${window.origin}/onboard-friend/${urlHash}`)}... + { + clipboard(`${window.origin}/onboard-friend/${urlHash}`); + success(_t("onboard.copy-link")) + }}>{copyContent} +
+ : {_t("onboard.click-link")}} +
} +
+
+ } + } + {accountType === "Solana" && <> + + } +
+
);