Sd 668 app console (#684)

* [app-js] fixed copyright

* [app-js] css fixes

* [app-js] Add api to window object

* Make CSS columns resizable (FF & Chrome)

* Window Interface export

* formatting

* Make columns responsive, added Dropdown

* Added code snippets

* Strip down output to functional component

* removed component state, removed onEdit, update on select

* Editor styling

* Added snippets and local storage

* output formatting

* Example dummies

* Cleanup & examples

* Added util & keyring @polkadot modules to window object

* Moved intro to component to make it translatable

* Added more RPC examples

* small fix

* WIP exaples

* Styles for resizer, fixed flex overflow misbehaviour

* remove code from snippets for options,

* Added labels to dropdown

* Examples

* More examples and removed deprecated examples

* Added labels to dropdown -> missing type decl.

* correst link to ui-keyring package

* Make tslint happy

* Pull api clone/disconnect into sd-668 (#686)

* JS playground & console (start something...)

* It runs...

* WIP

* Use codeflask

* Highlights

* Small updates, console v0.1 is ok to play with

* Bump

* Only shadow, no border (article)

* Allow API to be disposed of between runs

* Clone and disconnect API

* Move id generation (no need for constructor)

* Small updates

* Small type adjustments

* smaller fixes after code review

* updated yarn.lock

* move options calculation out of return

* Remove exposure of api to window object

* Expand JS console logging (#691)

* Expand JS console logging

* Log extrinsics directly

* switch to getDerivedStateFromProps()

* roll back ts versions

* react-i18next rollback to 9.0.2

* Lock  react-i18next to 9.0.2
This commit is contained in:
Stefanie Doll 2019-02-11 18:02:34 +01:00 committed by GitHub
parent e3ac5dbc3d
commit 061f346fd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1687 additions and 1216 deletions

View File

@ -1,4 +1,4 @@
// Copyright 2017-2019 @polkadot/app-123code authors & contributors
// 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.
@ -7,74 +7,79 @@ import { BareProps } from '@polkadot/ui-app/types';
import React from 'react';
import CodeFlask from 'codeflask';
import DEFAULT_CODE from './snippets/newHead';
import WRAPPING from './snippets/wrapping';
type Props = BareProps & {
children?: React.ReactNode,
onEdit: (code: string) => void
};
type State = {
code: string
code: string,
onEdit: (code: string) => void,
snippet: string
};
export default class Editor extends React.PureComponent<Props, State> {
private id: string;
type State = {
snippet: string
};
export default class Editor extends React.PureComponent<Props> {
private id: string = `flask-${Date.now()}`;
private editor: any;
state: State = {
snippet: ''
};
constructor (props: Props) {
super(props);
this.id = `flask-${Date.now()}`;
this.state = {
code: `${WRAPPING}${DEFAULT_CODE}`
};
}
static getDerivedStateFromProps (nextProps: Props, prevState: State) {
if (nextProps.snippet !== prevState.snippet) {
return {
snippet: nextProps.snippet
};
}
return null;
}
componentDidMount () {
const { onEdit } = this.props;
const { code } = this.state;
const editor = new CodeFlask(`#${this.id}`, {
this.editor = new CodeFlask(`#${this.id}`, {
language: 'js',
lineNumbers: true
});
const { editor, props: { code, onEdit } } = this;
editor.updateCode(code);
editor.updateCode(`${WRAPPING}${code}`);
editor.onUpdate((code: string) => {
this.onEdit(code);
onEdit(code);
});
editor.editorRoot.addEventListener('focusin', () => {
editor.onUpdate(this.onEdit);
});
editor.editorRoot.addEventListener('focusout', () => {
editor.onUpdate(() => {
// empty
});
this.editor.onUpdate(onEdit);
});
onEdit(code);
}
render () {
const { children } = this.props;
componentDidUpdate () {
const { code, onEdit, snippet } = this.props;
if (snippet !== this.state.snippet) {
onEdit(code);
this.editor.updateCode(`${WRAPPING}${code}`);
}
}
render () {
return (
<article className='js--Editor'>
<article className='container js--Editor'>
<div
className='container'
className=''
id={this.id}
/>
{children}
{this.props.children}
</article>
);
}
private onEdit = (code: string): void => {
const { onEdit } = this.props;
this.setState({ code }, () => onEdit(code));
}
}

View File

@ -0,0 +1,27 @@
// 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);

View File

@ -1,4 +1,4 @@
// Copyright 2017-2019 @polkadot/app-123code authors & contributors
// 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.
@ -6,33 +6,46 @@ import { BareProps } from '@polkadot/ui-app/types';
import { Log } from './types';
import React from 'react';
import { format } from '@polkadot/util/logger';
import { isError, isNull, isUndefined } from '@polkadot/util';
type Props = BareProps & {
children?: React.ReactNode,
logs: Array<Log>
};
export default class Output extends React.PureComponent<Props> {
render () {
const { children, logs } = this.props;
return (
<div className='js--Output'>
{logs.map(this.renderEntry)}
{children}
</div>
);
const format = (value: any): string => {
if (isError(value)) {
return value.stack ? value.stack : value.toString();
} else if (isUndefined(value)) {
return 'undefined';
} else if (isNull(value)) {
return 'null';
} else if (Array.isArray(value)) {
return `[${value.map((value) => format(value)).join(', ')}]`;
} else if (value instanceof Map) {
return `{${[...value.entries()].map(([key, value]) => key + ': ' + format(value)).join(', ')}}`;
}
private renderEntry = ({ args, type }: Log, index: number) => {
return (
<div
className={`js--Log ${type}`}
key={index}
>
{args.map((arg) => format(arg)).join(' ')}
return value.toString();
};
const renderEntry = ({ args, type }: Log, index: number): React.ReactNode => (
<div className={`js--Log ${type}`} key={index}>
{args.map((arg) => format(arg)).join(' ')}
</div>
);
export default (props: Props) => {
return (
<article className='container js--Output'>
<div className='logs-wrapper'>
<div className='logs-container'>
<div className='logs-content'>
{props.logs.map(renderEntry)}
</div>
</div>
</div>
);
}
}
{props.children}
</article>
);
};

View File

@ -1,4 +1,4 @@
// Copyright 2017-2019 @polkadot/app-123code authors & contributors
// 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.

View File

@ -3,15 +3,35 @@
/* of the Apache-2.0 license. See the LICENSE file for details. */
.js--App {
display: flex;
flex-direction: column;
height: 100vh;
padding: 1rem 1.5rem;
}
/* .container {
padding: 0.25rem;
} */
.js--Content {
align-items: stretch;
display: flex;
flex-grow: 2;
justify-content: space-between;
height: 100%;
}
.js--Dropdown {
margin-right: 100px;
position: relative;
z-index: 200;
.dropdown .menu > .item {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
}
}
.js--Editor,
.js--Output {
min-width: 200px;
.action-button {
position: absolute;
right: 0.25rem;
@ -21,12 +41,46 @@
}
.js--Output {
margin-top: 1rem;
padding: 10px;
background-color: #4e4e4e;
color: #ffffff;
display: flex;
flex-direction: column;
font-family: monospace;
font-size: 14px;
font-size: 13px;
font-variant-ligatures: common-ligatures;
overflow: auto;
padding: 10px;
position: relative;
resize: horizontal;
width: 50%;
&::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;
min-height: 0px;
}
.logs-container {
flex: 1;
overflow: auto;;
}
.logs-content {
height: auto;
}
.js--Log {
animation: fadein 0.2s;
@ -34,26 +88,25 @@
word-break: break-all;
&.error {
color: red;
color: #f88;
}
}
}
.js--Editor {
flex-grow: 2;
padding: 0;
position: relative;
> div.container {
width: 100%;
height: 60vh;
position: relative;
}
.codeflask {
/* background: #f4f7fb; */
}
textarea {
outline: 0;
}
.codeflask--has-line-numbers .codeflask__flatten {
min-width: calc(100% - 40px);
width: auto;
}
.codeflask__lines {
background: #eee;
z-index: 100;
}
}

View File

@ -2,58 +2,108 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiPromise } from '@polkadot/api';
import { KeyringInstance } from '@polkadot/keyring/types';
import { ApiProps } from '@polkadot/ui-api/types';
import { AppProps, I18nProps } from '@polkadot/ui-app/types';
import { Log, LogType } from './types';
import React from 'react';
import { withApi, withMulti } from '@polkadot/ui-api/index';
import { Button } from '@polkadot/ui-app/index';
import { Button, Dropdown } from '@polkadot/ui-app/index';
import uiKeyring from '@polkadot/ui-keyring';
import * as util from '@polkadot/util';
import * as hashing from '@polkadot/util-crypto';
import './index.css';
import Editor from './Editor';
import Output from './Output';
import snippets from './snippets';
import translate from './translate';
import Intro from './Intro';
import Editor from './Editor';
import Output from './Output';
type Injected = {
api: ApiPromise,
console: {
error: (...args: Array<any>) => void,
log: (...args: Array<any>) => void
},
global: null,
hashing: typeof hashing,
keyring: KeyringInstance,
util: typeof util,
window: null
};
type Props = ApiProps & AppProps & I18nProps;
type State = {
code: string,
logs: Array<Log>
isRunning: boolean,
logs: Array<Log>,
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: '',
logs: []
code: local ? local.code : snippets[0].code,
isRunning: false,
logs: [],
snippet: local ? local.value : snippets[0].value
};
render () {
const { logs } = this.state;
const { code, isRunning, logs, snippet } = this.state;
const { t } = this.props;
const options = snippets.map(({ code, ...options }) => ({ ...options }));
return (
<main className='js--App'>
<Editor onEdit={this.onEdit}>
<Button
className='action-button'
isCircular
isPrimary
icon='play'
onClick={this.runJs}
<header className='container'>
<Intro />
<Dropdown
className='js--Dropdown'
onChange={this.selectExample}
options={options}
label={t('Select example')}
defaultValue={snippet}
withLabel
/>
</Editor>
<Output logs={logs}>
<Button
className='action-button'
isCircular
isNegative
icon='erase'
onClick={this.clearConsole}
/>
</Output>
</header>
<section className='js--Content'>
<Editor
code={code}
snippet={snippet}
onEdit={this.onEdit}
>
<div className='action-button'>
<Button
isCircular
isPrimary
icon='play'
onClick={this.runJs}
/>
<Button
isCircular
isDisabled={!isRunning}
isNegative
icon='close'
onClick={this.stopJs}
/>
</div>
</Editor>
<Output logs={logs}>
<Button
className='action-button'
isCircular
isNegative
icon='erase'
onClick={this.clearConsole}
/>
</Output>
</section>
</main>
);
}
@ -62,8 +112,12 @@ class App extends React.PureComponent<Props, State> {
const { api } = this.props;
const { code } = this.state;
const { keyring } = uiKeyring;
const injected = {
api,
this.stopJs();
this.clearConsole();
this.injected = {
api: api.clone(),
console: {
error: this.hookConsole('error'),
log: this.hookConsole('log')
@ -75,9 +129,31 @@ class App extends React.PureComponent<Props, State> {
window: null
};
const exec = `(async ({${Object.keys(injected).join(',')}}) => { try { ${code} } catch (error) { console.error(error); } })(injected);`;
// 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);`;
new Function('injected', exec)(injected);
new Function('injected', exec)(this.injected);
this.setState({ isRunning: true });
}
private stopJs = (): void => {
if (!this.injected) {
return;
}
this.injected.api.disconnect();
this.injected = null;
this.setState({ isRunning: false });
}
private selectExample = (value: string) => {
const snippet = snippets.find(obj => obj.value === value);
localStorage.setItem('app-js-snippet', value);
this.setState({ code: (snippet ? snippet.code : ''), snippet: value });
}
private onEdit = (code: string): void => {

View File

@ -0,0 +1,38 @@
// 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 { Snippet } from '@polkadot/app-js/types';
export const extrinsicMakeTransfer: Snippet = {
value: 'extrinsicMakeTransfer',
text: 'Extrinsics - 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 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 }) => {
if (type === 'Finalised') {
console.log('Successful transfer of ' + randomAmount + ' with hash ' + status.asFinalised.toHex());
} else {
console.log('Status of transfer: ' + type);
}
events.forEach(({ phase, event: { data, method, section } }) => {
console.log(phase.toString() + ' : ' + section + '.' + method + ' ' + data.toString());
});
});`
};

View File

@ -0,0 +1,35 @@
// 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.
import { Snippet } from './../types';
import {
rpcNetworkAuthoring,
rpcNewHead,
rpcQueryState,
rpcSysthemInfo
} from './rpc-examples';
import {
storageGetInfo,
storageGetBalanceInformation,
storageSystemEvents,
storageListenToBalanceChange
} from './storage-examples';
import { extrinsicMakeTransfer } from './extrinsics-examples';
const snippets: Array<Snippet> = [
rpcNetworkAuthoring,
rpcNewHead,
rpcQueryState,
rpcSysthemInfo,
storageGetInfo,
storageGetBalanceInformation,
storageSystemEvents,
storageListenToBalanceChange,
extrinsicMakeTransfer
];
export default snippets;

View File

@ -1,14 +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 `// subscribe to new headers, printing the full info for 5
let count = 0;
const unsub = await api.rpc.chain.subscribeNewHead((header) => {
console.log(\`#\${header.blockNumber}:\`, header);
if (++count === 5) {
console.log('5 headers retrieved, unsubscribing');
unsub();
}
});`;

View File

@ -0,0 +1,29 @@
// 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);`;

View File

@ -0,0 +1,70 @@
// 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 { Snippet } from '@polkadot/app-js/types';
export const rpcNetworkAuthoring: Snippet = {
value: 'rpcNetworkAuthoring',
text: 'Get authoring information',
label: { color: 'pink', children: 'RPC', size: 'tiny' },
code: `// Returns all pending extrinsics, potentially grouped by sender
const unsub = await api.rpc.author.pendingExtrinsics((extrinsics) => {
if(extrinsics.length === 0){
console.log('No pending extrinsics');
return;
}
console.log(extrinsics);
});`
};
export const rpcNewHead: Snippet = {
value: 'rpcListenToHead',
text: 'Listen to new Head',
label: { color: 'pink', children: 'RPC', size: 'tiny' },
code: `// subscribe to new headers, printing the full info for 5 Blocks
let count = 0;
const unsub = await api.rpc.chain.subscribeNewHead((header) => {
console.log(\`#\${header.blockNumber}:\`, header);
if (++count === 5) {
console.log('5 headers retrieved, unsubscribing');
unsub();
}
});`
};
export const rpcQueryState: Snippet = {
value: 'rpcQueryState',
text: 'Get authoring iformation',
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 }) => {
console.log( 'Magic number: ' + magicNumber );
console.log( 'Metadata: ' + metadata.raw );
});`
};
export const rpcSysthemInfo: Snippet = {
value: 'rpcSysthemInfo',
text: 'Get system information',
label: { color: 'pink', children: 'RPC', size: 'tiny' },
code: `// Retrieve the chain & node information information via rpc calls
const [chain, nodeName, nodeVersion, properties] = await Promise.all([
api.rpc.system.chain(),
api.rpc.system.name(),
api.rpc.system.version(),
api.rpc.system.properties()
]);
console.log('You are connected to chain ' + chain)
console.log('You are using: ' + nodeName + ' v' + nodeVersion);
if (properties.size > 0) {
console.log('Node specific properties:');
properties.forEach((value, key) => {
console.log(key, value);
});
} else {
console.log('No specific chain properties found.');
}`
};

View File

@ -0,0 +1,98 @@
// 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 { Snippet } from '@polkadot/app-js/types';
export const storageGetInfo: Snippet = {
value: 'storageGetInfo',
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),
api.query.timestamp.blockPeriod(),
api.query.session.validators()
]);
console.log('Account: ' + ALICE + ' -- AccountNonce: ' + accountNonce);
console.log('blockPeriod in seconds: ' + blockPeriod.toNumber());
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))
);
validators.forEach((authorityId, index) => {
console.log('Validator: ' + authorityId.toString() )
console.log('Balance: ' + validatorBalances[index].toString() );
});
}
`
};
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',
label: { color: 'blue', children: 'Storage', size: 'tiny' },
code: `// Subscribe to system events via storage
api.query.system.events((events) => {
console.log('----- Received ' + events.length + ' event(s): -----');
// loop through the Vec<EventRecord>
events.forEach((record) => {
// extract the phase, event and the event types
const { event, phase } = record;
const types = event.typeDef;
// show what we are busy with
console.log(event.section + ':' + event.method + '::' + 'phase=' + phase.toString());
console.log(event.meta.documentation.toString());
// loop through each of the parameters, displaying the type and data
event.data.forEach((data, index) => {
console.log(types[index].type + ';' + data.toString());
});
});
});`
};
export const storageListenToBalanceChange: Snippet = {
value: 'storageListenToBalanceChange',
text: 'Listen to balance changes',
label: { color: 'blue', children: 'Storage', size: 'tiny' },
code: `// You may leave this example running and make a transfer
// of any value from or to Alice address in the 'Transfer' App
const ALICE = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ';
// Retrieve the initial balance.
let previous = await api.query.balances.freeBalance(ALICE);
console.log('ALICE has a balance of' + previous);
// Subscribe and listen to balance changes
api.query.balances.freeBalance(ALICE, (balance) => {
// Calculate the delta
const change = balance.sub(previous);
// Only display positive value changes (Since we are pulling 'previous' above already,
// the initial balance change will also be zero)
if (!change.isZero()) {
previous = balance;
console.log('New transaction of: '+ change);
}
});`
};

View File

@ -1,12 +1,9 @@
// Copyright 2017-2019 @polkadot/app-123code authors & contributors
// 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.
export default `// all code is wrapped within an async closure, allowing access to:
// api (@polkadot/api), hashing (@polkadot/util-crypto),
// keyring (@polkadot/keyring) and util (@polkadot/util)
// (async ({ api, hashing, keyring, util }) => {
export default `// (async ({ api, hashing, keyring, util }) => {
// ... any user code is executed here ...
// })(injected);
// })();
`;

View File

@ -1,10 +1,20 @@
// Copyright 2017-2019 @polkadot/app-123code authors & contributors
// 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 { SemanticShorthandItem } from 'semantic-ui-react/dist/commonjs/generic';
import { LabelProps } from 'semantic-ui-react/dist/commonjs/elements/Label';
export type LogType = 'error' | 'log';
export type Log = {
args: Array<any>,
type: LogType
};
export type Snippet = {
text: string;
value: string;
code: string;
label?: SemanticShorthandItem<LabelProps>
};

View File

@ -31,8 +31,7 @@
"homepage": "https://github.com/polkadot-js/ui/tree/master/packages/ui-reactive#readme",
"dependencies": {
"@babel/runtime": "^7.2.0",
"@polkadot/api": "^0.42.2",
"@polkadot/types": "^0.42.2",
"@polkadot/api": "^0.42.4",
"rxjs-compat": "^6.3.2"
}
}

View File

@ -11,10 +11,10 @@
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.2.0",
"@polkadot/extrinsics": "^0.42.2",
"@polkadot/extrinsics": "^0.42.4",
"@polkadot/keyring": "^0.33.36",
"@polkadot/storage": "^0.42.2",
"@polkadot/types": "^0.42.2",
"@polkadot/storage": "^0.42.4",
"@polkadot/types": "^0.42.4",
"@polkadot/ui-api": "^0.23.7",
"@polkadot/ui-identicon": "^0.25.8",
"@polkadot/ui-keyring": "^0.25.8",
@ -38,7 +38,7 @@
"react-copy-to-clipboard": "^5.0.1",
"react-dom": "^16.7.0",
"react-dropzone": "^7.0.1",
"react-i18next": "^9.0.2",
"react-i18next": "9.0.2",
"react-router": "^4.3.1",
"react-router-dom": "^4.3.1",
"semantic-ui-css": "^2.3.1",

View File

@ -31,8 +31,7 @@
"homepage": "https://github.com/polkadot-js/ui/tree/master/packages/ui-reactive#readme",
"dependencies": {
"@babel/runtime": "^7.2.0",
"@polkadot/api": "^0.42.2",
"@polkadot/types": "^0.42.2",
"@polkadot/api": "^0.42.4",
"rxjs-compat": "^6.3.2"
}
}

2200
yarn.lock

File diff suppressed because it is too large Load Diff