Skip to content

Commit

Permalink
updated frontend with latest examples version
Browse files Browse the repository at this point in the history
  • Loading branch information
gagdiez committed Sep 20, 2022
1 parent 6b2cd65 commit 982d4f7
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 65 deletions.
10 changes: 5 additions & 5 deletions templates/frontend/react/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import './assets/global.css';
import { EducationalText, SignInPrompt, SignOutButton } from './ui-components';


export default function App({ isSignedIn, contract, wallet }) {
export default function App({ isSignedIn, helloNEAR, wallet }) {
const [valueFromBlockchain, setValueFromBlockchain] = React.useState();

const [uiPleaseWait, setUiPleaseWait] = React.useState(true);

// Get blockchian state once on component load
React.useEffect(() => {
contract.getGreeting()
helloNEAR.getGreeting()
.then(setValueFromBlockchain)
.catch(alert)
.finally(() => {
Expand All @@ -31,8 +31,8 @@ export default function App({ isSignedIn, contract, wallet }) {
e.preventDefault();
setUiPleaseWait(true);
const { greetingInput } = e.target.elements;
contract.setGreeting(greetingInput.value)
.then(async () => {return contract.getGreeting();})
helloNEAR.setGreeting(greetingInput.value)
.then(async () => {return helloNEAR.getGreeting();})
.then(setValueFromBlockchain)
.finally(() => {
setUiPleaseWait(false);
Expand All @@ -44,7 +44,7 @@ export default function App({ isSignedIn, contract, wallet }) {
<SignOutButton accountId={wallet.accountId} onClick={() => wallet.signOut()}/>
<main className={uiPleaseWait ? 'please-wait' : ''}>
<h1>
The contract says: <span className="greeting">{valueFromBlockchain}</span>
The helloNEAR says: <span className="greeting">{valueFromBlockchain}</span>
</h1>
<form onSubmit={changeGreeting} className="change">
<label>Change greeting:</label>
Expand Down
34 changes: 19 additions & 15 deletions templates/frontend/react/index.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
// React
import React from 'react';
import { createRoot } from 'react-dom/client';
import ReactDOM from 'react-dom';
import App from './App';

// NEAR
import { HelloNEAR } from './near-interface';
import { Wallet } from './near-wallet';
import { Contract } from './near-interface';

const reactRoot = createRoot(document.querySelector('#root'));
// When creating the wallet you can optionally ask to create an access key
// Having the key enables to call non-payable methods without interrupting the user to sign
const wallet = new Wallet({ createAccessKeyFor: process.env.CONTRACT_NAME })

// create the Wallet and the Contract
const contractId = process.env.CONTRACT_NAME;
const wallet = new Wallet({contractId: contractId});
const contract = new Contract({wallet: wallet});
// Abstract the logic of interacting with the contract to simplify your flow
const helloNEAR = new HelloNEAR({ contractId: process.env.CONTRACT_NAME, walletToUse: wallet });

window.onload = wallet.startUp()
.then((isSignedIn) => {
reactRoot.render(<App isSignedIn={isSignedIn} contract={contract} wallet={wallet} />);
})
.catch(e => {
reactRoot.render(<div style={{color: 'red'}}>Error: <code>{e.message}</code></div>);
console.error(e);
});
// Setup on page load
window.onload = async () => {
const isSignedIn = await wallet.startUp()

ReactDOM.render(
<App isSignedIn={isSignedIn} helloNEAR={helloNEAR} wallet={wallet} />,
document.getElementById('root')
);
}
1 change: 0 additions & 1 deletion templates/frontend/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"@babel/preset-env": "^7.18.2",
"@babel/preset-react": "^7.17.12",
"@types/node": "^18.6.2",
"ava": "^4.2.0",
"react-test-renderer": "^18.1.0",
"ts-node": "^10.8.0",
"typescript": "^4.7.2",
Expand Down
19 changes: 10 additions & 9 deletions templates/frontend/shared/near-interface.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
export class Contract{
wallet;
/* Talking with a contract often involves transforming data, we recommend you to encapsulate that logic into a class */

constructor({wallet}){
this.wallet = wallet;
export class HelloNEAR {
constructor({ contractId, walletToUse }) {
this.contractId = contractId;
this.wallet = walletToUse;
}

async getGreeting(){
return await this.wallet.viewMethod({method: 'get_greeting'});
async getGreeting() {
return await this.wallet.viewMethod({ contractId: this.contractId, method: 'get_greeting' });
}
async setGreeting(greeting){
return await this.wallet.callMethod({method: 'set_greeting', args:{message: greeting}});

async setGreeting(greeting) {
return await this.wallet.callMethod({ contractId: this.contractId, method: 'set_greeting', args: { message: greeting } });
}
}
37 changes: 20 additions & 17 deletions templates/frontend/shared/near-wallet.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* A helper file that simplifies using the wallet selector */

// near api js
import { providers } from 'near-api-js';

Expand All @@ -19,28 +21,31 @@ const NO_DEPOSIT = '0';
export class Wallet {
walletSelector;
wallet;
accountId;
contractId;

constructor({contractId}){
this.contractId = contractId;
network;
createAccessKeyFor;

constructor({ createAccessKeyFor = undefined, network = 'testnet' }) {
// Login to a wallet passing a contractId will create a local
// key, so the user skips signing non-payable transactions.
// Omitting the accountId will result in the user being
// asked to sign all transactions.
this.createAccessKeyFor = createAccessKeyFor
this.network = 'testnet'
}

// To be called when the website loads
async startUp() {
this.walletSelector = await setupWalletSelector({
network: 'testnet',
network: this.network,
modules: [setupMyNearWallet({ iconUrl: MyNearIconUrl }),
setupLedger({ iconUrl: LedgerIconUrl })],
setupLedger({ iconUrl: LedgerIconUrl })],
});

const isSignedIn = this.walletSelector.isSignedIn();

if (isSignedIn) {
const { accounts } = this.walletSelector.store.getState();

this.wallet = await this.walletSelector.wallet();
this.accountId = accounts[0].accountId;
this.accountId = this.walletSelector.store.getState().accounts[0].accountId;
}

return isSignedIn;
Expand All @@ -49,19 +54,19 @@ export class Wallet {
// Sign-in method
signIn() {
const description = 'Please select a wallet to sign in.';
const modal = setupModal(this.walletSelector, { contractId: this.contractId, description });
const modal = setupModal(this.walletSelector, { contractId: this.createAccessKeyFor, description });
modal.show();
}

// Sign-out method
signOut() {
this.wallet.signOut();
this.wallet = this.accountId = this.contractId = null;
this.wallet = this.accountId = this.createAccessKeyFor = null;
window.location.replace(window.location.origin + window.location.pathname);
}

// Make a read-only call to retrieve information from the network
async viewMethod({ contractId = this.contractId, method, args = {} }) {
async viewMethod({ contractId, method, args = {} }) {
const { network } = this.walletSelector.options;
const provider = new providers.JsonRpcProvider({ url: network.nodeUrl });

Expand All @@ -76,12 +81,10 @@ export class Wallet {
}

// Call a method that changes the contract's state
async callMethod({ contractId = this.contractId, method, args = {}, gas = THIRTY_TGAS, deposit = NO_DEPOSIT }) {
const { accountId } = this.walletSelector.store.getState().accounts[0];

async callMethod({ contractId, method, args = {}, gas = THIRTY_TGAS, deposit = NO_DEPOSIT }) {
// Sign a transaction with the "FunctionCall" action
return await this.wallet.signAndSendTransaction({
signerId: accountId,
signerId: this.accountId,
receiverId: contractId,
actions: [
{
Expand Down
12 changes: 7 additions & 5 deletions templates/frontend/vanilla/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,20 @@ <h1>
</p>
<ol>
<li>
Look in <code>./frontend/index.js</code> – you'll see <code>getGreeting</code>
and <code>setGreeting</code> being called on <code>contract</code>.
Look in <code>index.js</code> and <code>near-api.js</code> – you'll see <code>get_greeting</code>
and <code>set_greeting</code> being called on <code>contract</code>.
What's this?
</li>
<li>
Ultimately, this <code>contract</code> code is defined in
<code>./contract</code> – this is the source code for your
<code>assembly/index.ts</code> – this is the source code for your
<a target="_blank" href="https://docs.near.org/docs/develop/contracts/overview">smart contract</a>.
</li>
<li>
When you run <code>npm run dev</code>, the contract's code gets deployed
to the NEAR testnet. You can see how this happens by looking in <code>package.json</code>.
When you run <code>npm run dev</code>, the code in
<code>assembly/index.ts</code> gets deployed to the NEAR testnet. You
can see how this happens by looking in <code>package.json</code> at the
<code>scripts</code> section to find the <code>dev</code> command.
</li>
</ol>
<hr>
Expand Down
21 changes: 12 additions & 9 deletions templates/frontend/vanilla/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import 'regenerator-runtime/runtime';
import { Contract } from './near-interface';
import { Wallet } from './near-wallet';
import { HelloNEAR } from './near-interface';

// create the Wallet and the Contract
const wallet = new Wallet({contractId: process.env.CONTRACT_NAME});
const contract = new Contract({wallet: wallet});
// When creating the wallet you can optionally ask to create an access key
// Having the key enables to call non-payable methods without interrupting the user to sign
const wallet = new Wallet({ createAccessKeyFor: process.env.CONTRACT_NAME })

// Abstract the logic of interacting with the contract to simplify your flow
const helloNEAR = new HelloNEAR({ contractId: process.env.CONTRACT_NAME, walletToUse: wallet });

// Setup on page load
window.onload = async () => {
let isSignedIn = await wallet.startUp();

if(isSignedIn){
if (isSignedIn) {
signedInFlow();
}else{
} else {
signedOutFlow();
}

Expand All @@ -22,7 +25,7 @@ window.onload = async () => {
// Button clicks
document.querySelector('form').onsubmit = doUserAction;
document.querySelector('#sign-in-button').onclick = () => { wallet.signIn(); };
document.querySelector('#sign-out-button').onclick = () => { wallet.signOut(); };
document.querySelector('#sign-out-button').onclick = () => { wallet.signOut(); };

// Take the new greeting and send it to the contract
async function doUserAction(event) {
Expand All @@ -32,7 +35,7 @@ async function doUserAction(event) {
document.querySelector('#signed-in-flow main')
.classList.add('please-wait');

await contract.setGreeting(greeting.value);
await helloNEAR.setGreeting(greeting.value);

// ===== Fetch the data from the blockchain =====
await fetchGreeting();
Expand All @@ -42,7 +45,7 @@ async function doUserAction(event) {

// Get greeting from the contract on chain
async function fetchGreeting() {
const currentGreeting = await contract.getGreeting();
const currentGreeting = await helloNEAR.getGreeting();

document.querySelectorAll('[data-behavior=greeting]').forEach(el => {
el.innerText = currentGreeting;
Expand Down
9 changes: 5 additions & 4 deletions templates/frontend/vanilla/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"build": "parcel build index.html --public-url ./"
},
"devDependencies": {
"env-cmd": "^10.1.0",
"events": "^3.3.0",
"nodemon": "^2.0.16",
"parcel": "^2.6.0",
"process": "^0.11.10",
"env-cmd": "^10.1.0"
"parcel": "^2.7.0",
"process": "^0.11.10"
},
"dependencies": {
"@near-wallet-selector/core": "^7.0.0",
Expand All @@ -26,4 +27,4 @@
"@near-wallet-selector/wallet-connect": "^7.0.0",
"near-api-js": "^0.44.2"
}
}
}

0 comments on commit 982d4f7

Please sign in to comment.