Skip to content

Commit

Permalink
Merge pull request #41 from keypom/ben/trial-accounts
Browse files Browse the repository at this point in the history
Ben/trial accounts
  • Loading branch information
BenKurrek authored Apr 7, 2023
2 parents 29c10f9 + bd2a9e9 commit c46d411
Show file tree
Hide file tree
Showing 38 changed files with 774 additions and 906 deletions.
77 changes: 77 additions & 0 deletions docs-advanced-tutorials/trial-accounts/create-trial-drop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
require('dotenv').config()
const path = require("path");
const homedir = require("os").homedir();
const { readFileSync } = require('fs');
const { keyStores, connect, Account } = require('near-api-js');

const keypom = require("../../lib");
const {
initKeypom,
createTrialAccountDrop
} = keypom

const funderAccountId = 'benjiman.testnet';
const NETWORK_ID = 'testnet';
async function createTrialAccount() {
// Initiate connection to the NEAR blockchain.
const CREDENTIALS_DIR = ".near-credentials";
const credentialsPath = path.join(homedir, CREDENTIALS_DIR);

let keyStore = new keyStores.UnencryptedFileSystemKeyStore(credentialsPath);

let nearConfig = {
networkId: NETWORK_ID,
keyStore: keyStore,
nodeUrl: `https://rpc.${NETWORK_ID}.near.org`,
walletUrl: `https://wallet.${NETWORK_ID}.near.org`,
helperUrl: `https://helper.${NETWORK_ID}.near.org`,
explorerUrl: `https://explorer.${NETWORK_ID}.near.org`,
};

let near = await connect(nearConfig);
const fundingAccount = new Account(near.connection, funderAccountId)

// Initialize the SDK and point it to the custom NEAR object that was created.
await initKeypom({
near,
network: NETWORK_ID
});

// What contracts can the trial account call?
const callableContracts = [
'guest-book.examples.keypom.testnet'
]
// What is the maximum amount of $NEAR that can be attached to a call for each callable contract?
const maxAttachableNEARPerContract = [
'1',
]
// What methods can the trial account call?
const callableMethods = [
['*'],
]

const wasmDirectory = `${require('path').resolve(__dirname, '..')}/trial-accounts/ext-wasm/trial-accounts.wasm`
const {keys} = await createTrialAccountDrop({
account: fundingAccount,
numKeys: 1,
contractBytes: [...readFileSync(wasmDirectory)],
// How much $NEAR should be made available to the trial account when it's created?
startingBalanceNEAR: 2.5,
callableContracts,
callableMethods,
maxAttachableNEARPerContract,
// Once the trial account has spent this much $NEAR, the trial will be over.
trialEndFloorNEAR: 1.25
})

const guestBookInstance = "http://localhost:1234"
console.log(`
Guest-Book App:
${guestBookInstance}/keypom-url#v2.keypom.testnet/${keys.secretKeys[0]}
Good Luck!
`)
}

createTrialAccount();
File renamed without changes.
31 changes: 31 additions & 0 deletions docs-advanced-tutorials/trial-accounts/guest-book/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# Developer note: near.gitignore will be renamed to .gitignore upon project creation
# dependencies
node_modules
/.pnp
.pnp.js

# build
/out
/dist

# keys
/neardev

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
/.cache

npm-debug.log*
yarn-debug.log*
yarn-error.log*
61 changes: 61 additions & 0 deletions docs-advanced-tutorials/trial-accounts/guest-book/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'regenerator-runtime/runtime';
import React, { useState, useEffect } from 'react';
import Form from './components/Form';
import SignIn from './components/SignIn';
import Messages from './components/Messages';

const App = ({ isSignedIn, guestBook, wallet }) => {
const [messages, setMessages] = useState([]);

useEffect(() => {
guestBook.getMessages().then(setMessages);
}, []);

onSubmit = async (e) => {
e.preventDefault();

const { fieldset, message, donation } = e.target.elements;

fieldset.disabled = true;

await guestBook.addMessage(message.value, donation.value)
const messages = await guestBook.getMessages()

setMessages(messages);
message.value = '';
donation.value = '0';
fieldset.disabled = false;
message.focus();
};

const signIn = () => { wallet.signIn() }

const signOut = () => { wallet.signOut() }

return (
<main>
<table>
<tr>
<td><h1>📖 NEAR Guest Book</h1></td>
<td>{ isSignedIn
? <button onClick={signOut}>Log out</button>
: <button onClick={signIn}>Log in</button>
}</td>
</tr>
</table>

<hr />
{ isSignedIn
? <Form onSubmit={onSubmit} currentAccountId={wallet.accountId} />
: <SignIn/>
}

<hr />

{ !!messages.length && <Messages messages={messages}/> }

</main>
);
};

