Skip to content

Commit

Permalink
Merge pull request #4 from vgrichina/web4-login
Browse files Browse the repository at this point in the history
Switch to login and submit transactions via web4
  • Loading branch information
evgenykuzyakov authored Jun 18, 2024
2 parents 852bee9 + bad9136 commit 3da4133
Show file tree
Hide file tree
Showing 7 changed files with 3,614 additions and 3,086 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"chartjs-adapter-moment": "^1.0.0",
"collections": "^5.1.12",
"error-polyfill": "^0.1.2",
"js-cookie": "^3.0.5",
"local-storage": "^2.0.0",
"moment": "^2.29.1",
"near-api-js": "^0.43.1",
Expand Down Expand Up @@ -63,6 +64,7 @@
},
"devDependencies": {
"prettier": "^2.2.1",
"web4-deploy": "^0.7.0"
"web4-deploy": "^0.7.1",
"web4-near": "^0.5.0"
}
}
68 changes: 29 additions & 39 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useCallback, useEffect, useState } from "react";
import Cookies from 'js-cookie'
import "error-polyfill";
import "bootstrap-icons/font/bootstrap-icons.css";
import "bootstrap/dist/js/bootstrap.bundle";
import "./App.scss";
import { BrowserRouter as Router, Link, Route, Switch } from "react-router-dom";
import { NearConfig, TGas, useNearPromise } from "./data/near";
import { TGas, useNearPromise } from "./data/near";
import ArticlePage from "./pages/ArticlePage";
import HistoryPage from "./pages/HistoryPage";
import { OneNear } from "./data/utils";
Expand All @@ -16,46 +17,30 @@ import AuthorPage from "./pages/AuthorPage";

export const refreshAllowanceObj = {};

const WEB4_ACCOUNT_ID = "web4_account_id";

