App-js follow up tasks (#703)
* Bump up yarn.lock * Clean up examples, added jacos example to storage examples * Fixed Dropdown * Update package.json * resize wip * css resize fix * Add line-break after code in exec to prevent catch from being commented out * Fixed typo in example * Formatting * More formatting * Added missing semicolon * Update to use UI signer * Make visible on sidebar * Combine some info from samples * blockPeriod.toNumber() (oops, dropped that, reinstate) * lifecycle bugfix for duplicate comments * Kicked Intro, moved info to WRAPPER * removed leftover <Intro /> import
This commit is contained in:
parent
c57fee1494
commit
a69548866b
@ -33,23 +33,13 @@ export default class Editor extends React.PureComponent<Props> {
|
||||
this.id = `flask-${Date.now()}`;
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps (nextProps: Props, prevState: State) {
|
||||
if (nextProps.snippet !== prevState.snippet) {
|
||||
return {
|
||||
snippet: nextProps.snippet
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this.editor = new CodeFlask(`#${this.id}`, {
|
||||
language: 'js',
|
||||
lineNumbers: true
|
||||
});
|
||||
const { editor, props: { code, onEdit } } = this;
|
||||
|
||||
editor.updateCode(`${WRAPPING}${code}`);
|
||||
const { editor, props: { code, onEdit } } = this;
|
||||
|
||||
editor.onUpdate((code: string) => {
|
||||
onEdit(code);
|
||||
@ -68,6 +58,7 @@ export default class Editor extends React.PureComponent<Props> {
|
||||
if (snippet !== this.state.snippet) {
|
||||
onEdit(code);
|
||||
this.editor.updateCode(`${WRAPPING}${code}`);
|
||||
this.setState({ snippet });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/app-js authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { I18nProps } from '@polkadot/ui-app/types';
|
||||
|
||||
import { Trans } from 'react-i18next';
|
||||
import React from 'react';
|
||||
|
||||
import translate from './translate';
|
||||
|
||||
type Props = I18nProps;
|
||||
|
||||
const Intro = (props: Props) => {
|
||||
const { t } = props;
|
||||
return (
|
||||
<Trans i18nKey='appJsIntro'>
|
||||
<p>All code is wrapped within an async closure, allowing access to
|
||||
<a href='https://www.npmjs.com/package/@polkadot/api' title={t('Go to module page on npmjs.com')} target='_blank'>@polkadot/api</a>,
|
||||
<a href='https://www.npmjs.com/package/@polkadot/util-crypto' title={t('Go to module page on npmjs.com')} target='_blank'>@polkadot/util-crypto</a>,
|
||||
<a href='https://www.npmjs.com/package/@polkadot/ui-keyring' title={t('Go to module page on npmjs.com')} target='_blank'>@polkadot/ui-keyring</a> and
|
||||
<a href='https://www.npmjs.com/package/@polkadot/util' title={t('Go to module page on npmjs.com')} target='_blank'>@polkadot/util</a>.
|
||||
</p>
|
||||
</Trans>
|
||||
);
|
||||
};
|
||||
export default translate(Intro);
|
||||
@ -9,15 +9,6 @@
|
||||
padding: 1rem 0 0;
|
||||
}
|
||||
|
||||
.js--Content {
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
flex-grow: 2;
|
||||
height: 100%;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.js--Dropdown {
|
||||
margin-right: 100px;
|
||||
position: relative;
|
||||
@ -30,6 +21,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.js--Content {
|
||||
align-content: stretch;
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.js--Editor,
|
||||
.js--Output {
|
||||
min-width: 200px;
|
||||
@ -42,34 +42,64 @@
|
||||
}
|
||||
}
|
||||
|
||||
.js--Editor {
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
resize: horizontal;
|
||||
width: 60%;
|
||||
|
||||
textarea {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.codeflask--has-line-numbers {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.codeflask--has-line-numbers .codeflask__flatten {
|
||||
font-size: 12px;
|
||||
height: 99.99%;
|
||||
line-height: 18px;
|
||||
min-width: calc(100% - 40px);
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.codeflask__lines {
|
||||
background: #fafafa;
|
||||
line-height: 18px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
&::after {
|
||||
bottom: 0;
|
||||
content: '↔';
|
||||
cursor: col-resize;
|
||||
font-size: 20px;
|
||||
height: 20px;
|
||||
line-height: 18px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 22px;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.js--Output {
|
||||
background-color: #4e4e4e;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
font-variant-ligatures: common-ligatures;
|
||||
line-height: 18px;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
resize: horizontal;
|
||||
width: 40%;
|
||||
|
||||
&::after {
|
||||
font-size: 24px;
|
||||
line-height: 24px;
|
||||
content: '↔';
|
||||
cursor: col-resize;
|
||||
z-index: 1;
|
||||
width: 22px;
|
||||
height: 30px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.logs-wrapper {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
@ -95,26 +125,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.js--Editor {
|
||||
flex-grow: 2;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
|
||||
textarea {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.codeflask--has-line-numbers .codeflask__flatten {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
min-width: calc(100% - 40px);
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.codeflask__lines {
|
||||
background: #fafafa;
|
||||
line-height: 18px;
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,6 @@ import './index.css';
|
||||
import snippets from './snippets';
|
||||
import translate from './translate';
|
||||
|
||||
import Intro from './Intro';
|
||||
import Editor from './Editor';
|
||||
import Output from './Output';
|
||||
|
||||
@ -43,17 +42,23 @@ type State = {
|
||||
snippet: string
|
||||
};
|
||||
|
||||
const local = snippets.find(obj => obj.value === localStorage.getItem('app-js-snippet'));
|
||||
|
||||
class App extends React.PureComponent<Props, State> {
|
||||
injected: Injected | null = null;
|
||||
state: State = {
|
||||
code: local ? local.code : snippets[0].code,
|
||||
code: '',
|
||||
isRunning: false,
|
||||
logs: [],
|
||||
snippet: local ? local.value : snippets[0].value
|
||||
snippet: ''
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
const local = snippets.find(obj => obj.value === localStorage.getItem('app-js-snippet'));
|
||||
this.setState({
|
||||
code: local ? local.code : snippets[0].code,
|
||||
snippet: local ? local.value : snippets[0].value
|
||||
});
|
||||
}
|
||||
|
||||
render () {
|
||||
const { code, isRunning, logs, snippet } = this.state;
|
||||
const { t } = this.props;
|
||||
@ -62,7 +67,6 @@ class App extends React.PureComponent<Props, State> {
|
||||
return (
|
||||
<main className='js--App'>
|
||||
<header className='container'>
|
||||
<Intro />
|
||||
<Dropdown
|
||||
className='js--Dropdown'
|
||||
onChange={this.selectExample}
|
||||
@ -133,7 +137,7 @@ class App extends React.PureComponent<Props, State> {
|
||||
|
||||
// squash into a single line so exceptions (with linenumbers) maps to the same line/origin
|
||||
// as we have in the editor view (TODO: Make the console.error here actually return the full stack)
|
||||
const exec = `(async ({${Object.keys(this.injected).join(',')}}) => { try { ${code} } catch (error) { console.error(error); } })(injected);`;
|
||||
const exec = `(async ({${Object.keys(this.injected).join(',')}}) => { try { ${code} \n } catch (error) { console.error(error); } })(injected);`;
|
||||
|
||||
new Function('injected', exec)(this.injected);
|
||||
|
||||
|
||||
@ -6,26 +6,21 @@ import { Snippet } from '@polkadot/app-js/types';
|
||||
|
||||
export const extrinsicMakeTransfer: Snippet = {
|
||||
value: 'extrinsicMakeTransfer',
|
||||
text: 'Extrinsics - Make transfer and listen to events',
|
||||
text: 'Make transfer and listen to events',
|
||||
label: { color: 'grey', children: 'Extrinsics', size: 'tiny' },
|
||||
code: `// Make a transfer from Alice to Bob and listen to system events.
|
||||
// You need to be connected to a development chain for this example to work.
|
||||
const ALICE = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ';
|
||||
const BOB = '5Gw3s7q4QLkSWwknsiPtjujPv3XM4Trxi5d4PgKMMk3gfGTE';
|
||||
|
||||
// Get a random number between 1 and 100000
|
||||
const randomAmount = Math.floor((Math.random() * 100000) + 1);
|
||||
|
||||
// Get Alice seed
|
||||
const ALICE_SEED = 'Alice'.padEnd(32, ' ');
|
||||
|
||||
// Add Alice to our keyring (with the known seed for the account)
|
||||
const alice = keyring.addFromSeed(util.stringToU8a(ALICE_SEED));
|
||||
|
||||
// Create a extrinsic, transferring randomAmount units to Bob.
|
||||
const transfer = api.tx.balances.transfer(BOB, randomAmount);
|
||||
|
||||
// Sign and Send the transaction
|
||||
transfer.signAndSend(alice, ({ events = [], status, type }) => {
|
||||
transfer.signAndSend(ALICE, ({ events = [], status, type }) => {
|
||||
if (type === 'Finalised') {
|
||||
console.log('Successful transfer of ' + randomAmount + ' with hash ' + status.asFinalised.toHex());
|
||||
} else {
|
||||
|
||||
@ -13,9 +13,9 @@ import {
|
||||
|
||||
import {
|
||||
storageGetInfo,
|
||||
storageGetBalanceInformation,
|
||||
storageSystemEvents,
|
||||
storageListenToBalanceChange
|
||||
storageListenToBalanceChange,
|
||||
storageRetrieveInfoOnQueryKeys
|
||||
} from './storage-examples';
|
||||
|
||||
import { extrinsicMakeTransfer } from './extrinsics-examples';
|
||||
@ -26,9 +26,9 @@ const snippets: Array<Snippet> = [
|
||||
rpcQueryState,
|
||||
rpcSysthemInfo,
|
||||
storageGetInfo,
|
||||
storageGetBalanceInformation,
|
||||
storageSystemEvents,
|
||||
storageListenToBalanceChange,
|
||||
storageRetrieveInfoOnQueryKeys,
|
||||
extrinsicMakeTransfer
|
||||
];
|
||||
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/app-123code authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export default `// This example set shows how to make queries and retrieve info on query keys
|
||||
const ALICE = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ';
|
||||
|
||||
// retrieve the balance, once-off at the latest block
|
||||
const currBalance = await api.query.balances.freeBalance(ALICE);
|
||||
|
||||
console.log('Alice has a current balance of', currBalance);
|
||||
|
||||
// retrieve balance updates with an optional value callback
|
||||
const balanceUnsub = await api.query.balances.freeBalance(ALICE, (balance) => {
|
||||
console.log('Alice has an updated balance of', balance);
|
||||
});
|
||||
|
||||
// retrieve the balance at a block hash in the past
|
||||
const header = await api.rpc.chain.getHeader();
|
||||
const prevHash = await api.rpc.chain.getBlockHash(header.blockNumber.subn(42));
|
||||
const prevBalance = await api.query.balances.freeBalance.at(prevHash, ALICE);
|
||||
|
||||
console.log('Alice had a balance of', prevBalance, '(42 blocks ago)');
|
||||
|
||||
// useful in some situations - the value hash and storage entry size
|
||||
const currHash = await api.query.balanace.freeBalance.hash(ALICE);
|
||||
const currSize = await api.query.balanace.freeBalance.size(ALICE);
|
||||
|
||||
console.log('Alice balance entry has a value hash of', currHash, 'with a size of', currSize);`;
|
||||
@ -36,7 +36,7 @@ const unsub = await api.rpc.chain.subscribeNewHead((header) => {
|
||||
|
||||
export const rpcQueryState: Snippet = {
|
||||
value: 'rpcQueryState',
|
||||
text: 'Get authoring iformation',
|
||||
text: 'Get state metadata',
|
||||
label: { color: 'pink', children: 'RPC', size: 'tiny' },
|
||||
code: `// subscribe to new headers, printing the full info for 5 Blocks
|
||||
const unsub = await api.rpc.state.getMetadata(({ magicNumber, metadata }) => {
|
||||
|
||||
@ -9,18 +9,20 @@ export const storageGetInfo: Snippet = {
|
||||
text: 'Get chain state information',
|
||||
label: { color: 'blue', children: 'Storage', size: 'tiny' },
|
||||
code: `// Get chain state information
|
||||
const ALICE = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ';
|
||||
// Make our basic chain state/storage queries, all in one go
|
||||
const [accountNonce, blockPeriod, validators] = await Promise.all([
|
||||
api.query.system.accountNonce(ALICE),
|
||||
const [blockPeriod, validators, transferFee] = await Promise.all([
|
||||
api.query.timestamp.blockPeriod(),
|
||||
api.query.session.validators()
|
||||
api.query.session.validators(),
|
||||
api.query.balances.transferFee()
|
||||
]);
|
||||
console.log('Account: ' + ALICE + ' -- AccountNonce: ' + accountNonce);
|
||||
|
||||
console.log('blockPeriod in seconds: ' + blockPeriod.toNumber());
|
||||
console.log('transferFee: ', transferFee);
|
||||
|
||||
if (validators && validators.length > 0) {
|
||||
// Retrieve the balances for all validators
|
||||
console.log('Validators');
|
||||
|
||||
const validatorBalances = await Promise.all(
|
||||
validators.map(authorityId => api.query.balances.freeBalance(authorityId))
|
||||
);
|
||||
@ -33,22 +35,6 @@ if (validators && validators.length > 0) {
|
||||
`
|
||||
};
|
||||
|
||||
export const storageGetBalanceInformation: Snippet = {
|
||||
value: 'storageGetBalanceInformation',
|
||||
text: 'Get current transfer fee',
|
||||
label: { color: 'blue', children: 'Storage', size: 'tiny' },
|
||||
code: `// Listen to the total transfer fee for 5 Blocks
|
||||
let count = 0;
|
||||
const unsub = await api.query.balances.transferFee((sum) => {
|
||||
console.log('Transfer fee: '+ sum);
|
||||
|
||||
if (++count === 5) {
|
||||
console.log('listened to 5 blocks, unsubscribing');
|
||||
unsub();
|
||||
}
|
||||
});`
|
||||
};
|
||||
|
||||
export const storageSystemEvents: Snippet = {
|
||||
value: 'storageSystemEvents',
|
||||
text: 'Listen to system events',
|
||||
@ -96,3 +82,34 @@ api.query.balances.freeBalance(ALICE, (balance) => {
|
||||
}
|
||||
});`
|
||||
};
|
||||
|
||||
export const storageRetrieveInfoOnQueryKeys: Snippet = {
|
||||
value: 'storageRetrieveInfoOnQueryKeys',
|
||||
text: 'Retrieve Info on query keys',
|
||||
label: { color: 'blue', children: 'Storage', size: 'tiny' },
|
||||
code: `// This example set shows how to make queries and retrieve info on query keys
|
||||
const ALICE = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ';
|
||||
|
||||
// retrieve the balance, once-off at the latest block
|
||||
const currBalance = await api.query.balances.freeBalance(ALICE);
|
||||
|
||||
console.log('Alice has a current balance of', currBalance);
|
||||
|
||||
// retrieve balance updates with an optional value callback
|
||||
const balanceUnsub = await api.query.balances.freeBalance(ALICE, (balance) => {
|
||||
console.log('Alice has an updated balance of', balance);
|
||||
});
|
||||
|
||||
// retrieve the balance at a block hash in the past
|
||||
const header = await api.rpc.chain.getHeader();
|
||||
const prevHash = await api.rpc.chain.getBlockHash(header.blockNumber.subn(42));
|
||||
const prevBalance = await api.query.balances.freeBalance.at(prevHash, ALICE);
|
||||
|
||||
console.log('Alice had a balance of', prevBalance, '(42 blocks ago)');
|
||||
|
||||
// useful in some situations - the value hash and storage entry size
|
||||
const currHash = await api.query.balances.freeBalance.hash(ALICE);
|
||||
const currSize = await api.query.balances.freeBalance.size(ALICE);
|
||||
|
||||
console.log('Alice balance entry has a value hash of', currHash, 'with a size of', currSize);`
|
||||
};
|
||||
|
||||
@ -6,6 +6,10 @@ export default `// transfer
|
||||
const sender = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ';
|
||||
const recipient = '5GTZEKgRKX2a5hepNjwTBzR5nR6UqtEsMZ4TnL1Yuah1N2Tu';
|
||||
|
||||
const nonce = await api.query.system.accountNonce(ALICE),
|
||||
|
||||
console.log('Current nonce', nonce);
|
||||
|
||||
const unsub = await api.tx.balances
|
||||
.transfer(recipient,12345)
|
||||
.signAndSend(sender, ({ events = [], status, type }) => {
|
||||
|
||||
@ -2,7 +2,8 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export default `// (async ({ api, hashing, keyring, util }) => {
|
||||
export default `// All code is wrapped within an async closure, allowing access to api, hashing, keyring, util.
|
||||
// (async ({ api, hashing, keyring, util }) => {
|
||||
// ... any user code is executed here ...
|
||||
// })();
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@ export default ([
|
||||
{
|
||||
Component: Js,
|
||||
display: {
|
||||
isHidden: true,
|
||||
needsApi: []
|
||||
},
|
||||
i18n: {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user