export default App;
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import PropTypes from 'prop-types';

export default function Form({ onSubmit, currentAccountId }) {
return (
<form onSubmit={onSubmit}>
<fieldset id="fieldset">
<p>Sign the guest book, { currentAccountId }!</p>
<p className="highlight">
<label htmlFor="message">Message:</label>
<input
autoComplete="off"
autoFocus
id="message"
required
/>
</p>
<p>
<label htmlFor="donation">Donation (optional):</label>
<input
autoComplete="off"
defaultValue={'0'}
id="donation"
min="0"
step="0.01"
type="number"
/>
<span title="NEAR Tokens"></span>
</p>
<button type="submit">
Sign
</button>
</fieldset>
</form>
);
}

Form.propTypes = {
onSubmit: PropTypes.func.isRequired,
currentUser: PropTypes.shape({
accountId: PropTypes.string.isRequired,
balance: PropTypes.string.isRequired
})
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import PropTypes from 'prop-types';

export default function Messages({ messages }) {
return (
<>
<h2>Messages</h2>
{messages.map((message, i) =>
// TODO: format as cards, add timestamp
<p key={i} className={message.premium ? 'is-premium' : ''}>
<strong>{message.sender}</strong>:<br/>
{message.text}
</p>
)}
</>
);
}

Messages.propTypes = {
messages: PropTypes.array
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';

export default function SignIn() {
return (
<>
<p>
This app demonstrates a key element of NEAR’s UX: once an app has
permission to make calls on behalf of a user (that is, once a user
signs in), the app can make calls to the blockchain for them without
prompting extra confirmation. So you’ll see that if you don’t
include a donation, your message gets posted right to the guest book.
</p>
<p>
But, if you do add a donation, then NEAR will double-check that
you’re ok with sending money to this app.
</p>
<p>
Go ahead and sign in to try it out!
</p>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONTRACT_NAME=guest-book.examples.keypom.testnet
Binary file not shown.
128 changes: 128 additions & 0 deletions docs-advanced-tutorials/trial-accounts/guest-book/global.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
* {
box-sizing: border-box;
}

html {
--bg: #f4f4f4;
--fg: #25282A;
--gray: #888;
--royal: #0072CE;
--blue: #6AD1E3;
--primary: #93b0df;
--secondary: var(--royal);
--tertiary: #FF585D;

background-color: var(--bg);
color: var(--fg);
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;
font-size: calc(.65em + 0.7vw);
line-height: 1.3;

::selection {
background: var(--secondary);
color: var(--bg);
}

@media (prefers-color-scheme: light) {
--bg: #25282A;
--fg: #fff;
--secondary: var(--blue);

::selection {
background: var(--secondary);
color: var(--fg);
}
}
}

body {
margin: 0 auto;
padding: 0 1em;
max-width: 40em;
}

fieldset {
border: none;
margin: 0;
padding: 0;
}

.highlight {
align-items: center;
display: flex;
margin-bottom: 0.5em;
width: 100%;
label {
margin-right: 0.5em;
}
input {
caret-color: var(--secondary);
}
}

label {
color: var(--gray);
}

button, .highlight {
border-radius: 5px;
border-color: var(--primary);
border: 0.1em solid var(--primary);
padding: 0.5em 1em;

&:hover, &:focus, &:focus-within {
border-color: var(--secondary);
}
}

input {
border: none;
flex: 1;
&:read-only {
color: var(--primary)
}
}

input[type="number"] {
text-align: center;
border-bottom: 0.1em solid var(--primary);
margin: 0 1em;
width: 4em;
padding-left: 0.5em;
&:hover, &:focus {
border-color: var(--secondary);
}
}

button, input {
background: transparent;
color: inherit;
cursor: pointer;
font: inherit;
outline: none;
}

button {
position: relative;
transition: top 50ms;
&:hover, &:focus {
top: -1px;
}
background: var(--primary);

&:active {
background: var(--secondary);
border-color: var(--secondary);
top: 1px;
}
}

.is-premium {
border-left: 0.25em solid var(--secondary);
padding-left: 0.25em;
margin-left: -0.5em;
}

table button{
margin-left: 1rem;
}
Loading

0 comments on commit c46d411

Please sign in to comment.