function App(props) {
const signedIn = !!Cookies.get(WEB4_ACCOUNT_ID);
const signedAccountId = Cookies.get(WEB4_ACCOUNT_ID);
const [connected, setConnected] = useState(false);
const [signedIn, setSignedIn] = useState(false);
const [signedAccountId, setSignedAccountId] = useState(null);
const [redirectUrl, setRedirectUrl] = useState(null);

const _near = useNearPromise();
const account = useAccount();

const requestSignIn = useCallback(
async (e) => {
e && e.preventDefault();
const appTitle = "wiki";
const near = await _near;

await near.walletConnection.requestSignIn(
NearConfig.contractName,
appTitle
);
return false;
},
[_near]
);
// TODO: Obtain contractId elsewhere
const contractId = account?.near?.contract.contractId;

const logOut = useCallback(async () => {
const near = await _near;
near.walletConnection.signOut();
near.accountId = null;
setSignedIn(false);
setSignedAccountId(null);
}, [_near]);
const requestSignIn = useCallback((e) => {
setRedirectUrl('/web4/login');
}, []);

const donate = async (e) => {
e.preventDefault();
await account.near.contract.donate(
{},
TGas.mul(10).toFixed(),
OneNear.toFixed()
);
};
const logOut = useCallback(() => {
// TODO: Is anything else needed here like clearing cookies?
setRedirectUrl('/web4/logout');
}, []);

// TODO: Check if this still works (probably just need to be handled by web4)
const refreshAllowance = useCallback(async () => {
alert(
"You're out of access key allowance. Need sign in again to refresh it"
Expand All @@ -67,8 +52,6 @@ function App(props) {

useEffect(() => {
_near.then((near) => {
setSignedIn(!!near.accountId);
setSignedAccountId(near.accountId);
setConnected(true);
});
}, [_near]);
Expand All @@ -91,9 +74,11 @@ function App(props) {
</div>
) : signedIn ? (
<div>
<button className="btn btn-outline-light me-2" onClick={donate}>
Donate 1 NEAR for storage
</button>
<form action={`/web4/contract/${contractId}/donate`} method="POST" style={{ display: "inline" }}>
<input type="hidden" name="web4_gas" value={TGas.mul(10).toFixed()} />
<input type="hidden" name="web4_deposit" value={OneNear.toFixed()} />
<button className="btn btn-outline-light me-2" type="submit">Donate 1 NEAR for storage</button>
</form>

<button className="btn btn-outline-light" onClick={() => logOut()}>
Sign out <SocialAccount accountId={signedAccountId} />
Expand All @@ -105,11 +90,16 @@ function App(props) {
className="btn btn-outline-light"
onClick={(e) => requestSignIn(e)}
>
Sign in with NEAR Wallet
Sign in with NEAR
</button>
</div>
);

if (redirectUrl) {
window.location.href = redirectUrl;
return <div>Redirecting...</div>;
}

return (
<div className="App">
<Router basename={process.env.PUBLIC_URL}>
Expand Down Expand Up @@ -160,7 +150,7 @@ function App(props) {
</Link>
</li>
</ul>
<form className="d-flex">{header}</form>
<div className="d-flex">{header}</div>
</div>
</div>
</nav>
Expand Down
17 changes: 9 additions & 8 deletions src/components/Article/EditArticle.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { TGas } from "../../data/near";
import Editor from "react-markdown-editor-lite";
import "react-markdown-editor-lite/lib/index.css";
import { Markdown } from "./Markdown";
import { postJson } from "../../data/fetch-json";

const defaultBody = (articleId) => `# ${articleId}
Expand Down Expand Up @@ -46,14 +47,14 @@ export default function EditArticle(props) {
const postArticle = async () => {
setLoading(true);

await account.near.contract.post_article(
{
article_id: articleId,
body,
navigation_id: navigationId !== "" ? navigationId : null,
},
TGas.mul(75).toFixed()
);
// TODO: Pass contractId without using account.near
const contractId = account.near.contract.contractId;
await postJson(`/web4/contract/${contractId}/post_article`, {
article_id: articleId,
body,
navigation_id: navigationId !== "" ? navigationId : null,
web4_gas: TGas.mul(75).toFixed(),
});

const newArticle = {
body,
Expand Down
25 changes: 25 additions & 0 deletions src/data/fetch-json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
async function sendJson({ method, url, json }) {
const res = await fetch(url, {
method: method,
body: method !== 'GET' ? JSON.stringify(json) : undefined,
headers: { 'content-type': 'application/json; charset=utf-8' }
});

if (!res.ok) {
const err = new Error(`HTTP error: ${res.status} ${res.statusText}`);
err.data = await res.text();
}

if (res.status === 204) {
// No Content
return null;
}
}

export async function getJson(url) {
return await sendJson({ method: 'GET', url });
}

export async function postJson(url, json) {
return await sendJson({ method: 'POST', url, json });
}
10 changes: 4 additions & 6 deletions src/data/near.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as nearAPI from "near-api-js";
import Cookies from "js-cookie";
import { singletonHook } from "react-singleton-hook";
import Big from "big.js";
import { refreshAllowanceObj } from "../App";
Expand Down Expand Up @@ -86,12 +87,9 @@ async function _initNear() {
_near.keyStore = keyStore;
_near.nearConnection = nearConnection;

_near.walletConnection = new nearAPI.WalletConnection(
nearConnection,
NearConfig.contractName
);
_near.accountId = _near.walletConnection.getAccountId();
_near.account = _near.walletConnection.account();
// TODO: This is a hack, move everything to use web4 directly via REST API
_near.accountId = Cookies.get('web4_account_id');
_near.account = await nearConnection.account(_near.accountId);

_near.contract = wrapContract(_near.account, NearConfig.contractName, {
viewMethods: [
Expand Down
14 changes: 14 additions & 0 deletions src/setupProxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const web4 = require('web4-near')

module.exports = function (app) {
// Proxy to web4 gateway when the path starts with /web4
const web4Callback = web4.callback();
app.use((req, res, next) => {
if (req.url.startsWith('/web4')) {
web4Callback(req, res, next);
return;
}

next();
});
}
Loading

0 comments on commit 3da4133

Please sign in to comment.