Skip to content

feat: init register #214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"vue3-lazyload": "^0.3.6"
},
"devDependencies": {
"@hcaptcha/types": "^1.0.3",
"@babel/core": "^7.19.1",
"@babel/eslint-parser": "^7.19.1",
"@playwright/test": "^1.25.2",
Expand Down
1 change: 1 addition & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
Expand Down
133 changes: 132 additions & 1 deletion src/components/register/SignUp.vue
Original file line number Diff line number Diff line change
@@ -1 +1,132 @@
<template>Sign up</template>
<script setup lang="ts">
import { getAccountIdFromPrivateKey } from '@/backend/auth';
import { requestOnboard, waitForFunds } from '@/backend/funder';
import { validateUsernameNEAR } from '@/backend/near';
import { hcaptchaSiteKey } from '@/backend/utilities/config';
import { ValidationError } from '@/errors';
import useLogin from '@/plugins/loginMethods';
import { handleError } from '@/plugins/toast';
import { onMounted, ref } from 'vue';
import ChevronLeft from '../icons/ChevronLeft.vue';

const id = ref('');
const loadingState = ref<`checking_id` | `hcaptcha_loading` | `smart_contract` | `transfer_funds` | null>(null);
const captchaID = ref<string | null>(null);

const props = defineProps<{ privateKey: string }>();

const login = useLogin();

async function handleRegisterID() {
try {
if (!captchaID.value) {
return;
}

loadingState.value = `checking_id`;
id.value = id.value.toLowerCase();
const idValidity = await validateUsernameNEAR(id.value);
if (idValidity.error) {
loadingState.value = null;
throw new ValidationError(idValidity.error);
}
loadingState.value = `hcaptcha_loading`;
const res = await hcaptcha.execute(captchaID.value, { async: true });
// eslint-disable-next-line no-console
console.log(res);
if (!res) {
// eslint-disable-next-line no-console
console.log(`captchares`, res);
loadingState.value = null;
throw new Error(`Issue on captcha`);
}
const accountId = getAccountIdFromPrivateKey(props.privateKey);
loadingState.value = `smart_contract`;
await requestOnboard(res.response, accountId);
loadingState.value = `transfer_funds`;
await waitForFunds(accountId);
loadingState.value = null;
login.verify(props.privateKey);
} catch (error) {
if (typeof error === `string`) {
if (error === `challenge-closed`) {
return;
}
handleError({ message: `Captcha error: ${error}` });
return;
}
// eslint-disable-next-line no-console
console.log(`error`, error);
handleError(error);
} finally {
loadingState.value = null;
}
}

function back() {
localStorage.clear();
location.reload();
}

onMounted(async () => {
const doc = document.getElementById(`hcaptcha`);
if (!doc) {
throw new Error(`Impossible!`);
}
while (true) {
await Promise.resolve();
if (hcaptcha !== undefined && hcaptcha) {
break;
}
}
captchaID.value = hcaptcha.render(doc, {
size: `invisible`,
sitekey: hcaptchaSiteKey,
});
});
</script>

<template>
<article>
<button class="flex items-center mb-10" @click="back">
<div class="bg-gray2 dark:bg-gray5 focus:outline-none rounded-full">
<ChevronLeft />
</div>
<span class="pl-2 text-sm font-semibold dark:text-darkPrimaryText" style="margin-bottom: 2px">
Signup methods
</span>
</button>
<h1 class="text-lightPrimaryText dark:text-gray1 text-4xl font-bold mb-10">Sign up</h1>
<label for="id" class="text-gray5 dark:text-gray3 block pb-1 text-sm font-semibold"
>Pick your Blogchain username</label
>
<input
id="id"
v-model="id"
type="text"
placeholder="Enter a new @id"
class="focus:outline-none focus:border-primary text-primary dark:text-darkPrimaryText bg-gray2 dark:bg-gray7 mt-1 mb-5 w-full rounded-lg px-4 py-3 font-sans font-semibold text-base"
/>
<!-- This is basically a BrandedButton -->
<button
v-if="loadingState === null"
id="hcaptcha"
style="padding: 0.6rem 1.7rem"
class="w-full bg-primary text-lightButtonText focus:outline-none transform rounded-lg font-bold transition duration-500 ease-in-out hover:shadow-lg"
@click="handleRegisterID"
>
<span class="font-sans" style="font-size: 0.95rem"> Sign Up </span>
</button>
<h6 v-else-if="loadingState === 'checking_id'" class="text-primary text-center">Checking ID...</h6>
<h6 v-else-if="loadingState === 'hcaptcha_loading'" class="text-primary text-center">Verifying humanity...</h6>
<h6 v-else-if="loadingState === 'smart_contract'" class="text-primary text-center">Executing smart contract...</h6>
<h6 v-else-if="loadingState === 'transfer_funds'" class="text-primary text-center">Waiting for funds...</h6>
<!-- <div v-show="!hasEnoughFunds()">
<p class="justify-between p-5 font-sans text-sm text-gray7 dark:text-gray3">
Ensure that the NEAR account with ID: "{{ accountId }}" has sufficient funds before signing up.
</p>
<p class="justify-between p-5 font-sans text-sm text-gray7 dark:text-gray3">Available funds: {{ funds }} yN</p>
<BrandedButton :text="`Re-check funds`" class="w-full" :action="() => $emit(`checkFunds`)" />
</div> -->
</article>
</template>
27 changes: 14 additions & 13 deletions src/pages/Register.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { onMounted, ref } from 'vue';
import CapsuleIcon from '@/components/icons/CapsuleIcon.vue';
import RegisterMethods from '@/components/register/RegisterMethods.vue';
import SignUp from '@/components/register/SignUp.vue';
import useLogin, { Status } from '@/plugins/loginMethods';
import useLogin, { ITorusResponse, Status } from '@/plugins/loginMethods';
import router from '@/router';
import { toastError, toastWarning } from '@/plugins/toast';
import { toastError } from '@/plugins/toast';

const isLoading = ref(false);
const step = ref<`registerMethods` | `signUp`>(`registerMethods`);
const isLoading = ref<boolean>(false);
const userInfo = ref<ITorusResponse | null>(null);
const login = useLogin();

onMounted(async () => {
Expand All @@ -18,24 +18,25 @@ onMounted(async () => {
if (userData) {
const res = await login.verify(userData.privateKey);
switch (res) {
case Status.NO_ACCOUNT:
// If no username is found then register...
toastWarning(`looks like you don't have an account`);
return;
case Status.BLOCKED:
// If account is blocked then send to register page...
// If account is blocked then send to home page...
toastError(`Your account has been deactivated or banned`);
router.push(`/home`);
return;
case Status.SUCCESS:
router.push(`/home`);
location.reload();
return;
case Status.NO_ACCOUNT:
userInfo.value = userData;
}
}
isLoading.value = false;
} catch (err) {
console.log(err);
} catch (err: unknown) {
console.error(err);
if (err instanceof Error) {
toastError(err.message);
}
}
});
</script>
Expand All @@ -58,8 +59,8 @@ onMounted(async () => {
</div>
<div v-show="!isLoading" class="flex w-full h-full flex-col justify-center items-center px-14">
<!-- Step 1: Choose Login / register -->
<RegisterMethods v-if="step === `registerMethods`" />
<SignUp v-else-if="step === `signUp`" />
<RegisterMethods v-if="userInfo === null" />
<SignUp v-else :private-key="userInfo.privateKey" />
</div>
</section>
<p class="text-gray5 dark:text-gray3 px-4 py-5 pl-10 text-sm">
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"sourceMap": true,
"baseUrl": ".",
"noUnusedLocals": true,
"types": ["webpack-env"],
"types": ["webpack-env", "@hcaptcha/types"],
"paths": {
"@/*": ["src/*"]
},
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,11 @@
dependencies:
"@hapi/hoek" "^9.0.0"

"@hcaptcha/types@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@hcaptcha/types/-/types-1.0.3.tgz#baf10a4361a45ff1c64862dfb8dc9bbc8292a8fe"
integrity sha512-1mbU6eSGawRrqeahRrOzZo/SVLI6oZ5/azuBpSyVrRRR96CnS3fOVDWfzxpngfxKD0/I9Rwu6c/3ITqD8rXeTQ==

"@humanwhocodes/config-array@^0.11.6":
version "0.11.6"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.6.tgz#6a51d603a3aaf8d4cf45b42b3f2ac9318a4adc4b"
Expand Down