Merge branch 'develop_51' into restyle-code-editor-top-bar
This commit is contained in:
commit
5fd69b60fa
|
@ -12194,14 +12194,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
|
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
|
||||||
},
|
},
|
||||||
"typedarray-to-buffer": {
|
|
||||||
"version": "3.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
|
||||||
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
|
||||||
"requires": {
|
|
||||||
"is-typedarray": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ua-parser-js": {
|
"ua-parser-js": {
|
||||||
"version": "0.7.18",
|
"version": "0.7.18",
|
||||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz",
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz",
|
||||||
|
@ -12932,8 +12924,19 @@
|
||||||
"integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==",
|
"integrity": "sha512-wAnENuZx75T5ZSrT2De2LOaUuPf2yRjq1VfcbD7+Zd79F3DZZLBJcPyCNVQ1U0fAXt0wfgCKl7sVw5pffqR9Bw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"underscore": "1.8.3",
|
"underscore": "1.8.3",
|
||||||
"web3-core-helpers": "1.0.0-beta.36",
|
"web3-core-helpers": "1.0.0-beta.36"
|
||||||
"websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2"
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"websocket": {
|
||||||
|
"version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
|
||||||
|
"from": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
|
||||||
|
"requires": {
|
||||||
|
"debug": "^2.2.0",
|
||||||
|
"nan": "^2.3.3",
|
||||||
|
"typedarray-to-buffer": "^3.1.2",
|
||||||
|
"yaeti": "^0.0.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"web3-shh": {
|
"web3-shh": {
|
||||||
|
@ -13371,16 +13374,6 @@
|
||||||
"source-map": "~0.6.1"
|
"source-map": "~0.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"websocket": {
|
|
||||||
"version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
|
|
||||||
"from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
|
|
||||||
"requires": {
|
|
||||||
"debug": "^2.2.0",
|
|
||||||
"nan": "^2.3.3",
|
|
||||||
"typedarray-to-buffer": "^3.1.2",
|
|
||||||
"yaeti": "^0.0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"websocket-driver": {
|
"websocket-driver": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz",
|
||||||
|
@ -13611,11 +13604,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
|
||||||
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
|
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
|
||||||
},
|
},
|
||||||
"yaeti": {
|
|
||||||
"version": "0.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
|
||||||
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc="
|
|
||||||
},
|
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||||
|
|
|
@ -282,7 +282,7 @@ export const files = {
|
||||||
export const FILE = createRequestTypes('FILE');
|
export const FILE = createRequestTypes('FILE');
|
||||||
export const file = {
|
export const file = {
|
||||||
request: (file) => action(FILE[REQUEST], file),
|
request: (file) => action(FILE[REQUEST], file),
|
||||||
success: (file) => action(FILE[SUCCESS], file),
|
success: (file) => action(FILE[SUCCESS], {file}),
|
||||||
failure: (error) => action(FILE[FAILURE], {error})
|
failure: (error) => action(FILE[FAILURE], {error})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -300,20 +300,6 @@ export const removeFile = {
|
||||||
failure: (error) => action(REMOVE_FILE[FAILURE], {error})
|
failure: (error) => action(REMOVE_FILE[FAILURE], {error})
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CURRENT_FILE = createRequestTypes('CURRENT_FILE');
|
|
||||||
export const currentFile = {
|
|
||||||
request: () => action(CURRENT_FILE[REQUEST]),
|
|
||||||
success: (file) => action(CURRENT_FILE[SUCCESS], {currentFiles: [file]}),
|
|
||||||
failure: () => action(CURRENT_FILE[FAILURE])
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SAVE_CURRENT_FILE = createRequestTypes('SAVE_CURRENT_FILE');
|
|
||||||
export const saveCurrentFile = {
|
|
||||||
request: (file) => action(SAVE_CURRENT_FILE[REQUEST], file),
|
|
||||||
success: (file) => action(SAVE_CURRENT_FILE[SUCCESS], {currentFiles: [file]}),
|
|
||||||
failure: () => action(SAVE_CURRENT_FILE[FAILURE])
|
|
||||||
};
|
|
||||||
|
|
||||||
export const GAS_ORACLE = createRequestTypes('GAS_ORACLE');
|
export const GAS_ORACLE = createRequestTypes('GAS_ORACLE');
|
||||||
export const gasOracle = {
|
export const gasOracle = {
|
||||||
request: () => action(GAS_ORACLE[REQUEST]),
|
request: () => action(GAS_ORACLE[REQUEST]),
|
||||||
|
@ -349,6 +335,88 @@ export const web3EstimateGas = {
|
||||||
failure: (error, payload) => action(WEB3_ESTIMAGE_GAS[FAILURE], {web3Error: error, contract: payload.contract})
|
failure: (error, payload) => action(WEB3_ESTIMAGE_GAS[FAILURE], {web3Error: error, contract: payload.contract})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const START_DEBUG = createRequestTypes('START_DEBUG');
|
||||||
|
export const startDebug = {
|
||||||
|
request: (txHash) => action(START_DEBUG[REQUEST], {txHash}),
|
||||||
|
success: () => action(START_DEBUG[SUCCESS]),
|
||||||
|
failure: (error) => action(START_DEBUG[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEBUG_JUMP_BACK = createRequestTypes('DEBUG_JUMP_BACK');
|
||||||
|
export const debugJumpBack = {
|
||||||
|
request: () => action(DEBUG_JUMP_BACK[REQUEST], {}),
|
||||||
|
success: () => action(DEBUG_JUMP_BACK[SUCCESS]),
|
||||||
|
failure: (error) => action(DEBUG_JUMP_BACK[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEBUG_JUMP_FORWARD = createRequestTypes('DEBUG_JUMP_FORWARD');
|
||||||
|
export const debugJumpForward = {
|
||||||
|
request: () => action(DEBUG_JUMP_FORWARD[REQUEST], {}),
|
||||||
|
success: () => action(DEBUG_JUMP_FORWARD[SUCCESS]),
|
||||||
|
failure: (error) => action(DEBUG_JUMP_FORWARD[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEBUG_STEP_OVER_BACKWARD = createRequestTypes('DEBUG_STEP_OVER_BACKWARD');
|
||||||
|
export const debugStepOverBackward = {
|
||||||
|
request: () => action(DEBUG_STEP_OVER_BACKWARD[REQUEST], {}),
|
||||||
|
success: () => action(DEBUG_STEP_OVER_BACKWARD[SUCCESS]),
|
||||||
|
failure: (error) => action(DEBUG_STEP_OVER_BACKWARD[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEBUG_STEP_OVER_FORWARD = createRequestTypes('DEBUG_STEP_OVER_FORWARD');
|
||||||
|
export const debugStepOverForward = {
|
||||||
|
request: () => action(DEBUG_STEP_OVER_FORWARD[REQUEST], {}),
|
||||||
|
success: () => action(DEBUG_STEP_OVER_FORWARD[SUCCESS]),
|
||||||
|
failure: (error) => action(DEBUG_STEP_OVER_FORWARD[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEBUG_STEP_INTO_BACKWARD = createRequestTypes('DEBUG_STEP_INTO_BACKWARD');
|
||||||
|
export const debugStepIntoBackward = {
|
||||||
|
request: () => action(DEBUG_STEP_INTO_BACKWARD[REQUEST], {}),
|
||||||
|
success: () => action(DEBUG_STEP_INTO_BACKWARD[SUCCESS]),
|
||||||
|
failure: (error) => action(DEBUG_STEP_INTO_BACKWARD[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEBUG_STEP_INTO_FORWARD = createRequestTypes('DEBUG_STEP_INTO_FORWARD');
|
||||||
|
export const debugStepIntoForward = {
|
||||||
|
request: () => action(DEBUG_STEP_INTO_FORWARD[REQUEST], {}),
|
||||||
|
success: () => action(DEBUG_STEP_INTO_FORWARD[SUCCESS]),
|
||||||
|
failure: (error) => action(DEBUG_STEP_INTO_FORWARD[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TOGGLE_BREAKPOINT = createRequestTypes('TOGGLE_BREAKPOINT');
|
||||||
|
export const toggleBreakpoint = {
|
||||||
|
request: (filename, lineNumber) => action(TOGGLE_BREAKPOINT[REQUEST], {filename, lineNumber}),
|
||||||
|
success: (data, payload) => action(TOGGLE_BREAKPOINT[SUCCESS], {payload}),
|
||||||
|
failure: (error) => action(TOGGLE_BREAKPOINT[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEBUGGER_INFO = createRequestTypes('DEBUGGER_INFO');
|
||||||
|
export const debuggerInfo = {
|
||||||
|
success: (data) => action(DEBUGGER_INFO[SUCCESS], {data})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FETCH_EDITOR_TABS = createRequestTypes('FETCH_EDITOR_TABS');
|
||||||
|
export const fetchEditorTabs = {
|
||||||
|
request: () => action(FETCH_EDITOR_TABS[REQUEST]),
|
||||||
|
success: (editorTabs) => action(FETCH_EDITOR_TABS[SUCCESS], {editorTabs}),
|
||||||
|
failure: () => action(FETCH_EDITOR_TABS[FAILURE])
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ADD_EDITOR_TABS = createRequestTypes('ADD_EDITOR_TABS');
|
||||||
|
export const addEditorTabs = {
|
||||||
|
request: (file) => action(ADD_EDITOR_TABS[REQUEST], {file}),
|
||||||
|
success: () => action(ADD_EDITOR_TABS[SUCCESS]),
|
||||||
|
failure: () => action(ADD_EDITOR_TABS[FAILURE])
|
||||||
|
};
|
||||||
|
|
||||||
|
export const REMOVE_EDITOR_TABS = createRequestTypes('REMOVE_EDITOR_TABS');
|
||||||
|
export const removeEditorTabs = {
|
||||||
|
request: (file) => action(REMOVE_EDITOR_TABS[REQUEST], {file}),
|
||||||
|
success: () => action(REMOVE_EDITOR_TABS[SUCCESS]),
|
||||||
|
failure: () => action(REMOVE_EDITOR_TABS[FAILURE])
|
||||||
|
};
|
||||||
|
|
||||||
// Web Socket
|
// Web Socket
|
||||||
export const WATCH_NEW_PROCESS_LOGS = 'WATCH_NEW_PROCESS_LOGS';
|
export const WATCH_NEW_PROCESS_LOGS = 'WATCH_NEW_PROCESS_LOGS';
|
||||||
export const STOP_NEW_PROCESS_LOGS = 'STOP_NEW_PROCESS_LOGS';
|
export const STOP_NEW_PROCESS_LOGS = 'STOP_NEW_PROCESS_LOGS';
|
||||||
|
@ -358,6 +426,7 @@ export const INIT_BLOCK_HEADER = 'INIT_BLOCK_HEADER';
|
||||||
export const STOP_BLOCK_HEADER = 'STOP_BLOCK_HEADER';
|
export const STOP_BLOCK_HEADER = 'STOP_BLOCK_HEADER';
|
||||||
export const WATCH_GAS_ORACLE = 'WATCH_GAS_ORACLE';
|
export const WATCH_GAS_ORACLE = 'WATCH_GAS_ORACLE';
|
||||||
export const STOP_GAS_ORACLE = 'STOP_GAS_ORACLE';
|
export const STOP_GAS_ORACLE = 'STOP_GAS_ORACLE';
|
||||||
|
export const STOP_DEBUGGER = 'STOP_DEBUGGER';
|
||||||
|
|
||||||
export function listenToProcessLogs(processName) {
|
export function listenToProcessLogs(processName) {
|
||||||
return {
|
return {
|
||||||
|
@ -409,6 +478,12 @@ export function stopGasOracle(){
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function stopDebugger(){
|
||||||
|
return {
|
||||||
|
type: STOP_DEBUGGER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Actions without Side Effect
|
// Actions without Side Effect
|
||||||
export const UPDATE_BASE_ETHER = 'UPDATE_BASE_ETHER';
|
export const UPDATE_BASE_ETHER = 'UPDATE_BASE_ETHER';
|
||||||
export function updateBaseEther(value) {
|
export function updateBaseEther(value) {
|
||||||
|
@ -418,18 +493,10 @@ export function updateBaseEther(value) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TOGGLE_BREAKPOINT = 'TOGGLE_BREAKPOINT';
|
|
||||||
export function toggleBreakpoint(filename, lineNumber) {
|
|
||||||
return {
|
|
||||||
type: TOGGLE_BREAKPOINT,
|
|
||||||
payload: {filename, lineNumber}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export const UPDATE_DEPLOYMENT_PIPELINE = 'UPDATE_DEPLOYMENT_PIPELINE';
|
export const UPDATE_DEPLOYMENT_PIPELINE = 'UPDATE_DEPLOYMENT_PIPELINE';
|
||||||
export function updateDeploymentPipeline(value) {
|
export function updateDeploymentPipeline(value) {
|
||||||
return {
|
return {
|
||||||
type: UPDATE_DEPLOYMENT_PIPELINE,
|
type: UPDATE_DEPLOYMENT_PIPELINE,
|
||||||
payload: value
|
payload: value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,32 +8,34 @@ import CardTitleIdenticon from './CardTitleIdenticon';
|
||||||
const Accounts = ({accounts}) => (
|
const Accounts = ({accounts}) => (
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<h1>Accounts</h1>
|
<Card>
|
||||||
{accounts.map(account => (
|
<CardHeader>
|
||||||
<Card key={account.address}>
|
<h2>Accounts</h2>
|
||||||
<CardHeader>
|
</CardHeader>
|
||||||
|
<CardBody>
|
||||||
|
{accounts.map(account => (
|
||||||
|
<div className="explorer-row border-top" key={account.address}>
|
||||||
<CardTitleIdenticon id={account.address}>Account
|
<CardTitleIdenticon id={account.address}>Account
|
||||||
<Link to={`/embark/explorer/accounts/${account.address}`}>{account.address}</Link>
|
<Link to={`/embark/explorer/accounts/${account.address}`}>{account.address}</Link>
|
||||||
</CardTitleIdenticon>
|
</CardTitleIdenticon>
|
||||||
</CardHeader>
|
<Row>
|
||||||
<CardBody>
|
<Col>
|
||||||
<Row>
|
<strong>Balance</strong>
|
||||||
<Col>
|
<div>{account.balance} Ether</div>
|
||||||
<strong>Balance</strong>
|
</Col>
|
||||||
<div>{account.balance} Ether</div>
|
<Col>
|
||||||
</Col>
|
<strong>Tx Count</strong>
|
||||||
<Col>
|
<div>{account.transactionCount}</div>
|
||||||
<strong>Tx Count</strong>
|
</Col>
|
||||||
<div>{account.transactionCount}</div>
|
<Col>
|
||||||
</Col>
|
<strong>Index</strong>
|
||||||
<Col>
|
<div>{account.index}</div>
|
||||||
<strong>Index</strong>
|
</Col>
|
||||||
<div>{account.index}</div>
|
</Row>
|
||||||
</Col>
|
</div>
|
||||||
</Row>
|
))}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,7 +13,7 @@ const Block = ({block}) => (
|
||||||
<CardTitleIdenticon id={block.hash}>Block {block.number}</CardTitleIdenticon>
|
<CardTitleIdenticon id={block.hash}>Block {block.number}</CardTitleIdenticon>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<dl class="row">
|
<dl className="row">
|
||||||
<Description label="Hash" value={block.hash} />
|
<Description label="Hash" value={block.hash} />
|
||||||
<Description label="Timestamp" value={block.timestamp} />
|
<Description label="Timestamp" value={block.timestamp} />
|
||||||
<Description label="Difficulty" value={block.difficulty} />
|
<Description label="Difficulty" value={block.difficulty} />
|
||||||
|
|
|
@ -4,48 +4,50 @@ import {Row, Col, Card, CardHeader, CardBody} from 'reactstrap';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import CardTitleIdenticon from './CardTitleIdenticon';
|
import CardTitleIdenticon from './CardTitleIdenticon';
|
||||||
|
import LoadMore from "./LoadMore";
|
||||||
|
|
||||||
const Blocks = ({blocks}) => (
|
const Blocks = ({blocks, showLoadMore, loadMore}) => (
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<h1>Blocks</h1>
|
<Card>
|
||||||
{blocks.map(block => (
|
<CardHeader>
|
||||||
<Card key={block.number}>
|
<h2>Blocks</h2>
|
||||||
<CardHeader>
|
</CardHeader>
|
||||||
<CardTitleIdenticon id={block.hash}>Block
|
<CardBody>
|
||||||
<Link to={`/embark/explorer/blocks/${block.number}`}>
|
{blocks.map(block => (
|
||||||
{block.number}
|
<div className="explorer-row border-top" key={block.number}>
|
||||||
</Link>
|
<CardTitleIdenticon id={block.hash}>Block
|
||||||
</CardTitleIdenticon>
|
<Link to={`/embark/explorer/blocks/${block.number}`}>
|
||||||
</CardHeader>
|
{block.number}
|
||||||
<CardBody>
|
</Link>
|
||||||
<Row>
|
</CardTitleIdenticon>
|
||||||
<Col>
|
<Row>
|
||||||
<strong>Number</strong>
|
<Col>
|
||||||
<div>{block.number}</div>
|
<strong>Mined On</strong>
|
||||||
</Col>
|
<div>{new Date(block.timestamp * 1000).toLocaleString()}</div>
|
||||||
<Col>
|
</Col>
|
||||||
<strong>Mined On</strong>
|
<Col>
|
||||||
<div>{new Date(block.timestamp * 1000).toLocaleString()}</div>
|
<strong>Gas Used</strong>
|
||||||
</Col>
|
<div>{block.gasUsed}</div>
|
||||||
<Col>
|
</Col>
|
||||||
<strong>Gas Used</strong>
|
<Col>
|
||||||
<div>{block.gasUsed}</div>
|
<strong>TX Count</strong>
|
||||||
</Col>
|
<div>{block.transactions.length}</div>
|
||||||
<Col>
|
</Col>
|
||||||
<strong>TX Count</strong>
|
</Row>
|
||||||
<div>{block.transactions.length}</div>
|
</div>
|
||||||
</Col>
|
))}
|
||||||
</Row>
|
{showLoadMore && <LoadMore loadMore={() => loadMore()}/>}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
|
||||||
Blocks.propTypes = {
|
Blocks.propTypes = {
|
||||||
blocks: PropTypes.arrayOf(PropTypes.object)
|
blocks: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
showLoadMore: PropTypes.bool,
|
||||||
|
loadMore: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Blocks;
|
export default Blocks;
|
||||||
|
|
|
@ -1,9 +1,20 @@
|
||||||
|
import PropTypes from "prop-types";
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {CardTitle} from 'reactstrap';
|
import {CardTitle} from 'reactstrap';
|
||||||
import Blockies from 'react-blockies';
|
import Blockies from 'react-blockies';
|
||||||
|
|
||||||
const CardTitleIdenticon = ({id, children}) => (
|
const CardTitleIdenticon = ({id, children}) => (
|
||||||
<CardTitle><Blockies seed={id} className="rounded"/><span className="ml-2 align-top">{children}</span></CardTitle>
|
<CardTitle>
|
||||||
)
|
<Blockies seed={id} className="rounded"/><span className="ml-2 align-top text-truncate">{children}</span>
|
||||||
|
</CardTitle>
|
||||||
|
);
|
||||||
|
|
||||||
export default CardTitleIdenticon
|
CardTitleIdenticon.propTypes = {
|
||||||
|
id: PropTypes.string,
|
||||||
|
children: PropTypes.oneOfType([
|
||||||
|
PropTypes.object,
|
||||||
|
PropTypes.array
|
||||||
|
])
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CardTitleIdenticon;
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {
|
||||||
|
Row,
|
||||||
|
Col,
|
||||||
|
FormGroup,
|
||||||
|
Label,
|
||||||
|
Input,
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
CardBody,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
CardFooter,
|
||||||
|
ListGroup,
|
||||||
|
ListGroupItem
|
||||||
|
} from "reactstrap";
|
||||||
|
import ReactJson from 'react-json-view';
|
||||||
|
|
||||||
|
class ContractDebugger extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange(e) {
|
||||||
|
this.setState({txHash: e.target.value});
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(e) {
|
||||||
|
this.props.startDebug(this.state.txHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
debugJumpBack(e) {
|
||||||
|
this.props.debugJumpBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
debugJumpForward(e) {
|
||||||
|
this.props.debugJumpForward()
|
||||||
|
}
|
||||||
|
|
||||||
|
debugStepOverForward(e) {
|
||||||
|
this.props.debugStepOverForward()
|
||||||
|
}
|
||||||
|
|
||||||
|
debugStepOverBackward(e) {
|
||||||
|
this.props.debugStepOverBackward()
|
||||||
|
}
|
||||||
|
|
||||||
|
debugStepIntoForward(e) {
|
||||||
|
this.props.debugStepIntoForward()
|
||||||
|
}
|
||||||
|
|
||||||
|
debugStepIntoBackward(e) {
|
||||||
|
this.props.debugStepIntoBackward()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<Input name="txHash" id="txHash" onChange={(e) => this.handleChange(e)}/>
|
||||||
|
<Button color="primary" onClick={(e) => this.debug(e)}>Debug Tx</Button>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<Button color="light" className="btn-square debugButton jumpBack" alt="jump to previous breakpoint" onClick={(e) => this.debugJumpBack(e)}></Button>
|
||||||
|
<Button color="light" className="btn-square debugButton jumpForward" alt="jump to revious breakpoint" onClick={(e) => this.debugJumpForward(e)}></Button>
|
||||||
|
<Button color="light" className="btn-square debugButton stepOverBack" alt="step back" onClick={(e) => this.debugStepOverBackward(e)}></Button>
|
||||||
|
<Button color="light" className="btn-square debugButton stepOverForward" alt="step over" onClick={(e) => this.debugStepOverForward(e)}></Button>
|
||||||
|
<Button color="light" className="btn-square debugButton stepIntoForward" alt="step into" onClick={(e) => this.debugStepIntoForward(e)}></Button>
|
||||||
|
<Button color="light" className="btn-square debugButton stepIntoBack" alt="step out" onClick={(e) => this.debugStepIntoBackward(e)}></Button>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<br /><strong>Scopes</strong>
|
||||||
|
<div>
|
||||||
|
<ReactJson src={{locals: this.props.debuggerInfo.locals, contract: this.props.debuggerInfo.globals}} theme="monokai" sortKeys={true} name={false} collapse={1} />
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContractDebugger.propTypes = {
|
||||||
|
contract: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ContractDebugger;
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactJson from "react-json-view";
|
import ReactJson from "react-json-view";
|
||||||
import {Row, Col, Table} from "reactstrap";
|
import {Row, Col} from "reactstrap";
|
||||||
import {formatContractForDisplay} from '../utils/presentation';
|
|
||||||
import CopyButton from './CopyButton';
|
import CopyButton from './CopyButton';
|
||||||
|
|
||||||
const ContractDetail = ({contract}) => {
|
const ContractDetail = ({contract}) => {
|
||||||
const contractDisplay = formatContractForDisplay(contract);
|
|
||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
|
|
|
@ -1,183 +0,0 @@
|
||||||
import PropTypes from "prop-types";
|
|
||||||
import React, {Component} from 'react';
|
|
||||||
import {
|
|
||||||
Row,
|
|
||||||
Col,
|
|
||||||
Form,
|
|
||||||
FormGroup,
|
|
||||||
Label,
|
|
||||||
Input,
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
CardBody,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
CardFooter,
|
|
||||||
Collapse,
|
|
||||||
ListGroup,
|
|
||||||
ListGroupItem
|
|
||||||
} from "reactstrap";
|
|
||||||
|
|
||||||
class ContractFunction extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {inputs: {}, optionsCollapse: false, functionCollapse: false};
|
|
||||||
}
|
|
||||||
|
|
||||||
static isPureCall(method) {
|
|
||||||
return (method.mutability === 'view' || method.mutability === 'pure');
|
|
||||||
}
|
|
||||||
|
|
||||||
static isEvent(method) {
|
|
||||||
return !this.isPureCall(method) && (method.type === 'event');
|
|
||||||
}
|
|
||||||
|
|
||||||
buttonTitle() {
|
|
||||||
const {method} = this.props;
|
|
||||||
if (method.name === 'constructor') {
|
|
||||||
return 'Deploy';
|
|
||||||
}
|
|
||||||
|
|
||||||
return ContractFunction.isPureCall(method) ? 'Call' : 'Send';
|
|
||||||
}
|
|
||||||
|
|
||||||
inputsAsArray() {
|
|
||||||
return this.props.method.inputs
|
|
||||||
.map(input => this.state.inputs[input.name])
|
|
||||||
.filter(value => value);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChange(e, name) {
|
|
||||||
let newInputs = this.state.inputs;
|
|
||||||
newInputs[name] = e.target.value;
|
|
||||||
this.setState({inputs: newInputs});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCall(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.props.postContractFunction(this.props.contractProfile.name, this.props.method.name, this.inputsAsArray(), this.state.inputs.gasPrice * 1000000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
callDisabled() {
|
|
||||||
return this.inputsAsArray().length !== this.props.method.inputs.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleOptions() {
|
|
||||||
this.setState({
|
|
||||||
optionsCollapse: !this.state.optionsCollapse,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleFunction() {
|
|
||||||
this.setState({
|
|
||||||
functionCollapse: !this.state.functionCollapse,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Col xs={12}>
|
|
||||||
<Card>
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle className="collapsable contractFunction" onClick={() => this.toggleFunction()}>
|
|
||||||
{ContractFunction.isPureCall(this.props.method) &&
|
|
||||||
<button class="btn btn-brand btn-sm" style={{ "color": "#fff", "background-color": "#ff4500", "border-color": "#ff4500", "float": "right" }}>call</button>
|
|
||||||
}
|
|
||||||
{ContractFunction.isEvent(this.props.method) &&
|
|
||||||
<button class="btn btn-brand btn-sm" style={{ "color": "#fff", "background-color": "#aad450", "border-color": "#aad450", "float": "right" }}>event</button>
|
|
||||||
}
|
|
||||||
{this.props.method.name}({this.props.method.inputs.map(input => input.name).join(', ')})
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<Collapse isOpen={this.state.functionCollapse}>
|
|
||||||
<CardBody>
|
|
||||||
<Form action="" method="post" inline>
|
|
||||||
{this.props.method.inputs.map(input => (
|
|
||||||
<FormGroup key={input.name} className="pr-1">
|
|
||||||
<Label for={input.name} className="pr-1">{input.name}: </Label>
|
|
||||||
<Input name={input.name} id={input.name} placeholder={input.type} onChange={(e) => this.handleChange(e, input.name)}/>
|
|
||||||
</FormGroup>
|
|
||||||
))}
|
|
||||||
</Form>
|
|
||||||
{!ContractFunction.isPureCall(this.props.method) &&
|
|
||||||
<Col xs={12} style={{"margin-bottom": "5px", "margin-top": "5px"}}>
|
|
||||||
<Row>
|
|
||||||
<strong className="collapsable" onClick={() => this.toggleOptions()}><i className={this.state.optionsCollapse ? 'fa fa-caret-down' : 'fa fa-caret-right'}/>Advanced Options</strong>
|
|
||||||
<Collapse isOpen={this.state.optionsCollapse}>
|
|
||||||
<Form action="" method="post" inline>
|
|
||||||
<FormGroup key="gasPrice" className="pr-1">
|
|
||||||
<Label for="gasPrice" className="pr-1">Gas Price (in GWei)(optional)</Label>
|
|
||||||
<Input name="gasPrice" id="gasPrice" onChange={(e) => this.handleChange(e, 'gasPrice')}/>
|
|
||||||
</FormGroup>
|
|
||||||
</Form>
|
|
||||||
</Collapse>
|
|
||||||
</Row>
|
|
||||||
</Col>
|
|
||||||
}
|
|
||||||
<div align="right">
|
|
||||||
<Button color="primary" disabled={this.callDisabled()} onClick={(e) => this.handleCall(e)} >
|
|
||||||
{this.buttonTitle()}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</CardBody>
|
|
||||||
</Collapse>
|
|
||||||
{this.props.contractFunctions && this.props.contractFunctions.length > 0 && <CardFooter>
|
|
||||||
<ListGroup>
|
|
||||||
{this.props.contractFunctions.map(contractFunction => (
|
|
||||||
<ListGroupItem key={contractFunction.result}>
|
|
||||||
{contractFunction.inputs.length > 0 && <p>Inputs: {contractFunction.inputs.join(', ')}</p>}
|
|
||||||
<strong>Result: {contractFunction.result}</strong>
|
|
||||||
</ListGroupItem>
|
|
||||||
))}
|
|
||||||
</ListGroup>
|
|
||||||
</CardFooter>}
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ContractFunction.propTypes = {
|
|
||||||
contractProfile: PropTypes.object,
|
|
||||||
method: PropTypes.object,
|
|
||||||
contractFunctions: PropTypes.arrayOf(PropTypes.object),
|
|
||||||
postContractFunction: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
const filterContractFunctions = (contractFunctions, contractName, method) => {
|
|
||||||
return contractFunctions.filter((contractFunction) => (
|
|
||||||
contractFunction.contractName === contractName && contractFunction.method === method
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
const ContractFunctions = (props) => {
|
|
||||||
const {contractProfile} = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Row>
|
|
||||||
{contractProfile.methods
|
|
||||||
.filter((method) => {
|
|
||||||
return props.onlyConstructor ? method.type === 'constructor' : method.type !== 'constructor';
|
|
||||||
})
|
|
||||||
.map(method => <ContractFunction key={method.name}
|
|
||||||
method={method}
|
|
||||||
contractFunctions={filterContractFunctions(props.contractFunctions, contractProfile.name, method.name)}
|
|
||||||
contractProfile={contractProfile}
|
|
||||||
postContractFunction={props.postContractFunction}/>)}
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ContractFunctions.propTypes = {
|
|
||||||
onlyConstructor: PropTypes.bool,
|
|
||||||
contractProfile: PropTypes.object,
|
|
||||||
contractFunctions: PropTypes.arrayOf(PropTypes.object),
|
|
||||||
postContractFunction: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
ContractFunctions.defaultProps = {
|
|
||||||
onlyConstructor: false
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ContractFunctions;
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import classnames from 'classnames';
|
||||||
import ContractDetail from '../components/ContractDetail';
|
import ContractDetail from '../components/ContractDetail';
|
||||||
import ContractLoggerContainer from '../containers/ContractLoggerContainer';
|
import ContractLoggerContainer from '../containers/ContractLoggerContainer';
|
||||||
import ContractOverviewContainer from '../containers/ContractOverviewContainer';
|
import ContractOverviewContainer from '../containers/ContractOverviewContainer';
|
||||||
|
import ContractDebuggerContainer from '../containers/ContractDebuggerContainer';
|
||||||
|
|
||||||
class ContractLayout extends React.Component {
|
class ContractLayout extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -55,6 +56,14 @@ class ContractLayout extends React.Component {
|
||||||
Logger
|
Logger
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</NavItem>
|
</NavItem>
|
||||||
|
<NavItem>
|
||||||
|
<NavLink
|
||||||
|
className={classnames({ active: this.state.activeTab === '4' })}
|
||||||
|
onClick={() => { this.toggle('4'); }}
|
||||||
|
>
|
||||||
|
Debugger
|
||||||
|
</NavLink>
|
||||||
|
</NavItem>
|
||||||
</Nav>
|
</Nav>
|
||||||
<TabContent activeTab={this.state.activeTab}>
|
<TabContent activeTab={this.state.activeTab}>
|
||||||
<TabPane tabId="1">
|
<TabPane tabId="1">
|
||||||
|
@ -66,6 +75,9 @@ class ContractLayout extends React.Component {
|
||||||
<TabPane tabId="3">
|
<TabPane tabId="3">
|
||||||
<ContractLoggerContainer contract={this.props.contract} />
|
<ContractLoggerContainer contract={this.props.contract} />
|
||||||
</TabPane>
|
</TabPane>
|
||||||
|
<TabPane tabId="4">
|
||||||
|
<ContractDebuggerContainer contract={this.props.contract} />
|
||||||
|
</TabPane>
|
||||||
</TabContent>
|
</TabContent>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
@ -79,12 +79,12 @@ class ContractFunction extends Component {
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="collapsable contractFunction" onClick={() => this.toggleFunction()}>
|
<CardTitle className="collapsable" onClick={() => this.toggleFunction()}>
|
||||||
{ContractFunction.isPureCall(this.props.method) &&
|
{ContractFunction.isPureCall(this.props.method) &&
|
||||||
<button class="btn btn-brand btn-sm" style={{ "color": "#fff", "background-color": "#ff4500", "border-color": "#ff4500", "float": "right" }}>call</button>
|
<button className="btn btn-warning btn-sm float-right">call</button>
|
||||||
}
|
}
|
||||||
{ContractFunction.isEvent(this.props.method) &&
|
{ContractFunction.isEvent(this.props.method) &&
|
||||||
<button class="btn btn-brand btn-sm" style={{ "color": "#fff", "background-color": "#aad450", "border-color": "#aad450", "float": "right" }}>event</button>
|
<button className="btn btn-info btn-sm float-right">event</button>
|
||||||
}
|
}
|
||||||
{this.props.method.name}({this.props.method.inputs.map(input => input.name).join(', ')})
|
{this.props.method.name}({this.props.method.inputs.map(input => input.name).join(', ')})
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
.explorer-row {
|
||||||
|
border-top-width: 0 !important; /*Bootstrap uses important, so we need to override it*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.explorer-row + .explorer-row {
|
||||||
|
margin-top: 5px;
|
||||||
|
padding-top: 20px;
|
||||||
|
border-top-width: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explorer-row .text-truncate {
|
||||||
|
width: 90%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
|
@ -8,9 +8,11 @@ import AccountsContainer from '../containers/AccountsContainer';
|
||||||
import BlocksContainer from '../containers/BlocksContainer';
|
import BlocksContainer from '../containers/BlocksContainer';
|
||||||
import TransactionsContainer from '../containers/TransactionsContainer';
|
import TransactionsContainer from '../containers/TransactionsContainer';
|
||||||
|
|
||||||
|
import './Explorer.css';
|
||||||
|
|
||||||
const ExplorerDashboardLayout = () => (
|
const ExplorerDashboardLayout = () => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Row>
|
<Row className="mt-4">
|
||||||
<Col>
|
<Col>
|
||||||
<AccountsContainer />
|
<AccountsContainer />
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as monaco from 'monaco-editor';
|
import * as monaco from 'monaco-editor';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import FontAwesomeIcon from 'react-fontawesome';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import './TextEditor.css';
|
import './TextEditor.css';
|
||||||
|
|
||||||
|
@ -40,7 +42,7 @@ class TextEditor extends React.Component {
|
||||||
|
|
||||||
editor.onMouseDown((e) => {
|
editor.onMouseDown((e) => {
|
||||||
if (e.target.type === GUTTER_GLYPH_MARGIN){
|
if (e.target.type === GUTTER_GLYPH_MARGIN){
|
||||||
this.props.toggleBreakpoint(this.props.file.name, e.target.position.lineNumber);
|
this.props.toggleBreakpoint(this.props.currentFile.name, e.target.position.lineNumber);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -49,7 +51,10 @@ class TextEditor extends React.Component {
|
||||||
|
|
||||||
|
|
||||||
getLanguage() {
|
getLanguage() {
|
||||||
const extension = this.props.file.name.split('.').pop();
|
if (!this.props.currentFile.name) {
|
||||||
|
return DEFAULT_LANGUAGE;
|
||||||
|
}
|
||||||
|
const extension = this.props.currentFile.name.split('.').pop();
|
||||||
return SUPPORTED_LANGUAGES[SUPPORTED_LANGUAGES.indexOf(extension)] || DEFAULT_LANGUAGE;
|
return SUPPORTED_LANGUAGES[SUPPORTED_LANGUAGES.indexOf(extension)] || DEFAULT_LANGUAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,8 +102,9 @@ class TextEditor extends React.Component {
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
//TODO remove me when debuggerLine comes from the debugger API
|
let debuggerLine = this.props.debuggerLine;
|
||||||
let debuggerLine = this.props.debuggerLine || 11;
|
console.dir("debuggerLine")
|
||||||
|
console.dir(debuggerLine)
|
||||||
newDecorations.push({
|
newDecorations.push({
|
||||||
range: new monaco.Range(debuggerLine,1,debuggerLine,1),
|
range: new monaco.Range(debuggerLine,1,debuggerLine,1),
|
||||||
options: {
|
options: {
|
||||||
|
@ -111,23 +117,36 @@ class TextEditor extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if (this.props.file.content !== prevProps.file.content) {
|
if (this.props.currentFile.content && this.props.currentFile.content !== prevProps.currentFile.content) {
|
||||||
editor.setValue(this.props.file.content);
|
editor.setValue(this.props.currentFile.content);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateMarkers();
|
this.updateMarkers();
|
||||||
// TODO replace with const expectedDecorationsLength = this.props.debuggerLine ? this.props.breakpoints.length + 1 : this.props.breakpoints.length
|
const expectedDecorationsLength = this.props.debuggerLine ? this.props.breakpoints.length + 1 : this.props.breakpoints.length
|
||||||
const expectedDecorationsLength = this.props.breakpoints.length + 1;
|
if (expectedDecorationsLength !== this.state.decorations.length || this.props.debuggerLine !== prevProps.debuggerLine) {
|
||||||
if (expectedDecorationsLength !== this.state.decorations.length) {
|
|
||||||
this.updateDecorations();
|
this.updateDecorations();
|
||||||
}
|
}
|
||||||
this.updateLanguage();
|
this.updateLanguage();
|
||||||
this.handleResize();
|
this.handleResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderTabs() {
|
||||||
|
return (
|
||||||
|
<ul className="list-inline m-0 p-2">
|
||||||
|
{this.props.editorTabs.map(file => (
|
||||||
|
<li key={file.name} className={classNames("list-inline-item", "border-right", "p-2", { 'bg-dark': file.name === this.props.currentFile.name })}>
|
||||||
|
<a className="text-white no-underline" href='#switch-tab' onClick={() => this.props.addEditorTabs(file)}>{file.name}</a>
|
||||||
|
<FontAwesomeIcon onClick={() => this.props.removeEditorTabs(file)} className="mx-1" name="close" />
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="h-100 d-flex flex-column">
|
<div className="h-100 d-flex flex-column">
|
||||||
|
{this.renderTabs()}
|
||||||
<div style={{height: '100%'}} id={EDITOR_ID} />
|
<div style={{height: '100%'}} id={EDITOR_ID} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -136,10 +155,13 @@ class TextEditor extends React.Component {
|
||||||
|
|
||||||
TextEditor.propTypes = {
|
TextEditor.propTypes = {
|
||||||
onFileContentChange: PropTypes.func,
|
onFileContentChange: PropTypes.func,
|
||||||
file: PropTypes.object,
|
currentFile: PropTypes.object,
|
||||||
toggleBreakpoint: PropTypes.func,
|
toggleBreakpoint: PropTypes.func,
|
||||||
breakpoints: PropTypes.array,
|
breakpoints: PropTypes.array,
|
||||||
debuggerLine: PropTypes.number
|
debuggerLine: PropTypes.number,
|
||||||
|
editorTabs: PropTypes.array,
|
||||||
|
removeEditorTabs: PropTypes.func,
|
||||||
|
addEditorTabs: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TextEditor;
|
export default TextEditor;
|
||||||
|
|
|
@ -30,6 +30,9 @@ const TextEditorToolbar = (props) => (
|
||||||
<FontAwesomeIcon className="mr-2" name="file-text-o" /> Details
|
<FontAwesomeIcon className="mr-2" name="file-text-o" /> Details
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<NavLink className="btn" href="#" onClick={() => props.openAsideTab('logger')}>Logger</NavLink>
|
<NavLink className="btn" href="#" onClick={() => props.openAsideTab('logger')}>Logger</NavLink>
|
||||||
|
<NavLink className="btn" href="#" onClick={() => props.openAsideTab('debugger')}>
|
||||||
|
<FontAwesomeIcon className="mr-2" name="bug" /> Debugger
|
||||||
|
</NavLink>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
<NavLink className="btn" href="#" onClick={() => props.openAsideTab('browser')}>
|
<NavLink className="btn" href="#" onClick={() => props.openAsideTab('browser')}>
|
||||||
|
@ -42,7 +45,6 @@ const TextEditorToolbar = (props) => (
|
||||||
);
|
);
|
||||||
|
|
||||||
TextEditorToolbar.propTypes = {
|
TextEditorToolbar.propTypes = {
|
||||||
currentFile: PropTypes.object,
|
|
||||||
isContract: PropTypes.bool,
|
isContract: PropTypes.bool,
|
||||||
save: PropTypes.func,
|
save: PropTypes.func,
|
||||||
remove: PropTypes.func,
|
remove: PropTypes.func,
|
||||||
|
|
|
@ -4,48 +4,54 @@ import {Row, Col, Card, CardHeader, CardBody} from 'reactstrap';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import CardTitleIdenticon from './CardTitleIdenticon';
|
import CardTitleIdenticon from './CardTitleIdenticon';
|
||||||
|
import LoadMore from "./LoadMore";
|
||||||
|
|
||||||
const Transactions = ({transactions}) => (
|
const Transactions = ({transactions, showLoadMore, loadMore}) => (
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<h1>Transactions</h1>
|
<Card>
|
||||||
{transactions.map(transaction => (
|
<CardHeader>
|
||||||
<Card key={transaction.hash}>
|
<h2>Transactions</h2>
|
||||||
<CardHeader>
|
</CardHeader>
|
||||||
<CardTitleIdenticon id={transaction.hash}>Transaction
|
<CardBody>
|
||||||
<Link to={`/embark/explorer/transactions/${transaction.hash}`}>
|
{transactions.map(transaction => (
|
||||||
{transaction.hash}
|
<div className="explorer-row border-top" key={transaction.hash}>
|
||||||
</Link>
|
<CardTitleIdenticon id={transaction.hash}>Transaction
|
||||||
</CardTitleIdenticon>
|
<Link to={`/embark/explorer/transactions/${transaction.hash}`}>
|
||||||
</CardHeader>
|
{transaction.hash}
|
||||||
<CardBody>
|
</Link>
|
||||||
<Row>
|
</CardTitleIdenticon>
|
||||||
<Col>
|
<Row>
|
||||||
<strong>Block number</strong>
|
<Col md={6}>
|
||||||
<div>{transaction.blockNumber}</div>
|
<strong>Block number</strong>
|
||||||
</Col>
|
<div>{transaction.blockNumber}</div>
|
||||||
<Col>
|
</Col>
|
||||||
<strong>From</strong>
|
<Col md={6}>
|
||||||
<div>{transaction.from}</div>
|
<strong>From</strong>
|
||||||
</Col>
|
<div>{transaction.from}</div>
|
||||||
<Col>
|
</Col>
|
||||||
<strong>To</strong>
|
<Col md={6}>
|
||||||
<div>{transaction.to}</div>
|
<strong>To</strong>
|
||||||
</Col>
|
<div>{transaction.to}</div>
|
||||||
<Col>
|
</Col>
|
||||||
<strong>Type</strong>
|
<Col md={6}>
|
||||||
<div>{transaction.to ? "Contract Call" : "Contract Creation"}</div>
|
<strong>Type</strong>
|
||||||
</Col>
|
<div>{transaction.to ? "Contract Call" : "Contract Creation"}</div>
|
||||||
</Row>
|
</Col>
|
||||||
</CardBody>
|
</Row>
|
||||||
</Card>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
{showLoadMore && <LoadMore loadMore={() => loadMore()}/>}
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
|
||||||
Transactions.propTypes = {
|
Transactions.propTypes = {
|
||||||
transactions: PropTypes.arrayOf(PropTypes.object)
|
transactions: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
showLoadMore: PropTypes.bool,
|
||||||
|
loadMore: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Transactions;
|
export default Transactions;
|
||||||
|
|
|
@ -5,7 +5,6 @@ import PropTypes from 'prop-types';
|
||||||
import {blocks as blocksAction, initBlockHeader, stopBlockHeader} from '../actions';
|
import {blocks as blocksAction, initBlockHeader, stopBlockHeader} from '../actions';
|
||||||
import Blocks from '../components/Blocks';
|
import Blocks from '../components/Blocks';
|
||||||
import DataWrapper from "../components/DataWrapper";
|
import DataWrapper from "../components/DataWrapper";
|
||||||
import LoadMore from "../components/LoadMore";
|
|
||||||
import {getBlocks} from "../reducers/selectors";
|
import {getBlocks} from "../reducers/selectors";
|
||||||
|
|
||||||
class BlocksContainer extends Component {
|
class BlocksContainer extends Component {
|
||||||
|
@ -34,9 +33,8 @@ class BlocksContainer extends Component {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<DataWrapper shouldRender={this.props.blocks.length > 0} {...this.props} render={({blocks}) => (
|
<DataWrapper shouldRender={this.props.blocks.length > 0} {...this.props} render={({blocks}) => (
|
||||||
<Blocks blocks={blocks} />
|
<Blocks blocks={blocks} showLoadMore={(this.loadMoreFrom() >= 0)} loadMore={() => this.loadMore()} />
|
||||||
)} />
|
)} />
|
||||||
{(this.loadMoreFrom() >= 0) ? <LoadMore loadMore={() => this.loadMore()} /> : <React.Fragment />}
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {contractLogs as contractLogsAction, listenToContractLogs, startDebug, debugJumpBack, debugJumpForward, debugStepOverForward, debugStepOverBackward, debugStepIntoForward, debugStepIntoBackward} from '../actions';
|
||||||
|
|
||||||
|
import ContractDebugger from '../components/ContractDebugger';
|
||||||
|
import DataWrapper from "../components/DataWrapper";
|
||||||
|
import {getContractLogsByContract, debuggerInfo} from "../reducers/selectors";
|
||||||
|
|
||||||
|
class ContractDebuggerContainer extends Component {
|
||||||
|
componentDidMount() {
|
||||||
|
// if (this.props.contractLogs.length === 0) {
|
||||||
|
// this.props.listenToContractLogs();
|
||||||
|
// this.props.fetchContractLogs(this.props.contract.className);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<DataWrapper shouldRender={this.props.contractLogs !== undefined } {...this.props} render={() => (
|
||||||
|
<ContractDebugger contract={this.props.contract} startDebug={this.props.startDebug} debugJumpBack={this.props.debugJumpBack} debugJumpForward={this.props.debugJumpForward} debugStepOverForward={this.props.debugStepOverForward} debugStepOverBackward={this.props.debugStepOverBackward} debugStepIntoForward={this.props.debugStepIntoForward} debugStepIntoBackward={this.props.debugStepIntoBackward} debuggerInfo={this.props.debuggerInfo}
|
||||||
|
/>
|
||||||
|
)} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state, props) {
|
||||||
|
return {
|
||||||
|
contractLogs: getContractLogsByContract(state, props.contract.className),
|
||||||
|
debuggerInfo: debuggerInfo(state)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ContractDebuggerContainer.propTypes = {
|
||||||
|
contractLogs: PropTypes.array,
|
||||||
|
fetchContractLogs: PropTypes.func,
|
||||||
|
listenToContractLogs: PropTypes.func,
|
||||||
|
match: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
{
|
||||||
|
startDebug: startDebug.request,
|
||||||
|
debugJumpBack: debugJumpBack.request,
|
||||||
|
debugJumpForward: debugJumpForward.request,
|
||||||
|
debugStepOverForward: debugStepOverForward.request,
|
||||||
|
debugStepOverBackward: debugStepOverBackward.request,
|
||||||
|
debugStepIntoForward: debugStepIntoForward.request,
|
||||||
|
debugStepIntoBackward: debugStepIntoBackward.request
|
||||||
|
}
|
||||||
|
)(ContractDebuggerContainer);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
.editor--grid {
|
.editor--grid {
|
||||||
margin-left: -30px !important;
|
margin-left: -30px !important;
|
||||||
margin-right: -30px !important;
|
margin-right: -30px !important;
|
||||||
|
background-color: #1C1C1C;
|
||||||
}
|
}
|
|
@ -6,13 +6,11 @@ import TextEditorAsideContainer from './TextEditorAsideContainer';
|
||||||
import TextEditorContainer from './TextEditorContainer';
|
import TextEditorContainer from './TextEditorContainer';
|
||||||
import FileExplorerContainer from './FileExplorerContainer';
|
import FileExplorerContainer from './FileExplorerContainer';
|
||||||
import TextEditorToolbarContainer from './TextEditorToolbarContainer';
|
import TextEditorToolbarContainer from './TextEditorToolbarContainer';
|
||||||
import {currentFile as currentFileAction} from '../actions';
|
import {fetchEditorTabs as fetchEditorTabsAction} from '../actions';
|
||||||
import {getCurrentFile} from '../reducers/selectors';
|
import {getCurrentFile} from '../reducers/selectors';
|
||||||
|
|
||||||
import './EditorContainer.css';
|
import './EditorContainer.css';
|
||||||
|
|
||||||
const DEFAULT_FILE = {name: 'newContract.sol', content: ''};
|
|
||||||
|
|
||||||
class EditorContainer extends React.Component {
|
class EditorContainer extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
@ -20,9 +18,7 @@ class EditorContainer extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if(this.props.currentFile.content === '') {
|
this.props.fetchEditorTabs();
|
||||||
this.props.fetchCurrentFile();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
|
@ -32,7 +28,7 @@ class EditorContainer extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
isContract() {
|
isContract() {
|
||||||
return this.state.currentFile.name.endsWith('.sol');
|
return this.state.currentFile.name && this.state.currentFile.name.endsWith('.sol');
|
||||||
}
|
}
|
||||||
|
|
||||||
onFileContentChange(newContent) {
|
onFileContentChange(newContent) {
|
||||||
|
@ -83,7 +79,7 @@ class EditorContainer extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state, props) {
|
function mapStateToProps(state, props) {
|
||||||
const currentFile = getCurrentFile(state) || DEFAULT_FILE;
|
const currentFile = getCurrentFile(state);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentFile
|
currentFile
|
||||||
|
@ -92,11 +88,11 @@ function mapStateToProps(state, props) {
|
||||||
|
|
||||||
EditorContainer.propTypes = {
|
EditorContainer.propTypes = {
|
||||||
currentFile: PropTypes.object,
|
currentFile: PropTypes.object,
|
||||||
fetchCurrentFile: PropTypes.func
|
fetchEditorTabs: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
{fetchCurrentFile: currentFileAction.request},
|
{fetchEditorTabs: fetchEditorTabsAction.request},
|
||||||
)(EditorContainer);
|
)(EditorContainer);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {getContractsByPath} from "../reducers/selectors";
|
||||||
import ContractDetail from '../components/ContractDetail';
|
import ContractDetail from '../components/ContractDetail';
|
||||||
import ContractLoggerContainer from '../containers/ContractLoggerContainer';
|
import ContractLoggerContainer from '../containers/ContractLoggerContainer';
|
||||||
import ContractOverviewContainer from '../containers/ContractOverviewContainer';
|
import ContractOverviewContainer from '../containers/ContractOverviewContainer';
|
||||||
|
import ContractDebuggerContainer from '../containers/ContractDebuggerContainer';
|
||||||
|
|
||||||
class TextEditorAsideContainer extends Component {
|
class TextEditorAsideContainer extends Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -19,6 +20,17 @@ class TextEditorAsideContainer extends Component {
|
||||||
switch(this.props.currentAsideTab) {
|
switch(this.props.currentAsideTab) {
|
||||||
case 'browser':
|
case 'browser':
|
||||||
return <Preview />
|
return <Preview />
|
||||||
|
case 'debugger':
|
||||||
|
return this.props.contracts.map((contract, index) => {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardBody>
|
||||||
|
<CardTitle style={{"font-size": "2em"}}>{contract.className} - Details</CardTitle>
|
||||||
|
<ContractDebuggerContainer key={index} contract={contract} />
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
})
|
||||||
case 'detail':
|
case 'detail':
|
||||||
return this.props.contracts.map((contract, index) => {
|
return this.props.contracts.map((contract, index) => {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -3,20 +3,39 @@ import {connect} from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import TextEditor from '../components/TextEditor';
|
import TextEditor from '../components/TextEditor';
|
||||||
import {
|
import {
|
||||||
|
addEditorTabs as addEditorTabsAction,
|
||||||
|
fetchEditorTabs as fetchEditorTabsAction,
|
||||||
|
removeEditorTabs as removeEditorTabsAction,
|
||||||
toggleBreakpoint,
|
toggleBreakpoint,
|
||||||
} from '../actions';
|
} from '../actions';
|
||||||
import {getBreakpointsByFilename} from '../reducers/selectors';
|
|
||||||
|
|
||||||
const TextEditorContainer = (props) => (
|
import {getCurrentFile, getContractCompile, getContractDeploys, getBreakpointsByFilename, getDebuggerLine, getEditorTabs} from '../reducers/selectors';
|
||||||
<TextEditor file={props.currentFile}
|
|
||||||
breakpoints={props.breakpoints}
|
class TextEditorContainer extends React.Component {
|
||||||
toggleBreakpoint={props.toggleBreakpoint}
|
componentDidMount() {
|
||||||
onFileContentChange={props.onFileContentChange} />
|
this.props.fetchEditorTabs();
|
||||||
)
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<TextEditor file={this.props.currentFile}
|
||||||
|
currentFile={this.props.currentFile}
|
||||||
|
breakpoints={this.props.breakpoints}
|
||||||
|
toggleBreakpoint={this.props.toggleBreakpoint}
|
||||||
|
editorTabs={this.props.editorTabs}
|
||||||
|
removeEditorTabs={this.props.removeEditorTabs}
|
||||||
|
addEditorTabs={this.props.addEditorTabs}
|
||||||
|
debuggerLine={this.props.debuggerLine}
|
||||||
|
onFileContentChange={this.props.onFileContentChange} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function mapStateToProps(state, props) {
|
function mapStateToProps(state, props) {
|
||||||
const breakpoints = getBreakpointsByFilename(state, props.currentFile.name);
|
const breakpoints = getBreakpointsByFilename(state, props.currentFile.name);
|
||||||
return {breakpoints};
|
const editorTabs = getEditorTabs(state);
|
||||||
|
const debuggerLine = getDebuggerLine(state);
|
||||||
|
return {breakpoints, editorTabs, debuggerLine};
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditorContainer.propTypes = {
|
TextEditorContainer.propTypes = {
|
||||||
|
@ -24,9 +43,18 @@ TextEditorContainer.propTypes = {
|
||||||
onFileContentChange: PropTypes.func,
|
onFileContentChange: PropTypes.func,
|
||||||
toggleBreakpoints: PropTypes.func,
|
toggleBreakpoints: PropTypes.func,
|
||||||
breakpoints: PropTypes.array,
|
breakpoints: PropTypes.array,
|
||||||
|
toggleBreakpoint: PropTypes.object,
|
||||||
|
fetchEditorTabs: PropTypes.func,
|
||||||
|
removeEditorTabs: PropTypes.func,
|
||||||
|
addEditorTabs: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
{toggleBreakpoint},
|
{
|
||||||
|
toggleBreakpoint,
|
||||||
|
fetchEditorTabs: fetchEditorTabsAction.request,
|
||||||
|
removeEditorTabs: removeEditorTabsAction.request,
|
||||||
|
addEditorTabs: addEditorTabsAction.request
|
||||||
|
},
|
||||||
)(TextEditorContainer);
|
)(TextEditorContainer);
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {connect} from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import {transactions as transactionsAction, initBlockHeader, stopBlockHeader} from '../actions';
|
import {transactions as transactionsAction, initBlockHeader, stopBlockHeader} from '../actions';
|
||||||
import LoadMore from "../components/LoadMore";
|
|
||||||
import Transactions from '../components/Transactions';
|
import Transactions from '../components/Transactions';
|
||||||
import DataWrapper from "../components/DataWrapper";
|
import DataWrapper from "../components/DataWrapper";
|
||||||
import {getTransactions} from "../reducers/selectors";
|
import {getTransactions} from "../reducers/selectors";
|
||||||
|
@ -34,9 +33,9 @@ class TransactionsContainer extends Component {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<DataWrapper shouldRender={this.props.transactions.length > 0} {...this.props} render={({transactions}) => (
|
<DataWrapper shouldRender={this.props.transactions.length > 0} {...this.props} render={({transactions}) => (
|
||||||
<Transactions transactions={transactions} />
|
<Transactions transactions={transactions}
|
||||||
|
showLoadMore={(this.loadMoreFrom() >= 0)} loadMore={() => this.loadMore()} />
|
||||||
)} />
|
)} />
|
||||||
{(this.loadMoreFrom() > 0) ? <LoadMore loadMore={() => this.loadMore()} /> : <React.Fragment />}
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
|
@ -0,0 +1,360 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="224" height="216" id="svg2" version="1.1" inkscape:version="0.92.2pre0 (973e216, 2017-07-25)" sodipodi:docname="largeIcons.svg">
|
||||||
|
<metadata id="metadata606">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs id="defs604"/>
|
||||||
|
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1946" inkscape:window-height="1546" id="namedview602" showgrid="true" inkscape:zoom="4.3703705" inkscape:cx="92.781028" inkscape:cy="118.13064" inkscape:window-x="1047" inkscape:window-y="228" inkscape:window-maximized="0" inkscape:current-layer="svg2" inkscape:snap-grids="true" showguides="true" inkscape:guide-bbox="true">
|
||||||
|
<inkscape:grid type="xygrid" id="grid3583" empspacing="5" visible="true" enabled="true" snapvisiblegridlinesonly="true" spacingx="28" spacingy="24" originx="0" originy="0"/>
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<g id="g4">
|
||||||
|
<g transform="translate(-322,-72)" id="g8">
|
||||||
|
<circle transform="translate(326,74)" cx="15" cy="17" r="3" id="circle10" sodipodi:cx="15" sodipodi:cy="17" sodipodi:rx="3" sodipodi:ry="3" style="fill:#009802"/>
|
||||||
|
<path d="m 329,77 h 18 v 18 h -18 z" id="path12" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path d="m 327.25,75.25 h 20 v 20 h -20 z" id="path14" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path d="m 325.12,73.125 h 20 v 20 h -20 z" id="path16" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(26,0)" id="g18">
|
||||||
|
<path transform="translate(-32,0)" d="M 57,12 53.5,8 H 39 v 8 h 14.5" id="path22" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(-2.003,24)" id="g24">
|
||||||
|
<path transform="translate(-224,-120)" d="m 240.77,127 h -1.534 v 4.233 h -4.233 v 1.534 h 4.233 V 137 h 1.534 v -4.233 h 4.233 v -1.534 H 240.77 V 127 z" id="path28" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(26,24)" id="g30">
|
||||||
|
<path transform="translate(-96,-145)" d="m 103,148 h 18 v 18 h -18 z" id="path34" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-96,-145)" d="m 115.42,154.7 -6.705,-6.705 -1.0575,1.0575 1.785,1.785 -3.8625,3.8625 c -0.4425,0.4425 -0.4425,1.155 0,1.59 l 4.125,4.125 c 0.2175,0.2175 0.51,0.33 0.795,0.33 0.285,0 0.5775,-0.1125 0.795,-0.33 l 4.125,-4.125 c 0.4425,-0.435 0.4425,-1.1475 0,-1.59 z m -8.5125,0.795 3.5925,-3.5925 3.5925,3.5925 h -7.185 z m 10.342,1.125 c 0,0 -1.5,1.6275 -1.5,2.625 0,0.825 0.675,1.5 1.5,1.5 0.825,0 1.5,-0.675 1.5,-1.5 0,-0.9975 -1.5,-2.625 -1.5,-2.625 z" id="path36" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-96,-145)" d="m 103,163 h 18 v 3 h -18 z" id="path38" inkscape:connector-curvature="0" style="fill-opacity:0.36000001"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(0,48)" id="g40">
|
||||||
|
<path transform="translate(7,3)" d="M 0,0 H 18 V 18 H 0 z" id="path44" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(7,3)" d="m 13,5 h 1.4936 C 15.32558,5 16,5.67154 16,6.5064 v 7.9871 c 0,0.83198 -0.67154,1.5064 -1.5064,1.5064 H 6.5065 c -0.83198,0 -1.5064,-0.67154 -1.5064,-1.5064 v -1.4936 h 6.4936 c 0.8349,0 1.5064,-0.67446 1.5064,-1.5064 V 4.9999 z" id="path46" inkscape:connector-curvature="0" style="fill-opacity:0.36000001"/>
|
||||||
|
<path transform="translate(7,3)" d="M 3.5,2 C 2.669,2 2,2.669 2,3.5 v 8 C 2,12.331 2.669,13 3.5,13 h 8 c 0.831,0 1.5,-0.669 1.5,-1.5 v -8 C 13,2.669 12.331,2 11.5,2 h -8 z m 0,1.5 h 8 v 8 h -8 v -8 z" id="path48" inkscape:connector-curvature="0" style="fill:#212121"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(26,48)" id="g50">
|
||||||
|
<path transform="translate(-96,-24)" d="m 107,33 h 8 v 6 h -8 z" stroke-miterlimit="4.2" id="path54" inkscape:connector-curvature="0" style="stroke:#000000;stroke-width:2;stroke-miterlimit:4.19999981"/>
|
||||||
|
<path transform="translate(-96,-24)" d="m 115,36 4,-4 v 8" id="path56" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(54,0)" id="g58">
|
||||||
|
<g id="g62" style="stroke:#000000">
|
||||||
|
<path transform="matrix(0.36,0,0,0.36,-2.5,7.46)" d="m 53,14 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" id="path64" inkscape:connector-curvature="0" style="fill-rule:evenodd;stroke-width:2.77800012"/>
|
||||||
|
<path transform="translate(-128,-120)" d="m 143.48,129.5 2.5403,-2 h -1.5242 v -2 h -2 l -0.0161,2 h -1.5403 z" id="path66" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-128,-120)" d="m 146.5,132.5 2,2.5 v -1.4998 l 2,-1e-4 v -2.0002 l -2,1e-4 V 130 z" id="path68" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-128,-120)" d="m 143.5,135.5 -2.5,2 h 1.5 v 2 h 2 v -2 h 1.5 z" id="path70" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-128,-120)" d="m 140.5,132.5 -2,-2.5 v 1.4999 h -2 v 2.0002 l 2,-3e-4 V 135 z" id="path72" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(56,24)" id="g74">
|
||||||
|
<g id="g78" style="fill-rule:evenodd">
|
||||||
|
<path transform="matrix(0.9018,0,0,0.9018,4.308,4.525)" d="M 0,0 H 18 V 18 H 0 z" id="path80" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="matrix(0.9018,0,0,0.9018,4.308,4.525)" d="M 4.174,8.343 2.76,9.757 7.003,13.999 15.488,5.514 14.074,4.1 7.003,11.171 z" id="path82" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(57,47)" id="g84">
|
||||||
|
<path transform="translate(-68,-143)" d="M 76.94,152 76,152.94 79.0533,156 76,159.06 l 0.94,0.94 4,-4 z" id="path88" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-68,-143)" d="M 80.94,152 80,152.94 83.0533,156 80,159.06 l 0.94,0.94 4,-4 z" id="path90" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(-2,72)" id="g92">
|
||||||
|
<path transform="translate(-64,0)" d="m 80.44,16.94 c -2.48,0 -4.5,-2.02 -4.5,-4.5 0,-0.88 0.26,-1.7 0.69,-2.39 l 6.2,6.2 c -0.69,0.44 -1.51,0.69 -2.39,0.69 m 4.5,-4.5 c 0,0.88 -0.26,1.7 -0.69,2.39 l -6.2,-6.2 c 0.69,-0.44 1.51,-0.69 2.39,-0.69 2.48,0 4.5,2.02 4.5,4.5 M 80.5,6 C 76.91,6 74,8.91 74,12.5 74,16.09 76.91,19 80.5,19 84.09,19 87,16.09 87,12.5 87,8.91 84.09,6 80.5,6" id="path96" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(28,72)" id="g98">
|
||||||
|
<g id="g102" style="fill-rule:evenodd">
|
||||||
|
<path transform="matrix(0.87153,0,0,0.87153,4.071,4.568)" d="M 0,0 H 18 V 18 H 0 z" id="path104" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="matrix(0.87153,0,0,0.87153,4.071,4.568)" d="M 12,3.5 A 1.505,1.505 0 0 0 10.494,2 H 4.506 C 3.676,2 3,2.674 3,3.506 v 7.988 C 3,12.326 3.671,12.997 4.5,13 V 3.5 H 12 z M 6,6.506 C 6,5.674 6.676,5 7.506,5 h 5.988 C 14.326,5 15,5.672 15,6.506 v 7.988 C 15,15.326 14.324,16 13.494,16 H 7.506 A 1.505,1.505 0 0 1 6,14.494 V 6.506 z M 7.5,6.5 h 6 v 8 h -6 v -8 z" id="path106" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(54,72)" id="g108">
|
||||||
|
<path transform="translate(0,-24)" d="M 25,36 21.36,32 H 19.57 L 14,40 h 7.36 L 25,36 z" id="path112" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-24)" d="m 7,32 v 8 H 9.05 L 14,32 H 7 z" id="path114" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-24)" d="M 9.67,44.55 8.08,43.23 18.84,27.45 20.43,28.77 9.67,44.55 z" id="path116" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-24)" d="M 0,24 H 24 V 48 H 0 z" id="path118" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(0,-24)" d="M 0,24 H 24 V 48 H 0 z m 0,0 H 24 V 48 H 0 z m 0,0 H 24 V 48 H 0 z m 0,0 H 24 V 48 H 0 z" id="path120" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(0,-24)" d="M 0,24 H 24 V 48 H 0 z" id="path122" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(0,-24)" d="M 0,24 H 24 V 48 H 0 z" id="path124" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(0,-24)" d="M 0,24 H 24 V 48 H 0 z" id="path126" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(82,0)" id="g128">
|
||||||
|
<path transform="translate(-128,0)" d="M 149,8.33 147.67,7 144,10.67 140.33,7 139,8.33 142.67,12 139,15.67 140.33,17 144,13.33 147.67,17 149,15.67 145.33,12 149,8.33 z" id="path132" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(82,24)" id="g134">
|
||||||
|
<path transform="translate(-32,-24)" d="M 53,37 H 43 v -5 h 10 v 5 z M 41,42 H 55 V 30 H 41 v 12 z" id="path138" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(82,48)" id="g140">
|
||||||
|
<path transform="translate(-224,-48)" d="m 238,64 h 7 v -8 h -7 z m 9,2 H 233 V 54 h 14 z" id="path144" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(82,72)" id="g146">
|
||||||
|
<path transform="translate(-256,-48)" d="m 274,64 h -7 v -8 h 7 v 8 z m -9,2 h 14 V 54 h -14 v 12 z" id="path150" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(-2,96)" id="g152">
|
||||||
|
<path transform="translate(-160,0)" d="m 169,16.089 v 2.9105 h 2.9105 L 180.1944,10.7156 177.2838,7.8051 169,16.089 z m 13.769,-7.9387 c 0.30785,-0.30785 0.30785,-0.79294 0,-1.1008 l -1.8191,-1.8191 c -0.30785,-0.30784 -0.79295,-0.30784 -1.1008,0 l -1.5206,1.5299 2.9105,2.9105 1.5299,-1.5206 z" id="path156" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(26,96)" id="g158">
|
||||||
|
<path transform="translate(-288,-120)" d="m 310.77,127.04 -1.816,-1.8164 c -0.30331,-0.30338 -0.79716,-0.30338 -1.1005,0 l -2.4304,2.4309 -1.4894,-1.4935 -1.1005,1.1007 1.1044,1.1046 -6.9373,6.9348 v 3.695 h 3.6942 l 6.9373,-6.9387 1.1005,1.1046 1.1005,-1.1007 -1.4932,-1.4935 2.4304,-2.4309 c 0.3072,-0.30338 0.3072,-0.79345 0,-1.0968 z m -10.721,10.4 -1.4932,-1.4935 6.2724,-6.2736 1.4932,1.4935 -6.2723,6.2736 z" id="path162" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(54,96)" id="g164">
|
||||||
|
<path transform="translate(-32,-48)" d="m 44,59 2,3 v 4 h 4 v -4 l 2,-3 z" id="path168" inkscape:connector-curvature="0" style="opacity:0.5;fill:#424242"/>
|
||||||
|
<path transform="translate(-32,-48)" d="m 46.5,65.23 c 0.32,0.13 0.84,0.24 1.47,0.24 0.59,0 1.14,-0.1 1.53,-0.26 v -3.93 l 4,-4.57 v -0.19 h -11 v 0.22 l 4,4.57 v 3.93 z M 47.97,67 C 46.81,66.91 45.82,66.71 45,66.01 V 61.89 L 41,57.32 V 55 h 14 v 2.35 l -4,4.57 v 4.13 c -0.92,0.67 -2.1,0.94 -3.03,0.95" id="path170" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(82.001,96)" id="g172">
|
||||||
|
<path transform="matrix(0.75,0,0,0.75,-74.421,-143.43)" d="m 108.56,195.24 h 24 v 24 h -24 z" id="path176" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="matrix(0.75,0,0,0.75,-74.421,-143.43)" d="m 108.56,215.24 h 24 v 4 h -24 z" id="path178" inkscape:connector-curvature="0" style="fill-opacity:0.36000001"/>
|
||||||
|
<path transform="matrix(0.75,0,0,0.75,-74.421,-143.43)" d="m 119.56,198.24 -5.5,14 h 2.25 l 1.12,-3 h 6.25 l 1.12,3 h 2.25 l -5.49,-14 h -2 z m -1.38,9 2.38,-6.33 2.38,6.33 h -4.76 z" id="path180" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(106,1)" id="g182">
|
||||||
|
<path transform="matrix(0,-1,1,0,-112,-260)" d="m -278.5,126.5 h 14 v 12 h -14 z" id="path186" inkscape:connector-curvature="0" style="fill:none;stroke:#000000"/>
|
||||||
|
<path transform="matrix(0,1,1,0,-112,-260)" d="m 272,132.5 -5,-3.25 v 6.5" id="path188" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="matrix(0,-1,1,0,-112,-260)" d="m -275,126 h 1 v 13 h -1 z" id="path190" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<path style="fill:none;stroke:#000000" inkscape:connector-curvature="0" id="path196" d="m 119.5,30.5 h 14 v 12 h -14 z"/>
|
||||||
|
<path inkscape:connector-curvature="0" id="path198" d="m 126,36.5 5,-3.25 v 6.5"/>
|
||||||
|
<path inkscape:connector-curvature="0" id="path200" d="m 123,30 h 1 v 13 h -1 z"/>
|
||||||
|
<g transform="translate(111,48)" id="g202">
|
||||||
|
<path transform="matrix(-1,0,0,1,-192,-120)" d="m -214.5,126.5 h 14 v 12 h -14 z" id="path206" inkscape:connector-curvature="0" style="fill:none;stroke:#000000"/>
|
||||||
|
<path transform="translate(-192,-120)" d="m 208,132.5 -5,-3.25 v 6.5" id="path208" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="matrix(-1,0,0,1,-192,-120)" d="m -211,126 h 1 v 13 h -1 z" id="path210" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(106,73)" id="g212">
|
||||||
|
<path transform="matrix(0,1,1,0,-88,283)" d="m -278.5,102.5 h 14 v 12 h -14 z" id="path216" inkscape:connector-curvature="0" style="fill:none;stroke:#000000"/>
|
||||||
|
<path transform="matrix(0,-1,1,0,-88,283)" d="m 272,108.5 -5,-3.25 v 6.5" id="path218" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="matrix(0,1,1,0,-88,283)" d="m -275,102 h 1 v 13 h -1 z" id="path220" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(110,96)" id="g222">
|
||||||
|
<path transform="translate(-224,0)" d="m 237,11 h -4 V 7 h 4 v 4 z" id="path226" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-224,0)" d="m 247,9 h -9 V 7 h 9 v 2 z" id="path228" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-224,0)" d="m 247,11 h -9 v -1 h 9 v 1 z" id="path230" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-224,0)" d="m 247,15 h -9 v -2 h 9 v 2 z" id="path232" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-224,0)" d="m 237,17 h -4 v -4 h 4 v 4 z" id="path234" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-224,0)" d="m 247,17 h -9 v -1 h 9 v 1 z" id="path236" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(-2,120)" id="g238">
|
||||||
|
<path transform="translate(0,-144)" d="m 23,157 h -2 v 2 h 2 z" id="path242" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-144)" d="m 23,161 h -2 v 2 c 1,0 2,-1 2,-2 z" id="path244" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-144)" d="m 23,153 h -2 v 2 h 2 z" id="path246" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-144)" d="m 21,149 v 2 h 2 c 0,-1 -1,-2 -2,-2 z" id="path248" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-144)" d="m 11,163 h 4 v -6 H 9 v 4 c 0,1.1 0.9,2 2,2 z" id="path250" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-144)" d="M 11,153 H 9 v 2 h 2 z" id="path252" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-144)" d="m 19,149 h -2 v 2 h 2 z" id="path254" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-144)" d="m 19,161 h -2 v 2 h 2 z" id="path256" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-144)" d="m 11,149 c -1,0 -2,1 -2,2 h 2 z" id="path258" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-144)" d="m 15,149 h -2 v 2 h 2 z" id="path260" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(26,120)" id="g262">
|
||||||
|
<path transform="translate(-290,-46)" d="m 317,69 v -5 l -5,5 h 5 z" id="path266" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(54,120)" id="g268">
|
||||||
|
<g id="g272" style="fill-rule:evenodd">
|
||||||
|
<path transform="matrix(1.4142,0,0,1.4142,-278.88,-36.772)" d="m 209.92,31.305 a 1.0607,1.0607 0 1 1 -2.1213,0 1.0607,1.0607 0 1 1 2.1213,0 z" id="path274" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="matrix(1.4142,0,0,1.4142,-278.88,-31.772)" d="m 209.92,31.305 a 1.0607,1.0607 0 1 1 -2.1213,0 1.0607,1.0607 0 1 1 2.1213,0 z" id="path276" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="matrix(1.4142,0,0,1.4142,-278.88,-26.772)" d="m 209.92,31.305 a 1.0607,1.0607 0 1 1 -2.1213,0 1.0607,1.0607 0 1 1 2.1213,0 z" id="path278" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(84,120)" id="g280">
|
||||||
|
<path transform="translate(-162,-144)" d="m 166,147 h 18 v 18 h -18 z" id="path284" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-162,-144)" d="m 181.52,154.53 c -0.51,-2.58 -2.7862,-4.5262 -5.5162,-4.5262 -2.1675,0 -4.0462,1.23 -4.9875,3.0262 -2.2538,0.24375 -4.0125,2.1525 -4.0125,4.4738 0,2.4862 2.0138,4.5 4.5,4.5 h 9.75 c 2.07,0 3.75,-1.68 3.75,-3.75 0,-1.98 -1.5412,-3.585 -3.4838,-3.7238 z m -0.26625,5.9738 h -9.75 c -1.6575,0 -3,-1.3425 -3,-3 0,-1.6575 1.3425,-3 3,-3 h 0.5325 c 0.49125,-1.7288 2.0775,-3 3.9675,-3 2.28,0 4.125,1.845 4.125,4.125 v 0.375 h 1.125 c 1.2412,0 2.25,1.0088 2.25,2.25 0,1.2412 -1.0088,2.25 -2.25,2.25 z" id="path286" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(112,120)" id="g288">
|
||||||
|
<path transform="translate(-226,-72)" d="m 235,76 c -0.55,0 -0.99,0.45 -0.99,1 L 234,91 c 0,0.55 0.44,1 1,1 h 10 c 0.55,0 1,-0.45 1,-1 V 81 l -5,-5 h -6 z m 6,5 v -4 l 4,4 h -4 z" id="path292" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-226,-72)" d="m 231,75 h 18 v 18 h -18 z" id="path294" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(140,0)" id="g296">
|
||||||
|
<path transform="translate(-162,-24)" d="m 169,29 h 18 v 18 h -18 z" id="path300" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-162,-24)" d="m 167.25,27.25 h 20 v 20 h -20 z" id="path302" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-162,-24)" d="m 165.12,25.125 h 20 v 20 h -20 z" id="path304" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-162,-24)" d="m 171,28 c -0.55,0 -1,0.45 -1,1 v 14 c 0,0.55 0.44,1 1,1 h 5.0938 c -0.0656,-0.32311 -0.0937,-0.65753 -0.0937,-1 0,-2.7614 2.2386,-5 5,-5 0.34247,0 0.67689,0.02816 1,0.09375 v -5.0938 l -5,-5 h -6 z m 6,1 4,4 h -4 v -4 z" id="path306" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(140,24)" id="g308">
|
||||||
|
<path transform="translate(-66,-120)" d="m 71,124 h 18 v 18 H 71 z" id="path312" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-66,-120)" d="m 82,129 -2,-2 h -5 c -0.55,0 -1,0.45 -1,1 v 10 c 0,0.55 0.45,1 1,1 h 12 c 0.55,0 1,-0.45 1,-1 v -8 c 0,-0.55 -0.45,-1 -1,-1 h -5 z" id="path314" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(140,48)" id="g316">
|
||||||
|
<path transform="translate(-258,-144)" d="m 278,150 h -10.5 c -0.8325,0 -1.5,0.675 -1.5,1.5 v 9 c 0,0.825 0.6675,1.5 1.5,1.5 H 278 c 0.825,0 1.5,-0.675 1.5,-1.5 v -9 c 0,-0.825 -0.6675,-1.5 -1.5,-1.5 z m 0,10.5 H 267.5 V 153 H 278 v 7.5 z" id="path320" inkscape:connector-curvature="0" style="fill:#010101"/>
|
||||||
|
<path transform="translate(-258,-144)" d="m 262.97,147.07 h 18 v 18 h -18 z" id="path322" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(140,72)" id="g324">
|
||||||
|
<path transform="translate(6,3.9)" d="M 9,1 H 3.9954 C 3.45567,1 3,1.45078 3,2.0068 v 11.986 c 0,0.5569 0.44565,1.0068 0.9954,1.0068 h 8.0092 C 12.54433,14.9996 13,14.54882 13,13.9928 V 4.9996 l -4,-4 z m 3,4 H 9 V 2 l 3,3 z M 6,7 11,9.5 6,12 V 7 z" id="path328" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(140,96)" id="g330">
|
||||||
|
<g id="g334" style="stroke:#000000">
|
||||||
|
<path transform="matrix(0.72907,0,0,0.72907,5.617,4.598)" d="M 7.854,6.963 6.877,7.279 6.857,8.617 6.889,8.705 7.398,9.699 6.188,10.578 5.398,9.787 5.326,9.73 4.047,9.336 3.443,10.166 4.213,11.26 4.291,11.313 5.287,11.817 4.824,13.241 3.72,13.065 3.628,13.061 2.362,13.493 v 1.027 l 1.266,0.434 0.092,-0.004 1.104,-0.178 0.463,1.424 -0.996,0.506 -0.078,0.051 -0.77,1.094 0.604,0.83 1.279,-0.393 0.072,-0.059 0.789,-0.791 1.211,0.879 -0.51,0.996 -0.031,0.086 0.02,1.338 0.977,0.316 0.803,-1.068 0.025,-0.09 0.172,-1.104 h 1.498 l 0.172,1.104 0.025,0.09 0.803,1.068 0.977,-0.316 0.02,-1.338 -0.031,-0.086 -0.51,-0.996 1.211,-0.879 0.789,0.791 0.072,0.059 1.279,0.393 0.604,-0.83 -0.771,-1.094 -0.076,-0.051 -0.996,-0.506 0.461,-1.424 1.105,0.178 0.092,0.004 1.266,-0.434 v -1.027 l -1.266,-0.432 -0.092,0.004 -1.105,0.176 -0.461,-1.424 0.996,-0.504 0.076,-0.053 0.771,-1.094 L 15.159,9.336 13.88,9.731 13.808,9.788 13.019,10.579 11.808,9.7 12.318,8.706 12.349,8.618 12.329,7.28 11.352,6.964 10.549,8.034 10.524,8.122 10.352,9.227 H 8.854 L 8.682,8.121 8.656,8.03 7.854,6.963 m 1.748,3.398 a 3.621,3.645 0 0 1 3.621,3.645 3.621,3.645 0 0 1 -3.621,3.646 3.621,3.645 0 0 1 -3.619,-3.646 3.621,3.645 0 0 1 3.619,-3.645 z" id="path336" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="matrix(0.72907,0,0,0.72907,5.227,3.617)" d="M 14.885,1.563 14.178,1.957 14.365,3.24 14.396,3.279 15.14,4.04 14.553,5.03 13.529,4.736 13.479,4.729 12.262,5.172 12.25,5.98 13.455,6.459 13.506,6.453 14.537,6.189 15.1,7.191 14.332,7.932 14.301,7.971 14.08,9.248 14.771,9.662 15.787,8.859 15.807,8.811 16.1,7.787 17.242,7.803 17.502,8.834 17.52,8.883 18.514,9.715 19.219,9.32 19.03,8.04 19,7.998 18.258,7.234 18.844,6.25 19.869,6.541 19.92,6.551 21.14,6.105 21.15,5.297 19.943,4.818 19.893,4.824 18.861,5.088 18.301,4.086 19.07,3.346 19.1,3.307 19.322,2.029 18.627,1.615 17.609,2.418 17.59,2.467 17.303,3.49 16.16,3.475 15.896,2.443 15.879,2.395 14.885,1.563 z m 1.814,2.138 a 1.938,1.938 0 0 1 1.938,1.938 1.938,1.938 0 0 1 -1.938,1.937 1.938,1.938 0 0 1 -1.937,-1.937 1.938,1.938 0 0 1 1.937,-1.938 z" id="path338" inkscape:connector-curvature="0" style="stroke-width:0.89899999"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(138,120)" id="g340">
|
||||||
|
<g id="g344" style="fill:none">
|
||||||
|
<path transform="translate(8,4)" d="M 0,0 H 16 V 16 H 0 V 0 z" id="path346" inkscape:connector-curvature="0" style="opacity:0.5"/>
|
||||||
|
<path transform="translate(8,4)" d="M 6,14 H 3.5 C 2.5,14 2,13.5 2,12.5 v -9 C 2,2.5 2.5,2 3.5,2 h 9 C 14,2 14,3.4678 14,3.5 V 6 H 13 V 3 H 3 v 10 h 3 v 1 z m 9,-5 -3,2 3,3 -1,1 -3,-3 -2,3 -2,-8 8,2 z" id="path348" inkscape:connector-curvature="0" style="fill:#000000"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(0,144)" id="g350">
|
||||||
|
<path transform="translate(-98,-120)" d="m 110.5,127.5 h -1 l 2,-2 2,2 h -1 c 0,0 -0.0345,4.6379 -0.0345,4.0345 l 4.0345,-0.034 v -1 l 2,2 -2,2 v -1 l -4.0345,-0.034 0.0345,4.0346 h 1 l -2,2 -2,-2 h 1 l 0.0345,-4.0346 -4.0345,0.034 v 1 l -2,-2 2,-2 v 1 l 4.0345,0.034 z" id="path354" inkscape:connector-curvature="0" style="stroke:#000000"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(26,144)" id="g356">
|
||||||
|
<path transform="translate(-320,0)" d="m 333.6,15.2 h 1.6 V 8.8 h -1.6 v 6.4 z M 336,4 c -4.42,0 -8,3.58 -8,8 0,4.42 3.58,8 8,8 4.42,0 8,-3.58 8,-8 0,-4.42 -3.58,-8 -8,-8 z m 0,14.4 c -3.528,0 -6.4,-2.872 -6.4,-6.4 0,-3.528 2.872,-6.4 6.4,-6.4 3.528,0 6.4,2.872 6.4,6.4 0,3.528 -2.872,6.4 -6.4,6.4 z m 0.8,-3.2 h 1.6 V 8.8 h -1.6 v 6.4 z" id="path360" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(54,144)" id="g362">
|
||||||
|
<path transform="translate(-32,-72)" d="m 47,88 h -3 v -8 h 3 v 8 z" id="path366" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-32,-72)" d="m 53,88 h -3 v -8 h 3 v 8 z" id="path368" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(82,144)" id="g370">
|
||||||
|
<path transform="translate(-256,0)" d="m 275,15 h -2 V 9 h 2 z m -4,0 h -2 V 9 h 2 z m 4,-10 h -6 l -4,4 v 6 l 4,4 h 6 l 4,-4.12 V 9 z" id="path374" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(110,144)" id="g376">
|
||||||
|
<g font-weight="400" id="g380" style="font-weight:400;font-family:Sans">
|
||||||
|
<path transform="translate(-289,-96)" d="m 300,101 v 4.0001 1.0001 l 3.3434,0.53115 -0.0156,8.0468 -1.3278,0.42183 c 0.006,0.59278 0.43931,1.0114 1,1 h 8 c 0.57896,0.002 0.98177,-0.42708 1,-1 v -14 c -0.0102,-0.53477 -0.48177,-0.99739 -1,-1 h -10 c -0.53297,0.008 -0.99716,0.45677 -1,1 z m 1,0 h 10 v 14 h -8 l 0.71845,-0.42179 0.0937,-8.4218 -2.8122,-0.1561 v -0.99993 z" overflow="visible" style="text-indent:0;line-height:normal;text-transform:none;block-progression:tb;overflow:visible" id="path382" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-289,-96)" d="m 297,106 v 9 c 0.006,0.59278 0.43931,1.0114 1,1 h 5 c 0.57896,0.002 0.98177,-0.42708 1,-1 v -9 c -0.0102,-0.53477 -0.48177,-0.99739 -1,-1 h -5 c -0.53297,0.008 -0.99716,0.45677 -1,1 z m 1,1.0002 h 5 v 7 h -5 z" overflow="visible" style="text-indent:0;line-height:normal;text-transform:none;block-progression:tb;overflow:visible" id="path384" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(138,144)" id="g386">
|
||||||
|
<path transform="translate(-320,-48)" d="m 328,60 c 0,4.42 3.58,8 8,8 4.42,0 8,-3.58 8,-8 0,-4.42 -3.58,-8 -8,-8 -4.42,0 -8,3.58 -8,8 z m 8,6.4 c -3.528,0 -6.4,-2.872 -6.4,-6.4 0,-3.528 2.872,-6.4 6.4,-6.4 3.528,0 6.4,2.872 6.4,6.4 0,3.528 -2.872,6.4 -6.4,6.4 z M 334.5067,63.4286 339.0781,60 334.5067,56.5714 v 6.8571 z" id="path390" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(-2,168)" id="g392">
|
||||||
|
<path transform="translate(-96,-48)" d="m 108,60 10,-5 v 10" id="path396" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(26,168)" id="g398">
|
||||||
|
<path transform="translate(-64,-48)" d="M 86,60 76,55 v 10" id="path402" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(54,168)" id="g404">
|
||||||
|
<path transform="translate(-256,-24)" d="m 268.01,35.99 c 0.61,0.28 1.07,0.9 1.07,1.58 0.11,0.85 -0.05,1.72 0.12,2.57 0.27,0.54 1,0.28 1.43,0.55 0.49,0.24 0.48,1.01 -0.06,1.18 -0.56,0.22 -1.18,0.08 -1.74,-0.05 -0.71,-0.2 -1.41,-0.72 -1.5,-1.5 -0.18,-0.89 0.01,-1.8 -0.16,-2.68 -0.22,-0.64 -0.94,-0.9 -1.57,-0.93 -0.58,-0.1 -0.83,-0.94 -0.35,-1.3 0.51,-0.35 1.26,-0.14 1.69,-0.66 0.44,-0.48 0.29,-1.18 0.32,-1.78 0,-0.81 -0.02,-1.77 0.65,-2.34 0.66,-0.54 1.58,-0.71 2.41,-0.63 0.63,0 0.98,0.87 0.4,1.22 -0.44,0.37 -1.2,0.06 -1.51,0.65 -0.14,0.56 -0.05,1.15 -0.07,1.73 -0.01,0.75 -0.05,1.64 -0.72,2.13 -0.12,0.1 -0.26,0.19 -0.4,0.26" id="path408" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-256,-24)" d="m 276.98,35.99 c -0.67,-0.3 -1.08,-1.02 -1.08,-1.75 -0.07,-0.76 0.03,-1.52 -0.06,-2.28 -0.24,-0.58 -0.98,-0.4 -1.46,-0.59 -0.59,-0.24 -0.48,-1.18 0.14,-1.31 0.73,-0.15 1.52,-0.01 2.18,0.32 0.56,0.28 0.95,0.86 0.99,1.48 0.13,0.83 -0.03,1.68 0.13,2.5 0.2,0.68 0.94,0.83 1.54,0.9 0.56,0.07 0.86,0.8 0.46,1.21 -0.44,0.46 -1.2,0.2 -1.65,0.66 -0.51,0.46 -0.4,1.21 -0.4,1.83 -0.03,0.78 0.06,1.69 -0.52,2.3 -0.74,0.65 -1.8,0.86 -2.75,0.68 -0.52,-0.16 -0.69,-1.01 -0.15,-1.25 0.44,-0.23 1.02,-0.08 1.41,-0.45 0.26,-0.45 0.09,-0.98 0.14,-1.47 0.01,-0.76 -0.07,-1.63 0.43,-2.26 0.18,-0.21 0.42,-0.37 0.66,-0.51" id="path410" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(82,168)" id="g412">
|
||||||
|
<g id="g416">
|
||||||
|
<path d="M 0,0 H 24 V 24 H 0 z" id="path418" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path d="m 16,6 c -3.31,0 -6,2.69 -6,6 0,3.31 2.69,6 6,6 3.31,0 6,-2.69 6,-6 h -2 c 0,2.2091 -1.7909,4 -4,4 -2.2091,0 -4,-1.7909 -4,-4 0,-2.2091 1.7909,-4 4,-4 1.2756,0 2.3926,0.60127 3.125,1.5312 h 2.3438 C 20.52659,7.4496 18.4308,6 16,6 z" id="path420" inkscape:connector-curvature="0"/>
|
||||||
|
<path d="M 21.091,6.88 V 9.9718 H 17.9992 z" id="path422" inkscape:connector-curvature="0" style="stroke:#000000;stroke-width:1.06799996"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(110,168)" id="g424">
|
||||||
|
<path transform="translate(8,4)" d="M 2.5858,13.891 C 0.9959,12.4291 0,10.3315 0,8.0002 c 0,-4.42 3.58,-8 8,-8 4.42,0 8,3.58 8,8 0,4.42 -3.58,8 -8,8 v -1.6 c 3.528,0 6.4,-2.872 6.4,-6.4 0,-3.528 -2.872,-6.4 -6.4,-6.4 -3.528,0 -6.4,2.872 -6.4,6.4 0,1.9357 0.86461,3.674 2.2278,4.8487 l 1.6925,-1.4201 0.015145,4.463 -4.3925,-0.7899 1.443,-1.2108 z M 6.5066,11.4287 11.078,8.0001 6.5066,4.5715 v 6.8571 z" id="path428" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(138,168)" id="g430">
|
||||||
|
<path transform="translate(0,-72)" d="M 23,84 15,79 V 89" id="path434" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-72)" d="M 13,89 H 10 V 79 h 3 v 10 z" id="path436" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(166,0)" id="g438">
|
||||||
|
<path transform="translate(-160,-120)" d="m 169.2,130.15 c 0.0551,-0.1128 0.15339,-0.22 0.2313,-0.3064 0.54584,-0.6074 1.3889,-1.1974 3.0053,-1.5702 v -2.1715 c -1.2931,0.2523 -2.3146,0.6686 -3.304,1.5597 -0.33248,0.3832 -0.50543,0.6247 -0.514,1.1665 -0.007,0.443 0.17732,0.8863 0.58141,1.3219 z m 6.6309,3.1292 c -1.6164,-0.024 -3.1091,-0.2558 -4.6228,-0.764 -2.6938,-0.9037 -3.0286,-2.1697 -3.1703,-2.5931 -0.0958,1.6897 0.028,2.9573 0.0346,3.0648 0.092,1.5004 1.2918,2.6742 2.1575,3.1151 1.7796,0.9067 3.6614,1.3756 5.601,1.4151 v 2.4842 l 3.251,-4.6483 -3.251,-4.6486 v 2.5748 z m -0.32327,-5.2959 c 1.6164,0.01 3.4529,0.3384 5.2454,1.1131 0.73528,0.3177 1.3275,0.7904 1.8082,1.3048 0.33152,-0.1523 0.80672,-0.7308 0.74126,-1.2923 -0.16163,-1.3879 -1.6264,-2.1912 -1.8801,-2.3045 -1.7704,-0.7908 -3.9751,-1.0356 -5.9147,-1.0589 v -1.7442 l -2.0132,2.8787 2.0132,2.8783 v -1.775 z m 8.4236,1.8658 c -0.0824,0.6478 -0.82676,2.0349 -3.8978,2.9138 v 4.5247 c 1.1314,-0.3677 2.465,-1.2956 3.1787,-2.1988 0.2911,-0.3677 0.46906,-0.875 0.57736,-1.242 0.33216,-1.1229 0.18604,-3.3136 0.14175,-3.9977 z" id="path442" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(166,24)" id="g444">
|
||||||
|
<path transform="translate(8,4)" d="m 10.624,2.47 c 1.9155,0.90417 3.2862,2.7533 3.4971,4.9467 h 0.87866 C 14.70102,3.8234 11.68426,1 7.99976,1 L 7.61315,1.0175 9.84495,3.24 10.62403,2.47 z M 6.9629,2.02083 c -0.34561,-0.34417 -0.90209,-0.34417 -1.2418,0 l -3.7255,3.71 c -0.34561,0.34417 -0.34561,0.89833 0,1.2367 l 7.041,7.0117 c 0.34561,0.34417 0.90209,0.34417 1.2418,0 l 3.7255,-3.71 c 0.34561,-0.34417 0.34561,-0.89833 0,-1.2367 l -7.041,-7.0117 z m 2.6946,11.34 -7.041,-7.0117 3.7255,-3.71 7.041,7.0117 -3.7255,3.71 z M 5.3755,13.53 C 3.46,12.63167 2.0893,10.7767 1.8784,8.5833 H 0.99974 C 1.29848,12.1766 4.31524,15 7.99974,15 L 8.38635,14.9825 6.15455,12.76 5.37547,13.53 z" id="path448" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(166,48)" id="g450">
|
||||||
|
<path transform="translate(-288,-72)" d="m 293.96,74.013 h 20 v 20 h -20 z" id="path454" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-288,-72)" d="m 297,77 h 18 v 18 h -18 z" id="path456" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-288,-72)" d="m 295.25,75.25 h 20 v 20 h -20 z" id="path458" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-288,-72)" d="m 293.12,73.125 h 20 v 20 h -20 z" id="path460" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-288,-72)" d="m 288,72 h 24 v 24 h -24 z" id="path462" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(-288,-72)" d="m 309.35,84.686 c 0.0288,-0.224 0.0504,-0.448 0.0504,-0.686 0,-0.238 -0.0216,-0.462 -0.0504,-0.686 l 1.5184,-1.155 c 0.13673,-0.105 0.17272,-0.294 0.0863,-0.448 l -1.4393,-2.422 c -0.0863,-0.154 -0.28065,-0.21 -0.43897,-0.154 l -1.7919,0.7 c -0.37422,-0.28 -0.77722,-0.511 -1.2162,-0.686 l -0.27341,-1.855 C 305.77334,77.126 305.62223,77 305.44232,77 h -2.8785 c -0.17992,0 -0.33104,0.126 -0.35263,0.294 l -0.27346,1.855 c -0.43898,0.175 -0.84198,0.413 -1.2162,0.686 l -1.7919,-0.7 c -0.16551,-0.063 -0.35262,0 -0.43898,0.154 l -1.4393,2.422 c -0.0935,0.154 -0.0504,0.343 0.0863,0.448 l 1.5184,1.155 c -0.0287,0.224 -0.0504,0.455 -0.0504,0.686 0,0.231 0.0216,0.462 0.0504,0.686 l -1.5184,1.155 c -0.13673,0.105 -0.17271,0.294 -0.0863,0.448 l 1.4393,2.422 c 0.0863,0.154 0.28067,0.21 0.43898,0.154 l 1.7919,-0.7 c 0.37421,0.28 0.77721,0.511 1.2162,0.686 l 0.27346,1.855 c 0.0216,0.168 0.17271,0.294 0.35263,0.294 h 2.8785 c 0.17991,0 0.33103,-0.126 0.35263,-0.294 l 0.27345,-1.855 c 0.43898,-0.175 0.84198,-0.413 1.2162,-0.686 l 1.7919,0.7 c 0.16552,0.063 0.35263,0 0.43898,-0.154 l 1.4393,-2.422 c 0.0863,-0.154 0.0504,-0.343 -0.0863,-0.448 l -1.5184,-1.155 z m -5.3469,1.764 c -1.3889,0 -2.5187,-1.099 -2.5187,-2.45 0,-1.351 1.1298,-2.45 2.5187,-2.45 1.3889,0 2.5187,1.099 2.5187,2.45 0,1.351 -1.1298,2.45 -2.5187,2.45 z" id="path464" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(162,73)" id="g466">
|
||||||
|
<path transform="matrix(0,-1,1,0,-136,251)" d="m 232.5,150.5 h 14 v 12 h -14 z" id="path470" inkscape:connector-curvature="0" style="fill:none;stroke:#000000"/>
|
||||||
|
<path transform="matrix(0,-1,1,0,-136,251)" d="m 244,156.5 -5,-3.25 v 6.5" id="path472" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="matrix(0,-1,1,0,-136,251)" d="m 236,150 h 1 v 13 h -1 z" id="path474" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(166,96)" id="g476">
|
||||||
|
<path transform="translate(-160,-72)" d="m 168.5,78.5 h 14 v 12 h -14 z" id="path480" inkscape:connector-curvature="0" style="fill:none;stroke:#000000"/>
|
||||||
|
<path transform="translate(-160,-72)" d="m 180,84.5 -5,-3.25 v 6.5" id="path482" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-160,-72)" d="m 172,78 h 1 v 13 h -1 z" id="path484" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(166,120)" id="g486">
|
||||||
|
<path transform="matrix(-1,0,0,1,-192,-96)" d="m -214.5,102.5 h 14 v 12 h -14 z" id="path490" inkscape:connector-curvature="0" style="fill:none;stroke:#000000"/>
|
||||||
|
<path transform="translate(-192,-96)" d="m 203,108.5 5,-3.25 v 6.5" id="path492" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="matrix(-1,0,0,1,-192,-96)" d="m -211,102 h 1 v 13 h -1 z" id="path494" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(162,145)" id="g496">
|
||||||
|
<path transform="matrix(0,1,1,0,-88,219)" d="m -214.5,102.5 h 14 v 12 h -14 z" id="path500" inkscape:connector-curvature="0" style="fill:none;stroke:#000000"/>
|
||||||
|
<path transform="matrix(0,-1,1,0,-88,219)" d="m 203,108.5 5,-3.25 v 6.5" id="path502" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="matrix(0,1,1,0,-88,219)" d="m -211,102 h 1 v 13 h -1 z" id="path504" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(166,168)" id="g506">
|
||||||
|
<path transform="translate(-288,0)" d="m 298,12 c 0,3.31 2.69,6 6,6 3.31,0 6,-2.69 6,-6 0,-3.31 -2.69,-6 -6,-6 -3.31,0 -6,2.69 -6,6" id="path510" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(-2,192)" id="g512">
|
||||||
|
<path transform="translate(-64,-72)" d="m 78.5,89 c 0,1.1 0.9,2 2,2 1.1,0 2,-0.9 2,-2 0,-1.1 -0.9,-2 -2,-2 -1.1,0 -2,0.9 -2,2" id="path516" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-64,-72)" d="m 79,78 v 4 h -3 l 4.5,4 4.5,-4 h -3 v -4 h -3 z" id="path518" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(26,192)" id="g520">
|
||||||
|
<path transform="translate(-96,-72)" d="m 110.5,89 c 0,1.1 0.9,2 2,2 1.1,0 2,-0.9 2,-2 0,-1.1 -0.9,-2 -2,-2 -1.1,0 -2,0.9 -2,2" id="path524" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-96,-72)" d="m 112.5,78 -4.5,4 h 3 v 4 h 3 v -4 h 3 l -4.5,-4 z" id="path526" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(54,192)" id="g528">
|
||||||
|
<path transform="translate(-128,-72)" d="m 142,86.5 c 0,1.1 0.9,2 2,2 1.1,0 2,-0.9 2,-2 0,-1.1 -0.9,-2 -2,-2 -1.1,0 -2,0.9 -2,2" id="path532" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-128,-72)" d="m 137.25,87.03 c 2.55,-8.43 11.4,-8.73 13.94,0" id="path534" inkscape:connector-curvature="0" style="fill:none;stroke:#000000;stroke-width:2.5"/>
|
||||||
|
<path transform="translate(-128,-72)" d="m 151.68,89 -4.54,-2.76 6.68,-2.1" id="path536" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(82,192)" id="g538">
|
||||||
|
<path transform="translate(-288,-24)" d="m 295,36 c 0,4.97 4.03,9 9,9 4.97,0 9,-4.03 9,-9 0,-4.97 -4.03,-9 -9,-9 -4.97,0 -9,4.03 -9,9" id="path542" inkscape:connector-curvature="0" style="fill:url(#sprite60_a)"/>
|
||||||
|
<path transform="translate(-288,-24)" d="m 298,36 c 0,3.31 2.69,6 6,6 3.31,0 6,-2.69 6,-6 0,-3.31 -2.69,-6 -6,-6 -3.31,0 -6,2.69 -6,6" id="path544" inkscape:connector-curvature="0"/>
|
||||||
|
<defs id="defs546">
|
||||||
|
<radialGradient id="sprite60_b" cx="0" cy="0" r="1" gradientTransform="matrix(18,0,0,-18,680,341)" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0" id="stop549"/>
|
||||||
|
<stop stop-opacity="0" offset="1" id="stop551"/>
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient id="sprite60_a" cx="0" cy="0" r="1" gradientTransform="matrix(9,0,0,9,304,36)" gradientUnits="userSpaceOnUse" xlink:href="#sprite60_b"/>
|
||||||
|
</defs>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(110,192)" id="g554">
|
||||||
|
<g id="g558">
|
||||||
|
<path transform="translate(7,3)" d="M 0,0 H 18 V 18 H 0 z" id="path560" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
<path transform="translate(7,3)" d="M 15.25,8 H 16 V 6.125 5 H 5 V 6.125 8 h 0.75 c 0,-0.82843 0.67157,-1.5 1.5,-1.5 h 2.5 v 7.25 c 0,0.82843 -0.67157,1.5 -1.5,1.5 V 16 h 1.875 0.75 1.875 v -0.75 c -0.82843,0 -1.5,-0.67157 -1.5,-1.5 V 6.5 h 2.5 c 0.82843,0 1.5,0.67157 1.5,1.5 z" id="path562" inkscape:connector-curvature="0" style="fill-opacity:0.36000001"/>
|
||||||
|
<path transform="translate(7,3)" d="M 12.25,5 H 13 V 3.125 2 H 2 V 3.125 5 h 0.75 c 0,-0.82843 0.67157,-1.5 1.5,-1.5 h 2.5 v 7.25 c 0,0.82843 -0.67157,1.5 -1.5,1.5 V 13 h 1.875 0.75 1.875 v -0.75 c -0.82843,0 -1.5,-0.67157 -1.5,-1.5 V 3.5 h 2.5 c 0.82843,0 1.5,0.67157 1.5,1.5 z" id="path564" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(138,192)" id="g566">
|
||||||
|
<path transform="translate(-128,-24)" d="m 139.5,33 h 9 L 147,43 h -6" id="path570" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-128,-24)" d="m 147.5,30 h -2 v -1 h -3 v 1 h -2 c -0.55,0 -1,0.48 -1,1 v 1 h 1 7 1 v -1 c 0,-0.52 -0.45,-1 -1,-1" id="path572" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(168,192)" id="g574">
|
||||||
|
<path transform="translate(0,-48)" d="M 10,57 H 8 v 9 h 11 v -2 h -9 z" id="path578" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(0,-48)" d="m 13,56 h 7 v 5 h -7 z m -2,-2 v 9 h 11 v -9 z" id="path580" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(194,0)" id="g582">
|
||||||
|
<path transform="translate(-96,0)" d="m 112,6.6909 c -3.6364,0 -6.7418,2.2618 -8,5.4545 1.2582,3.1927 4.3636,5.4545 8,5.4545 3.6364,0 6.7418,-2.2618 8,-5.4545 -1.2582,-3.1927 -4.3636,-5.4545 -8,-5.4545 z m 0,9.0909 c -2.0073,0 -3.6364,-1.6291 -3.6364,-3.6364 0,-2.0073 1.6291,-3.6364 3.6364,-3.6364 2.0073,0 3.6364,1.6291 3.6364,3.6364 0,2.0073 -1.6291,3.6364 -3.6364,3.6364 z m 0,-5.8182 c -1.2073,0 -2.1818,0.97455 -2.1818,2.1818 0,1.2073 0.97455,2.1818 2.1818,2.1818 1.2073,0 2.1818,-0.97455 2.1818,-2.1818 0,-1.2073 -0.97455,-2.1818 -2.1818,-2.1818 z" id="path586" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(194,24)" id="g588">
|
||||||
|
<path transform="translate(-128,-48)" d="m 153,57 h -11 v -2 h 11 v 2 z" id="path592" inkscape:connector-curvature="0" style="opacity:0.2"/>
|
||||||
|
<path transform="translate(-128,-48)" d="m 142,57 h -6 v -2 h 6 v 2 z" id="path594" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-128,-48)" d="m 145,60 h -6 v -2 h 6 v 2 z" id="path596" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-128,-48)" d="m 150,63 h -6 v -2 h 6 v 2 z" id="path598" inkscape:connector-curvature="0"/>
|
||||||
|
<path transform="translate(-128,-48)" d="m 152,66 h -6 v -2 h 6 v 2 z" id="path600" inkscape:connector-curvature="0"/>
|
||||||
|
</g>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="12.355932" y="231.55931" id="text4355"><tspan sodipodi:role="line" id="tspan4357" x="12.355932" y="231.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">a</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="40.355934" y="231.55931" id="text4355-3"><tspan sodipodi:role="line" id="tspan4357-6" x="40.355934" y="231.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">b</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="68.355934" y="231.55931" id="text4355-7"><tspan sodipodi:role="line" id="tspan4357-5" x="68.355934" y="231.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">c</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="96.355934" y="231.55931" id="text4355-35"><tspan sodipodi:role="line" id="tspan4357-62" x="96.355934" y="231.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">d</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="124.35593" y="231.55931" id="text4355-9"><tspan sodipodi:role="line" id="tspan4357-1" x="124.35593" y="231.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">e</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="152.35593" y="231.55931" id="text4355-2"><tspan sodipodi:role="line" id="tspan4357-7" x="152.35593" y="231.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">f</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="180.35593" y="231.55931" id="text4355-0"><tspan sodipodi:role="line" id="tspan4357-9" x="180.35593" y="231.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">g</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="208.35593" y="231.55931" id="text4355-36"><tspan sodipodi:role="line" id="tspan4357-0" x="208.35593" y="231.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">h</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="-15.644068" y="207.55931" id="text4355-6"><tspan sodipodi:role="line" id="tspan4357-2" x="-15.644068" y="207.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">1</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="-15.644068" y="183.55931" id="text4355-61"><tspan sodipodi:role="line" id="tspan4357-8" x="-15.644068" y="183.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">2</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="-15.644068" y="159.55931" id="text4355-79"><tspan sodipodi:role="line" id="tspan4357-20" x="-15.644068" y="159.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">3</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="-15.644068" y="135.55931" id="text4355-23"><tspan sodipodi:role="line" id="tspan4357-75" x="-15.644068" y="135.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">4</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="-15.644068" y="111.55931" id="text4355-92"><tspan sodipodi:role="line" id="tspan4357-28" x="-15.644068" y="111.55931" style="font-size:12px;line-height:1.25;font-family:sans-serif">5</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="-15.644068" y="87.559311" id="text4355-97"><tspan sodipodi:role="line" id="tspan4357-3" x="-15.644068" y="87.559311" style="font-size:12px;line-height:1.25;font-family:sans-serif">6</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="-15.644068" y="63.559311" id="text4355-612"><tspan sodipodi:role="line" id="tspan4357-93" x="-15.644068" y="63.559311" style="font-size:12px;line-height:1.25;font-family:sans-serif">7</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="-15.644068" y="39.559311" id="text4355-1"><tspan sodipodi:role="line" id="tspan4357-94" x="-15.644068" y="39.559311" style="font-size:12px;line-height:1.25;font-family:sans-serif">8</tspan></text>
|
||||||
|
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none" x="-15.644068" y="15.559311" id="text4355-78"><tspan sodipodi:role="line" id="tspan4357-4" x="-15.644068" y="15.559311" style="font-size:12px;line-height:1.25;font-family:sans-serif">9</tspan></text>
|
||||||
|
<g id="Page-1-6" style="fill:none;stroke:none" transform="translate(200,50)">
|
||||||
|
<g id="undo">
|
||||||
|
<rect height="20" width="20" y="0" x="0" id="bounds" style="fill:#ffffff;fill-opacity:0"/>
|
||||||
|
<path id="shape" d="M 4.3431457,9.3431458 C 5.790861,7.8954305 7.790861,7 10,7 c 3.555275,0 6.568879,2.3191676 7.610506,5.527197 L 16.155367,13 15.658589,13 C 14.834916,10.669615 12.612438,9 10,9 8.3431458,9 6.8431457,9.6715729 5.7573593,10.757359 L 8,13 2,13 2,7 l 2.3431457,2.3431458 0,0 z" inkscape:connector-curvature="0" style="fill:#000000"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path style="fill:#000000" sodipodi:nodetypes="ccccccccccccc" inkscape:connector-curvature="0" d="m 215,82 -3,0 0,-4 -4,0 0,4 -3,0 5,6 z m -10,7 0,1 10,0 0,-1 z" id="path4295"/>
|
||||||
|
<path style="fill:none" inkscape:connector-curvature="0" d="m 196,72 h 24 v 24 h -24 z" id="path4297"/>
|
||||||
|
<path style="fill:#000000" d="m 210,102 -5,6 3,0 0,4 4,0 0,-4 3,0 z m -5,11 0,1 10,0 0,-1 z" id="path4295-3" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccccc"/>
|
||||||
|
<rect style="fill:#000000;" id="square-icon" width="8" height="8" x="206" y="176"/>
|
||||||
|
<g style="fill:#000000" id="g4456" transform="matrix(0.78548728,0,0,0.78548728,200.6822,123.63151)">
|
||||||
|
<path id="path4442" d="M 15.5,14 H 14.71 L 14.43,13.73 C 15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3 5.91,3 3,5.91 3,9.5 3,13.09 5.91,16 9.5,16 c 1.61,0 3.09,-0.59 4.23,-1.57 L 14,14.71 v 0.79 l 5,4.99 1.49,-1.49 z m -6,0 C 7.01,14 5,11.99 5,9.5 5,7.01 7.01,5 9.5,5 11.99,5 14,7.01 14,9.5 14,11.99 11.99,14 9.5,14 Z" inkscape:connector-curvature="0"/>
|
||||||
|
<path id="path4444" d="M 0,0 H 24 V 24 H 0 Z" inkscape:connector-curvature="0" style="fill:none"/>
|
||||||
|
</g>
|
||||||
|
<path inkscape:connector-curvature="0" id="path524-5" d="m 211.71941,203.4233 c 0,1.1 0.9,2 2,2 1.1,0 2,-0.9 2,-2 0,-1.1 -0.9,-2 -2,-2 -1.1,0 -2,0.9 -2,2"/>
|
||||||
|
<g transform="translate(190.16772,189.5042)" id="g520-3">
|
||||||
|
<path d="m 20.83228,13.9958 -4,-4.5 v 3 h -4 v 3 h 4 v 3 z" id="path526-7" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccc"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
|
@ -36,3 +36,44 @@
|
||||||
.contractFunction {
|
.contractFunction {
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.debugButton {
|
||||||
|
width: 28px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jumpBack {
|
||||||
|
background-position: 0px 48px;
|
||||||
|
background-image: url(images/icons.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jumpForward {
|
||||||
|
background-position: -28px 48px;
|
||||||
|
background-image: url(images/icons.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepOverBack {
|
||||||
|
transform: scaleX(-1);
|
||||||
|
background-position: -56px 24px;
|
||||||
|
background-image: url(images/icons.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepOverForward {
|
||||||
|
background-position: -56px 24px;
|
||||||
|
background-image: url(images/icons.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepIntoForward {
|
||||||
|
background-position: 0px 24px;
|
||||||
|
background-image: url(images/icons.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stepIntoBack {
|
||||||
|
background-position: -28px 24px;
|
||||||
|
background-image: url(images/icons.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-underline {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {combineReducers} from 'redux';
|
import {combineReducers} from 'redux';
|
||||||
import {REQUEST, SUCCESS, FAILURE, CONTRACT_COMPILE, FILES, LOGOUT, AUTHENTICATE,
|
import {REQUEST, SUCCESS, FAILURE, CONTRACT_COMPILE, FILES, LOGOUT, AUTHENTICATE,
|
||||||
FETCH_CREDENTIALS, UPDATE_BASE_ETHER, CHANGE_THEME, FETCH_THEME, EXPLORER_SEARCH,
|
FETCH_CREDENTIALS, UPDATE_BASE_ETHER, CHANGE_THEME, FETCH_THEME, EXPLORER_SEARCH, DEBUGGER_INFO,
|
||||||
SIGN_MESSAGE, VERIFY_MESSAGE, TOGGLE_BREAKPOINT,
|
SIGN_MESSAGE, VERIFY_MESSAGE, TOGGLE_BREAKPOINT,
|
||||||
UPDATE_DEPLOYMENT_PIPELINE, WEB3_CONNECT, WEB3_DEPLOY, WEB3_ESTIMAGE_GAS} from "../actions";
|
UPDATE_DEPLOYMENT_PIPELINE, WEB3_CONNECT, WEB3_DEPLOY, WEB3_ESTIMAGE_GAS, FETCH_EDITOR_TABS} from "../actions";
|
||||||
import {EMBARK_PROCESS_NAME, DARK_THEME, DEPLOYMENT_PIPELINES, DEFAULT_HOST} from '../constants';
|
import {EMBARK_PROCESS_NAME, DARK_THEME, DEPLOYMENT_PIPELINES, DEFAULT_HOST} from '../constants';
|
||||||
|
|
||||||
const BN_FACTOR = 10000;
|
const BN_FACTOR = 10000;
|
||||||
|
@ -31,7 +31,6 @@ const entitiesDefaultState = {
|
||||||
ensRecords: [],
|
ensRecords: [],
|
||||||
files: [],
|
files: [],
|
||||||
gasOracleStats: [],
|
gasOracleStats: [],
|
||||||
currentFiles: []
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const sorter = {
|
const sorter = {
|
||||||
|
@ -80,7 +79,7 @@ const sorter = {
|
||||||
if (a.name < b.name) return -1;
|
if (a.name < b.name) return -1;
|
||||||
if (a.name > b.name) return 1;
|
if (a.name > b.name) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const filtrer = {
|
const filtrer = {
|
||||||
|
@ -313,7 +312,7 @@ function messageVerification(state = DEFAULT_MESSAGE_VERIFICATION_STATE, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
function breakpoints(state = {}, action) {
|
function breakpoints(state = {}, action) {
|
||||||
if (action.type === TOGGLE_BREAKPOINT) {
|
if (action.type === TOGGLE_BREAKPOINT[SUCCESS]) {
|
||||||
const {filename, lineNumber} = action.payload;
|
const {filename, lineNumber} = action.payload;
|
||||||
let lineNumbers = state[filename] || [];
|
let lineNumbers = state[filename] || [];
|
||||||
if (lineNumbers.includes(lineNumber)){
|
if (lineNumbers.includes(lineNumber)){
|
||||||
|
@ -347,6 +346,20 @@ function web3(state = {deployments: {}, gasEstimates: {}}, action) {
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function debuggerInfo(state={}, action) {
|
||||||
|
if (action.type === DEBUGGER_INFO[SUCCESS]) {
|
||||||
|
return action.data;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
function editorTabs(state = [], action) {
|
||||||
|
if (action.type === FETCH_EDITOR_TABS[SUCCESS] && action.editorTabs) {
|
||||||
|
return action.editorTabs;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
entities,
|
entities,
|
||||||
loading,
|
loading,
|
||||||
|
@ -355,13 +368,15 @@ const rootReducer = combineReducers({
|
||||||
errorEntities,
|
errorEntities,
|
||||||
credentials,
|
credentials,
|
||||||
baseEther,
|
baseEther,
|
||||||
theme,
|
|
||||||
searchResult,
|
searchResult,
|
||||||
messageSignature,
|
messageSignature,
|
||||||
messageVerification,
|
messageVerification,
|
||||||
breakpoints,
|
breakpoints,
|
||||||
deploymentPipeline,
|
deploymentPipeline,
|
||||||
web3
|
web3,
|
||||||
|
debuggerInfo,
|
||||||
|
theme,
|
||||||
|
editorTabs
|
||||||
});
|
});
|
||||||
|
|
||||||
export default rootReducer;
|
export default rootReducer;
|
||||||
|
|
|
@ -170,7 +170,7 @@ export function getFiles(state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentFile(state) {
|
export function getCurrentFile(state) {
|
||||||
return last(state.entities.currentFiles);
|
return state.editorTabs.find(file => file.active) || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBaseEther(state) {
|
export function getBaseEther(state) {
|
||||||
|
@ -224,3 +224,16 @@ export function getWeb3GasEstimates(state) {
|
||||||
export function getWeb3Deployments(state) {
|
export function getWeb3Deployments(state) {
|
||||||
return state.web3.deployments;
|
return state.web3.deployments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function debuggerInfo(state) {
|
||||||
|
return state.debuggerInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDebuggerLine(state) {
|
||||||
|
if (!state.debuggerInfo.sources) return 10;
|
||||||
|
return state.debuggerInfo.sources.lineColumnPos[0].start.line + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEditorTabs(state) {
|
||||||
|
return state.editorTabs
|
||||||
|
}
|
||||||
|
|
|
@ -69,11 +69,16 @@ export const fetchFile = doRequest.bind(null, actions.file, api.fetchFile);
|
||||||
export const postFile = doRequest.bind(null, actions.saveFile, api.postFile);
|
export const postFile = doRequest.bind(null, actions.saveFile, api.postFile);
|
||||||
export const deleteFile = doRequest.bind(null, actions.removeFile, api.deleteFile);
|
export const deleteFile = doRequest.bind(null, actions.removeFile, api.deleteFile);
|
||||||
export const fetchEthGas = doRequest.bind(null, actions.gasOracle, api.getEthGasAPI);
|
export const fetchEthGas = doRequest.bind(null, actions.gasOracle, api.getEthGasAPI);
|
||||||
|
export const startDebug = doRequest.bind(null, actions.startDebug, api.startDebug);
|
||||||
|
export const debugJumpBack = doRequest.bind(null, actions.debugJumpBack, api.debugJumpBack);
|
||||||
|
export const debugJumpForward = doRequest.bind(null, actions.debugJumpForward, api.debugJumpForward);
|
||||||
|
export const debugStepOverForward = doRequest.bind(null, actions.debugStepOverForward, api.debugStepOverForward);
|
||||||
|
export const debugStepOverBackward = doRequest.bind(null, actions.debugStepOverBackward, api.debugStepOverBackward);
|
||||||
|
export const debugStepIntoForward = doRequest.bind(null, actions.debugStepIntoForward, api.debugStepIntoForward);
|
||||||
|
export const debugStepIntoBackward = doRequest.bind(null, actions.debugStepIntoBackward, api.debugStepIntoBackward);
|
||||||
|
export const toggleBreakpoint = doRequest.bind(null, actions.toggleBreakpoint, api.toggleBreakpoint);
|
||||||
export const authenticate = doRequest.bind(null, actions.authenticate, api.authenticate);
|
export const authenticate = doRequest.bind(null, actions.authenticate, api.authenticate);
|
||||||
|
|
||||||
export const fetchCurrentFile = doRequest.bind(null, actions.currentFile, storage.fetchCurrentFile);
|
|
||||||
export const postCurrentFile = doRequest.bind(null, actions.saveCurrentFile, storage.postCurrentFile);
|
|
||||||
export const deleteCurrentFile = doRequest.bind(null, null, storage.deleteCurrentFile);
|
|
||||||
export const fetchCredentials = doRequest.bind(null, actions.fetchCredentials, storage.fetchCredentials);
|
export const fetchCredentials = doRequest.bind(null, actions.fetchCredentials, storage.fetchCredentials);
|
||||||
export const saveCredentials = doRequest.bind(null, actions.saveCredentials, storage.saveCredentials);
|
export const saveCredentials = doRequest.bind(null, actions.saveCredentials, storage.saveCredentials);
|
||||||
export const logout = doRequest.bind(null, actions.logout, storage.logout);
|
export const logout = doRequest.bind(null, actions.logout, storage.logout);
|
||||||
|
@ -81,6 +86,9 @@ export const changeTheme = doRequest.bind(null, actions.changeTheme, storage.cha
|
||||||
export const fetchTheme = doRequest.bind(null, actions.fetchTheme, storage.fetchTheme);
|
export const fetchTheme = doRequest.bind(null, actions.fetchTheme, storage.fetchTheme);
|
||||||
export const signMessage = doRequest.bind(null, actions.signMessage, api.signMessage);
|
export const signMessage = doRequest.bind(null, actions.signMessage, api.signMessage);
|
||||||
export const verifyMessage = doRequest.bind(null, actions.verifyMessage, api.verifyMessage);
|
export const verifyMessage = doRequest.bind(null, actions.verifyMessage, api.verifyMessage);
|
||||||
|
export const fetchEditorTabs = doRequest.bind(null, actions.fetchEditorTabs, storage.fetchEditorTabs);
|
||||||
|
export const addEditorTabs = doRequest.bind(null, actions.addEditorTabs, storage.addEditorTabs);
|
||||||
|
export const removeEditorTabs = doRequest.bind(null, actions.removeEditorTabs, storage.removeEditorTabs);
|
||||||
|
|
||||||
export const explorerSearch = searchExplorer.bind(null, actions.explorerSearch);
|
export const explorerSearch = searchExplorer.bind(null, actions.explorerSearch);
|
||||||
|
|
||||||
|
@ -200,31 +208,55 @@ export function *watchPostFile() {
|
||||||
yield takeEvery(actions.SAVE_FILE[actions.REQUEST], postFile);
|
yield takeEvery(actions.SAVE_FILE[actions.REQUEST], postFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function *watchPostFileSuccess() {
|
|
||||||
yield takeEvery(actions.SAVE_FILE[actions.SUCCESS], postCurrentFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function *watchDeleteFile() {
|
export function *watchDeleteFile() {
|
||||||
yield takeEvery(actions.REMOVE_FILE[actions.REQUEST], deleteFile);
|
yield takeEvery(actions.REMOVE_FILE[actions.REQUEST], deleteFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function *watchDeleteFileSuccess() {
|
export function *watchDeleteFileSuccess() {
|
||||||
yield takeEvery(actions.REMOVE_FILE[actions.SUCCESS], fetchFiles);
|
yield takeEvery(actions.REMOVE_FILE[actions.SUCCESS], fetchFiles);
|
||||||
yield takeEvery(actions.REMOVE_FILE[actions.SUCCESS], deleteCurrentFile);
|
yield takeEvery(actions.REMOVE_FILE[actions.SUCCESS], removeEditorTabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function *watchFetchFileSuccess() {
|
export function *watchFetchFileSuccess() {
|
||||||
yield takeEvery(actions.FILE[actions.SUCCESS], postCurrentFile);
|
yield takeEvery(actions.FILE[actions.SUCCESS], addEditorTabs);
|
||||||
}
|
|
||||||
|
|
||||||
export function *watchFetchCurrentFile() {
|
|
||||||
yield takeEvery(actions.CURRENT_FILE[actions.REQUEST], fetchCurrentFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function *watchFetchEthGas() {
|
export function *watchFetchEthGas() {
|
||||||
yield takeEvery(actions.GAS_ORACLE[actions.REQUEST], fetchEthGas);
|
yield takeEvery(actions.GAS_ORACLE[actions.REQUEST], fetchEthGas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function *watchStartDebug() {
|
||||||
|
yield takeEvery(actions.START_DEBUG[actions.REQUEST], startDebug);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchDebugJumpBack() {
|
||||||
|
yield takeEvery(actions.DEBUG_JUMP_BACK[actions.REQUEST], debugJumpBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchDebugJumpForward() {
|
||||||
|
yield takeEvery(actions.DEBUG_JUMP_FORWARD[actions.REQUEST], debugJumpForward);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchDebugStepOverForward() {
|
||||||
|
yield takeEvery(actions.DEBUG_STEP_OVER_FORWARD[actions.REQUEST], debugStepOverForward);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchDebugStepOverBackward() {
|
||||||
|
yield takeEvery(actions.DEBUG_STEP_OVER_BACKWARD[actions.REQUEST], debugStepOverBackward);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchDebugStepIntoForward() {
|
||||||
|
yield takeEvery(actions.DEBUG_STEP_INTO_FORWARD[actions.REQUEST], debugStepIntoForward);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchDebugStepIntoBackward() {
|
||||||
|
yield takeEvery(actions.DEBUG_STEP_INTO_BACKWARD[actions.REQUEST], debugStepIntoBackward);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchToggleBreakpoint() {
|
||||||
|
yield takeEvery(actions.TOGGLE_BREAKPOINT[actions.REQUEST], toggleBreakpoint);
|
||||||
|
}
|
||||||
|
|
||||||
export function *watchAuthenticate() {
|
export function *watchAuthenticate() {
|
||||||
yield takeEvery(actions.AUTHENTICATE[actions.REQUEST], authenticate);
|
yield takeEvery(actions.AUTHENTICATE[actions.REQUEST], authenticate);
|
||||||
}
|
}
|
||||||
|
@ -273,6 +305,26 @@ export function *watchUpdateDeploymentPipeline() {
|
||||||
yield takeEvery(actions.UPDATE_DEPLOYMENT_PIPELINE, web3Connect);
|
yield takeEvery(actions.UPDATE_DEPLOYMENT_PIPELINE, web3Connect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function *watchFetchEditorTabs() {
|
||||||
|
yield takeEvery(actions.FETCH_EDITOR_TABS[actions.REQUEST], fetchEditorTabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchAddEditorTabs() {
|
||||||
|
yield takeEvery(actions.ADD_EDITOR_TABS[actions.REQUEST], addEditorTabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchRemoveEditorTabs() {
|
||||||
|
yield takeEvery(actions.REMOVE_EDITOR_TABS[actions.REQUEST], removeEditorTabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchAddEditorTabsSuccess() {
|
||||||
|
yield takeEvery(actions.ADD_EDITOR_TABS[actions.SUCCESS], fetchEditorTabs);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchRemoveEditorTabsSuccess() {
|
||||||
|
yield takeEvery(actions.REMOVE_EDITOR_TABS[actions.SUCCESS], fetchEditorTabs);
|
||||||
|
}
|
||||||
|
|
||||||
function createChannel(socket) {
|
function createChannel(socket) {
|
||||||
return eventChannel(emit => {
|
return eventChannel(emit => {
|
||||||
socket.onmessage = ((message) => {
|
socket.onmessage = ((message) => {
|
||||||
|
@ -385,6 +437,28 @@ export function *watchListenGasOracle() {
|
||||||
yield takeEvery(actions.WATCH_GAS_ORACLE, listenGasOracle);
|
yield takeEvery(actions.WATCH_GAS_ORACLE, listenGasOracle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function *listenDebugger() {
|
||||||
|
const credentials = yield select(getCredentials);
|
||||||
|
const socket = api.listenToDebugger(credentials);
|
||||||
|
const channel = yield call(createChannel, socket);
|
||||||
|
while (true) {
|
||||||
|
const { cancel, debuggerInfo } = yield race({
|
||||||
|
debuggerInfo: take(channel),
|
||||||
|
cancel: take(actions.STOP_DEBUGGER)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cancel) {
|
||||||
|
channel.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
yield put(actions.debuggerInfo.success(debuggerInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchListenDebugger() {
|
||||||
|
yield takeEvery(actions.START_DEBUG[actions.SUCCESS], listenDebugger);
|
||||||
|
}
|
||||||
|
|
||||||
export function *listenToMessages(action) {
|
export function *listenToMessages(action) {
|
||||||
const credentials = yield select(getCredentials);
|
const credentials = yield select(getCredentials);
|
||||||
const socket = api.listenToChannel(credentials, action.messageChannels[0]);
|
const socket = api.listenToChannel(credentials, action.messageChannels[0]);
|
||||||
|
@ -432,10 +506,16 @@ export default function *root() {
|
||||||
fork(watchDeleteFile),
|
fork(watchDeleteFile),
|
||||||
fork(watchDeleteFileSuccess),
|
fork(watchDeleteFileSuccess),
|
||||||
fork(watchFetchFileSuccess),
|
fork(watchFetchFileSuccess),
|
||||||
fork(watchFetchCurrentFile),
|
|
||||||
fork(watchPostFileSuccess),
|
|
||||||
fork(watchFetchCredentials),
|
fork(watchFetchCredentials),
|
||||||
fork(watchFetchEthGas),
|
fork(watchFetchEthGas),
|
||||||
|
fork(watchStartDebug),
|
||||||
|
fork(watchDebugJumpBack),
|
||||||
|
fork(watchDebugJumpForward),
|
||||||
|
fork(watchDebugStepOverForward),
|
||||||
|
fork(watchDebugStepOverBackward),
|
||||||
|
fork(watchDebugStepIntoForward),
|
||||||
|
fork(watchDebugStepIntoBackward),
|
||||||
|
fork(watchToggleBreakpoint),
|
||||||
fork(watchAuthenticate),
|
fork(watchAuthenticate),
|
||||||
fork(watchAuthenticateSuccess),
|
fork(watchAuthenticateSuccess),
|
||||||
fork(watchLogout),
|
fork(watchLogout),
|
||||||
|
@ -447,6 +527,12 @@ export default function *root() {
|
||||||
fork(watchVerifyMessage),
|
fork(watchVerifyMessage),
|
||||||
fork(watchWeb3EstimateGas),
|
fork(watchWeb3EstimateGas),
|
||||||
fork(watchWeb3Deploy),
|
fork(watchWeb3Deploy),
|
||||||
fork(watchUpdateDeploymentPipeline)
|
fork(watchUpdateDeploymentPipeline),
|
||||||
|
fork(watchListenDebugger),
|
||||||
|
fork(watchFetchEditorTabs),
|
||||||
|
fork(watchAddEditorTabs),
|
||||||
|
fork(watchRemoveEditorTabs),
|
||||||
|
fork(watchAddEditorTabsSuccess),
|
||||||
|
fork(watchRemoveEditorTabsSuccess),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,6 +185,42 @@ export function verifyMessage(payload) {
|
||||||
return post('/messages/verify', ...arguments);
|
return post('/messages/verify', ...arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function startDebug(payload) {
|
||||||
|
return post('/debugger/start', {params: payload, credentials: payload.credentials});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function debugJumpBack(payload) {
|
||||||
|
return post('/debugger/jumpBack', {params: payload, credentials: payload.credentials});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function debugJumpForward(payload) {
|
||||||
|
return post('/debugger/jumpForward', {params: payload, credentials: payload.credentials});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function debugStepOverForward(payload) {
|
||||||
|
return post('/debugger/stepOverForward', {params: payload, credentials: payload.credentials});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function debugStepOverBackward(payload) {
|
||||||
|
return post('/debugger/stepOverBackward', {params: payload, credentials: payload.credentials});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function debugStepIntoForward(payload) {
|
||||||
|
return post('/debugger/stepIntoForward', {params: payload, credentials: payload.credentials});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function debugStepIntoBackward(payload) {
|
||||||
|
return post('/debugger/stepIntoBackward', {params: payload, credentials: payload.credentials});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toggleBreakpoint(payload) {
|
||||||
|
return post('/debugger/breakpoint', {params: payload, credentials: payload.credentials});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listenToDebugger(credentials) {
|
||||||
|
return new WebSocket(`ws://${credentials.host}/embark-api/debugger`, [credentials.token]);
|
||||||
|
}
|
||||||
|
|
||||||
export function listenToChannel(credentials, channel) {
|
export function listenToChannel(credentials, channel) {
|
||||||
return new WebSocket(`ws://${credentials.host}/embark-api/communication/listenTo/${channel}`, [credentials.token]);
|
return new WebSocket(`ws://${credentials.host}/embark-api/communication/listenTo/${channel}`, [credentials.token]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,34 @@
|
||||||
export function postCurrentFile(file) {
|
export function addEditorTabs({file}) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
localStorage.setItem('currentFile', JSON.stringify(file));
|
const editorTabs = findOrCreateEditorTabs();
|
||||||
resolve({response: {data: file}});
|
editorTabs.forEach(f => f.active = false);
|
||||||
|
const alreadyAddedFile = editorTabs.find(f => f.name === file.name)
|
||||||
|
if (alreadyAddedFile) {
|
||||||
|
alreadyAddedFile.active = true
|
||||||
|
} else {
|
||||||
|
file.active = true
|
||||||
|
editorTabs.push(file);
|
||||||
|
}
|
||||||
|
localStorage.setItem('editorTabs', JSON.stringify(editorTabs));
|
||||||
|
resolve({response: {data: editorTabs}});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchCurrentFile() {
|
export function fetchEditorTabs() {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
resolve({response: {data: JSON.parse(localStorage.getItem('currentFile'))}});
|
resolve({response: {data: JSON.parse(localStorage.getItem('editorTabs'))}});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteCurrentFile() {
|
export function removeEditorTabs({file}) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
localStorage.removeItem('currentFile');
|
const editorTabs = findOrCreateEditorTabs();
|
||||||
resolve({});
|
const filtered = editorTabs.filter(value => value.name !== file.name);
|
||||||
|
if (file.active && filtered.length) {
|
||||||
|
filtered[0].active = true;
|
||||||
|
}
|
||||||
|
localStorage.setItem('editorTabs', JSON.stringify(filtered));
|
||||||
|
resolve({response: {data: filtered}});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,3 +64,8 @@ export function changeTheme({theme}) {
|
||||||
export function fetchTheme() {
|
export function fetchTheme() {
|
||||||
return new Promise(resolve => resolve({response: {data: localStorage.getItem('theme')}}));
|
return new Promise(resolve => resolve({response: {data: localStorage.getItem('theme')}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function findOrCreateEditorTabs() {
|
||||||
|
return JSON.parse(localStorage.getItem('editorTabs')) || [];
|
||||||
|
}
|
|
@ -217,6 +217,7 @@ class Engine {
|
||||||
this.registerModule('console_listener', {ipc: self.ipc});
|
this.registerModule('console_listener', {ipc: self.ipc});
|
||||||
this.registerModule('deployment', {plugins: this.plugins, onlyCompile: options.onlyCompile});
|
this.registerModule('deployment', {plugins: this.plugins, onlyCompile: options.onlyCompile});
|
||||||
this.registerModule('transactionTracker');
|
this.registerModule('transactionTracker');
|
||||||
|
this.registerModule('debugger');
|
||||||
|
|
||||||
this.events.on('file-event', function ({fileType, path}) {
|
this.events.on('file-event', function ({fileType, path}) {
|
||||||
clearTimeout(self.fileTimeout);
|
clearTimeout(self.fileTimeout);
|
||||||
|
|
|
@ -33,6 +33,10 @@ class BlockchainConnector {
|
||||||
cb(self);
|
cb(self);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.events.setCommandHandler("blockchain:getTransaction", (txHash, cb) => {
|
||||||
|
self.getTransactionByHash(txHash, cb);
|
||||||
|
});
|
||||||
|
|
||||||
embark.registerActionForEvent("contracts:deploy:afterAll", this.subscribeToContractEvents.bind(this));
|
embark.registerActionForEvent("contracts:deploy:afterAll", this.subscribeToContractEvents.bind(this));
|
||||||
|
|
||||||
if (!this.web3) {
|
if (!this.web3) {
|
||||||
|
@ -580,7 +584,7 @@ class BlockchainConnector {
|
||||||
this.web3.eth.getBlock(blockNumber, true, cb);
|
this.web3.eth.getBlock(blockNumber, true, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTransaction(hash, cb) {
|
getTransactionByHash(hash, cb) {
|
||||||
this.web3.eth.getTransaction(hash, cb);
|
this.web3.eth.getTransaction(hash, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,6 +599,14 @@ class BlockchainConnector {
|
||||||
return this.web3.eth.net.getId();
|
return this.web3.eth.net.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: fix me, why is this gasPrice??
|
||||||
|
getTransaction(hash, cb) {
|
||||||
|
const self = this;
|
||||||
|
this.onReady(() => {
|
||||||
|
self.web3.eth.getGasPrice(cb);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ContractObject(params) {
|
ContractObject(params) {
|
||||||
return new this.web3.eth.Contract(params.abi, params.address);
|
return new this.web3.eth.Contract(params.abi, params.address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ class Console {
|
||||||
}
|
}
|
||||||
|
|
||||||
processEmbarkCmd (cmd) {
|
processEmbarkCmd (cmd) {
|
||||||
if (cmd === 'help' || cmd === __('help')) {
|
if (cmd === 'help' || cmd === __('help') || cmd === '01189998819991197253') {
|
||||||
let helpText = [
|
let helpText = [
|
||||||
__('Welcome to Embark') + ' ' + this.version,
|
__('Welcome to Embark') + ' ' + this.version,
|
||||||
'',
|
'',
|
||||||
|
|
|
@ -101,6 +101,7 @@ class ConsoleListener {
|
||||||
this.events.emit('contracts:log', this.logs[this.logs.length - 1]);
|
this.events.emit('contracts:log', this.logs[this.logs.length - 1]);
|
||||||
|
|
||||||
this.logger.info(`Blockchain>`.underline + ` ${name}.${functionName}(${paramString})`.bold + ` | ${transactionHash} | gas:${gasUsed} | blk:${blockNumber} | status:${status}`);
|
this.logger.info(`Blockchain>`.underline + ` ${name}.${functionName}(${paramString})`.bold + ` | ${transactionHash} | gas:${gasUsed} | blk:${blockNumber} | status:${status}`);
|
||||||
|
this.events.emit('blockchain:tx', { name: name, functionName: functionName, paramString: paramString, transactionHash: transactionHash, gasUsed: gasUsed, blockNumber: blockNumber, status: status });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,10 @@ class ContractsManager {
|
||||||
cb(self.getContract(contractName));
|
cb(self.getContract(contractName));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.events.setCommandHandler("contracts:contract:byTxHash", (txHash, cb) => {
|
||||||
|
self.getContractByTxHash(txHash, cb)
|
||||||
|
});
|
||||||
|
|
||||||
self.events.setCommandHandler("contracts:build", (configOnly, cb) => {
|
self.events.setCommandHandler("contracts:build", (configOnly, cb) => {
|
||||||
self.deployOnlyOnConfig = configOnly; // temporary, should refactor
|
self.deployOnlyOnConfig = configOnly; // temporary, should refactor
|
||||||
self.build((err) => {
|
self.build((err) => {
|
||||||
|
@ -490,6 +494,19 @@ class ContractsManager {
|
||||||
return this.contracts[className];
|
return this.contracts[className];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getContractByTxHash(txHash, cb) {
|
||||||
|
this.events.request("blockchain:getTransaction", txHash, (err, tx) => {
|
||||||
|
if (err) return cb(err);
|
||||||
|
for (let contractName in this.contracts) {
|
||||||
|
let contract = this.contracts[contractName];
|
||||||
|
if (tx.to === contract.deployedAddress) {
|
||||||
|
return cb(null, contract);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cb("no known contract found for txHash: " + txHash);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
sortContracts(contractList) {
|
sortContracts(contractList) {
|
||||||
let converted_dependencies = [], i;
|
let converted_dependencies = [], i;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
var RemixDebug = require('remix-debug-debugtest');
|
||||||
|
var CmdLine = RemixDebug.CmdLine;
|
||||||
|
const async = require('async');
|
||||||
|
|
||||||
|
class DebuggerManager {
|
||||||
|
|
||||||
|
constructor(nodeUrl) {
|
||||||
|
this.nodeUrl = nodeUrl
|
||||||
|
this.outputJson = {}
|
||||||
|
this.inputJson = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
setInputJson(inputJson) {
|
||||||
|
this.inputJson = inputJson
|
||||||
|
}
|
||||||
|
|
||||||
|
setOutputJson(outputJson) {
|
||||||
|
this.outputJson = outputJson
|
||||||
|
}
|
||||||
|
|
||||||
|
createDebuggerSession(txHash, filename, cb) {
|
||||||
|
return this.debug(txHash, filename, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(txHash, filename, cb) {
|
||||||
|
console.dir("debugging tx " + txHash)
|
||||||
|
|
||||||
|
var cmd_line = new CmdLine()
|
||||||
|
this.cmd_line = cmd_line
|
||||||
|
cmd_line.connect("http", this.nodeUrl)
|
||||||
|
cmd_line.loadCompilationData(this.inputJson, this.outputJson)
|
||||||
|
|
||||||
|
cmd_line.initDebugger(() => {
|
||||||
|
this.isDebugging = true
|
||||||
|
|
||||||
|
cmd_line.startDebug(txHash, filename, () => {
|
||||||
|
if (cb) {
|
||||||
|
cmd_line.triggerSourceUpdate()
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return cmd_line
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastLine(txHash, filename, outputCb) {
|
||||||
|
const self = this;
|
||||||
|
let cmd_line = new CmdLine()
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function initDebugger(next) {
|
||||||
|
cmd_line = new CmdLine()
|
||||||
|
cmd_line.connect("http", self.nodeUrl)
|
||||||
|
cmd_line.loadCompilationData(self.inputJson, self.outputJson)
|
||||||
|
cmd_line.initDebugger(() => {
|
||||||
|
// self.isDebugging = true
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
function startDebug(next) {
|
||||||
|
cmd_line.startDebug(txHash, filename, () => {
|
||||||
|
cmd_line.events.on("source", () => {
|
||||||
|
outputCb(cmd_line.getSource())
|
||||||
|
})
|
||||||
|
|
||||||
|
let total_size = cmd_line.getTraceLength()
|
||||||
|
cmd_line.jumpTo(total_size - 1)
|
||||||
|
cmd_line.unload()
|
||||||
|
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
], () => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DebuggerManager;
|
|
@ -0,0 +1,212 @@
|
||||||
|
var RemixDebug = require('remix-debug-debugtest');
|
||||||
|
var CmdLine = RemixDebug.CmdLine;
|
||||||
|
var DebuggerManager = require('./debugger_manager.js');
|
||||||
|
|
||||||
|
class TransactionDebugger {
|
||||||
|
constructor(embark, _options) {
|
||||||
|
const self = this
|
||||||
|
this.embark = embark
|
||||||
|
|
||||||
|
this.debugger_manager = new DebuggerManager("http://localhost:8545")
|
||||||
|
embark.events.on('contracts:compile:solc', this.debugger_manager.setInputJson.bind(this.debugger_manager))
|
||||||
|
embark.events.on('contracts:compiled:solc', this.debugger_manager.setOutputJson.bind(this.debugger_manager))
|
||||||
|
|
||||||
|
this.tx_tracker = {}
|
||||||
|
this.last_tx = ""
|
||||||
|
|
||||||
|
this.isDebugging = false
|
||||||
|
this.listenToEvents()
|
||||||
|
this.listenToCommands()
|
||||||
|
this.listentoAPI()
|
||||||
|
}
|
||||||
|
|
||||||
|
listenToEvents() {
|
||||||
|
const self = this
|
||||||
|
this.embark.events.on('blockchain:tx', (tx) => {
|
||||||
|
this.embark.events.request("contracts:contract", tx.name, (contract) => {
|
||||||
|
self.tx_tracker[tx.transactionHash] = {tx: tx, contract: contract}
|
||||||
|
self.last_tx = tx.transactionHash
|
||||||
|
if (tx.status !== '0x0') return
|
||||||
|
|
||||||
|
self.embark.logger.info("Transaction failed");
|
||||||
|
|
||||||
|
self.debugger_manager.getLastLine(tx.transactionHash, contract.filename, (lines) => {
|
||||||
|
lines.forEach((line) => {
|
||||||
|
self.embark.logger.error(line)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
listentoAPI() {
|
||||||
|
this.debuggerData = {}
|
||||||
|
this.apiDebugger = false
|
||||||
|
|
||||||
|
this.embark.registerAPICall('post', '/embark-api/debugger/start', (req, res) => {
|
||||||
|
let txHash = req.body.params.txHash
|
||||||
|
|
||||||
|
this.embark.events.request("contracts:contract:byTxHash", txHash, (err, contract) => {
|
||||||
|
if (err) {
|
||||||
|
this.embark.logger.error(err);
|
||||||
|
return res.send({error: err})
|
||||||
|
}
|
||||||
|
|
||||||
|
let filename = contract.filename
|
||||||
|
|
||||||
|
this.debuggerData = {}
|
||||||
|
this.apiDebugger = this.debugger_manager.createDebuggerSession(txHash, filename, () => {
|
||||||
|
})
|
||||||
|
res.send({ok :true})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
this.embark.registerAPICall('post', '/embark-api/debugger/JumpBack', (req, res) => {
|
||||||
|
this.apiDebugger.stepJumpNextBreakpoint()
|
||||||
|
res.send({ok :true})
|
||||||
|
})
|
||||||
|
this.embark.registerAPICall('post', '/embark-api/debugger/JumpForward', (req, res) => {
|
||||||
|
this.apiDebugger.stepJumpPreviousBreakpoint()
|
||||||
|
res.send({ok :true})
|
||||||
|
})
|
||||||
|
this.embark.registerAPICall('post', '/embark-api/debugger/StepOverForward', (req, res) => {
|
||||||
|
this.apiDebugger.stepOverForward(true)
|
||||||
|
res.send({ok :true})
|
||||||
|
})
|
||||||
|
this.embark.registerAPICall('post', '/embark-api/debugger/StepOverBackward', (req, res) => {
|
||||||
|
this.apiDebugger.stepOverBack(true)
|
||||||
|
res.send({ok :true})
|
||||||
|
})
|
||||||
|
this.embark.registerAPICall('post', '/embark-api/debugger/StepIntoForward', (req, res) => {
|
||||||
|
this.apiDebugger.stepIntoForward(true)
|
||||||
|
res.send({ok :true})
|
||||||
|
})
|
||||||
|
this.embark.registerAPICall('post', '/embark-api/debugger/StepIntoBackward', (req, res) => {
|
||||||
|
this.apiDebugger.stepIntoBack(true)
|
||||||
|
res.send({ok :true})
|
||||||
|
});
|
||||||
|
this.embark.registerAPICall('post', '/embark-api/debugger/breakpoint', (req, res) => {
|
||||||
|
console.dir("new breakpoint")
|
||||||
|
res.send({ok :true})
|
||||||
|
});
|
||||||
|
|
||||||
|
this.embark.registerAPICall('ws', '/embark-api/debugger', (ws, _req) => {
|
||||||
|
if (!this.apiDebugger) return
|
||||||
|
|
||||||
|
this.apiDebugger.events.on("source", (lineColumnPos, rawLocation) => {
|
||||||
|
this.debuggerData.sources = {lineColumnPos, rawLocation}
|
||||||
|
ws.send(JSON.stringify(this.debuggerData), () => {})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.apiDebugger.events.on("locals", (data) => {
|
||||||
|
this.debuggerData.locals = this.simplifyDebuggerVars(data)
|
||||||
|
ws.send(JSON.stringify(this.debuggerData), () => {})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.apiDebugger.events.on("globals", (data) => {
|
||||||
|
this.debuggerData.globals = this.simplifyDebuggerVars(data)
|
||||||
|
ws.send(JSON.stringify(this.debuggerData), () => {})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
simplifyDebuggerVars(data) {
|
||||||
|
let new_data = {};
|
||||||
|
|
||||||
|
for (let key in data) {
|
||||||
|
let field = data[key];
|
||||||
|
new_data[`${key} (${field.type})`] = field.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_data
|
||||||
|
}
|
||||||
|
|
||||||
|
listenToCommands() {
|
||||||
|
const self = this
|
||||||
|
this.cmdDebugger = false
|
||||||
|
|
||||||
|
this.embark.registerConsoleCommand((cmd, _options) => {
|
||||||
|
let cmdName = cmd.split(" ")[0]
|
||||||
|
let txHash = cmd.split(" ")[1]
|
||||||
|
return {
|
||||||
|
match: () => cmdName === 'debug',
|
||||||
|
process: (cb) => {
|
||||||
|
if (txHash) {
|
||||||
|
this.embark.events.request("contracts:contract:byTxHash", txHash, (err, contract) => {
|
||||||
|
if (err) {
|
||||||
|
this.embark.logger.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let filename = contract.filename
|
||||||
|
self.cmdDebugger = self.debugger_manager.createDebuggerSession(txHash, filename, () => {
|
||||||
|
self.cmdDebugger.getSource().forEach((line) => {
|
||||||
|
console.dir(line)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let filename = self.tx_tracker[self.last_tx].contract.filename
|
||||||
|
self.cmdDebugger = self.debugger_manager.createDebuggerSession(self.last_tx, filename, () => {
|
||||||
|
self.cmdDebugger.getSource().forEach((line) => {
|
||||||
|
console.dir(line)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
this.embark.registerConsoleCommand((cmd, _options) => {
|
||||||
|
return {
|
||||||
|
match: () => (cmd === 'next' || cmd === 'n'),
|
||||||
|
process: (cb) => {
|
||||||
|
if (!self.cmdDebugger.currentStep()) {
|
||||||
|
console.dir("end of execution reached")
|
||||||
|
return self.cmdDebugger.unload()
|
||||||
|
}
|
||||||
|
self.cmdDebugger.stepOverForward(true)
|
||||||
|
self.cmdDebugger.getSource().forEach((line) => {
|
||||||
|
console.dir(line)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
this.embark.registerConsoleCommand((cmd, _options) => {
|
||||||
|
return {
|
||||||
|
match: () => (cmd === 'previous' || cmd === 'p'),
|
||||||
|
process: (cb) => {
|
||||||
|
if (!self.cmdDebugger.currentStep()) {
|
||||||
|
console.dir("end of execution reached")
|
||||||
|
return self.cmdDebugger.unload()
|
||||||
|
}
|
||||||
|
self.cmdDebugger.stepOverBack(true)
|
||||||
|
self.cmdDebugger.getSource().forEach((line) => {
|
||||||
|
console.dir(line)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
this.embark.registerConsoleCommand((cmd, _options) => {
|
||||||
|
return {
|
||||||
|
match: () => (cmd === 'var local' || cmd === 'v l' || cmd === 'vl'),
|
||||||
|
process: (cb) => {
|
||||||
|
self.cmdDebugger.displayLocals()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
this.embark.registerConsoleCommand((cmd, _options) => {
|
||||||
|
return {
|
||||||
|
match: () => (cmd === 'var global' || cmd === 'v g' || cmd === 'vg'),
|
||||||
|
process: (cb) => {
|
||||||
|
self.cmdDebugger.displayGlobals()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = TransactionDebugger
|
|
@ -88,7 +88,7 @@ class Solidity {
|
||||||
},
|
},
|
||||||
outputSelection: {
|
outputSelection: {
|
||||||
'*': {
|
'*': {
|
||||||
'': ['ast'],
|
'': ['ast', 'legacyAST'], // legacyAST is needed by the debugger, for now
|
||||||
'*': [
|
'*': [
|
||||||
'abi',
|
'abi',
|
||||||
'devdoc',
|
'devdoc',
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -115,6 +115,7 @@
|
||||||
"swarm-api": "0.1.2",
|
"swarm-api": "0.1.2",
|
||||||
"tar": "3.2.1",
|
"tar": "3.2.1",
|
||||||
"toposort": "1.0.7",
|
"toposort": "1.0.7",
|
||||||
|
"remix-debug-debugtest": "latest",
|
||||||
"underscore": "1.9.1",
|
"underscore": "1.9.1",
|
||||||
"url-loader": "1.1.1",
|
"url-loader": "1.1.1",
|
||||||
"uuid": "3.3.2",
|
"uuid": "3.3.2",
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,5 @@
|
||||||
|
.embark/
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
config/production/password
|
||||||
|
config/livenet/password
|
|
@ -0,0 +1,87 @@
|
||||||
|
import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
|
import SimpleStorage from 'Embark/contracts/SimpleStorage';
|
||||||
|
import React from 'react';
|
||||||
|
import { Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap';
|
||||||
|
|
||||||
|
class Blockchain extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
valueSet: 10,
|
||||||
|
valueGet: "",
|
||||||
|
logs: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange(e) {
|
||||||
|
this.setState({ valueSet: e.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
checkEnter(e, func) {
|
||||||
|
if (e.key !== 'Enter') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
func.apply(this, [e]);
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var value = parseInt(this.state.valueSet, 10);
|
||||||
|
|
||||||
|
SimpleStorage.methods.set(value).send();
|
||||||
|
this._addToLog("SimpleStorage.methods.set(value).send()");
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
SimpleStorage.methods.get().call().then(_value => this.setState({ valueGet: _value }));
|
||||||
|
this._addToLog("SimpleStorage.methods.get(console.log)");
|
||||||
|
}
|
||||||
|
|
||||||
|
_addToLog(txt) {
|
||||||
|
this.state.logs.push(txt);
|
||||||
|
this.setState({ logs: this.state.logs });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (<React.Fragment>
|
||||||
|
<h3> 1. Set the value in the blockchain</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.setValue)}>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.valueSet}
|
||||||
|
onChange={(e) => this.handleChange(e)}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.setValue(e)}>Set Value</Button>
|
||||||
|
<HelpBlock>Once you set the value, the transaction will need to be mined and then the value will be updated
|
||||||
|
on the blockchain.</HelpBlock>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3> 2. Get the current value</h3>
|
||||||
|
<Form inline>
|
||||||
|
<FormGroup>
|
||||||
|
<HelpBlock>current value is <span className="value">{this.state.valueGet}</span></HelpBlock>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.getValue(e)}>Get Value</Button>
|
||||||
|
<HelpBlock>Click the button to get the current value. The initial value is 100.</HelpBlock>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3> 3. Contract Calls </h3>
|
||||||
|
<p>Javascript calls being made: </p>
|
||||||
|
<div className="logs">
|
||||||
|
{
|
||||||
|
this.state.logs.map((item, i) => <p key={i}>{item}</p>)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Blockchain;
|
|
@ -0,0 +1,180 @@
|
||||||
|
/*global web3*/
|
||||||
|
import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
|
import React from 'react';
|
||||||
|
import { Alert, Form, FormGroup, FormControl, Button } from 'react-bootstrap';
|
||||||
|
|
||||||
|
window.EmbarkJS = EmbarkJS;
|
||||||
|
|
||||||
|
class ENS extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
valueResolve: 'eth',
|
||||||
|
responseResolve: null,
|
||||||
|
isResolveError: false,
|
||||||
|
valueLookup: '',
|
||||||
|
responseLookup: null,
|
||||||
|
isLookupError: false,
|
||||||
|
valueRegister: '',
|
||||||
|
addressRegister: '',
|
||||||
|
responseRegister: null,
|
||||||
|
isRegisterError: false,
|
||||||
|
embarkLogs: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
EmbarkJS.onReady(() => {
|
||||||
|
if (!web3.eth.defaultAccount) {
|
||||||
|
this.setState({
|
||||||
|
globalError: 'There is currently no default account. If Metamask is active, please sign in or deactivate it.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
addressRegister: web3.eth.defaultAccount,
|
||||||
|
valueLookup: web3.eth.defaultAccount
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange(stateName, e) {
|
||||||
|
this.setState({ [stateName]: e.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
checkEnter(e, func) {
|
||||||
|
if (e.key !== 'Enter') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
func.apply(this, [e]);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerSubDomain(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const self = this;
|
||||||
|
const embarkLogs = this.state.embarkLogs;
|
||||||
|
embarkLogs.push(`EmbarkJS.Names.registerSubDomain('${this.state.valueRegister}', '${this.state.addressRegister}', console.log)`);
|
||||||
|
this.setState({
|
||||||
|
embarkLogs: embarkLogs
|
||||||
|
});
|
||||||
|
|
||||||
|
EmbarkJS.Names.registerSubDomain(this.state.valueRegister, this.state.addressRegister, (err, transaction) => {
|
||||||
|
const message = err ? err : `Successfully registered "${this.state.valueRegister}" with ${transaction.gasUsed} gas`;
|
||||||
|
self.setState({
|
||||||
|
responseRegister: message,
|
||||||
|
isRegisterError: !!err
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveName(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const embarkLogs = this.state.embarkLogs;
|
||||||
|
embarkLogs.push(`EmbarkJS.Names.resolve('${this.state.valueResolve}', console.log)`);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
embarkLogs: embarkLogs
|
||||||
|
});
|
||||||
|
EmbarkJS.Names.resolve(this.state.valueResolve, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
return this.setState({
|
||||||
|
responseResolve: err.message || err,
|
||||||
|
isResolveError: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
responseResolve: result,
|
||||||
|
isResolveError: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
lookupAddress(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const embarkLogs = this.state.embarkLogs;
|
||||||
|
embarkLogs.push(`EmbarkJS.Names.resolve('${this.state.valueLookup}', console.log)`);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
embarkLogs: embarkLogs
|
||||||
|
});
|
||||||
|
EmbarkJS.Names.lookup(this.state.valueLookup, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
return this.setState({
|
||||||
|
responseLookup: err.message || err,
|
||||||
|
isLookupError: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
responseLookup: result,
|
||||||
|
isLookupError: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (<React.Fragment>
|
||||||
|
{this.state.globalError && <Alert bsStyle="danger">{this.state.globalError}</Alert>}
|
||||||
|
<h3>Resolve a name</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.resolveName)}>
|
||||||
|
<FormGroup>
|
||||||
|
{this.state.responseResolve &&
|
||||||
|
<Alert className="alert-result" bsStyle={this.state.isResolveError ? 'danger' : 'success'}>
|
||||||
|
Resolved address: <span className="value">{this.state.responseResolve}</span>
|
||||||
|
</Alert>}
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.valueResolve}
|
||||||
|
onChange={(e) => this.handleChange('valueResolve', e)}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.resolveName(e)}>Resolve name</Button>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Lookup an address</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.lookupAddress)}>
|
||||||
|
<FormGroup>
|
||||||
|
{this.state.responseLookup &&
|
||||||
|
<Alert className="alert-result" bsStyle={this.state.isLookupError ? 'danger' : 'success'}>
|
||||||
|
Looked up domain: <span className="value">{this.state.responseLookup}</span>
|
||||||
|
</Alert>}
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.valueLookup}
|
||||||
|
onChange={(e) => this.handleChange('valueLookup', e)}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.lookupAddress(e)}>Lookup address</Button>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Register subdomain</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.registerSubDomain)}>
|
||||||
|
<FormGroup>
|
||||||
|
{this.state.responseRegister &&
|
||||||
|
<Alert className="alert-result" bsStyle={this.state.isRegisterError ? 'danger' : 'success'}>
|
||||||
|
<span className="value">{this.state.responseRegister}</span>
|
||||||
|
</Alert>}
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.valueRegister}
|
||||||
|
onChange={(e) => this.handleChange('valueRegister', e)}/>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.addressRegister}
|
||||||
|
onChange={(e) => this.handleChange('addressRegister', e)}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.registerSubDomain(e)}>Register subdomain</Button>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Embark Calls </h3>
|
||||||
|
<p>Javascript calls being made: </p>
|
||||||
|
<div className="logs">
|
||||||
|
{
|
||||||
|
this.state.embarkLogs.map((item, i) => <p key={i}>{item}</p>)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ENS;
|
|
@ -0,0 +1,272 @@
|
||||||
|
import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
|
import React from 'react';
|
||||||
|
import {Alert, Form, FormGroup, FormControl, HelpBlock, Button} from 'react-bootstrap';
|
||||||
|
|
||||||
|
class Storage extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
textToSave: 'hello world!',
|
||||||
|
generatedHash: '',
|
||||||
|
loadText: '',
|
||||||
|
storedText: '',
|
||||||
|
fileToUpload: null,
|
||||||
|
fileHash: '',
|
||||||
|
imageToDownload: '',
|
||||||
|
url: '',
|
||||||
|
logs: [],
|
||||||
|
storageError: '',
|
||||||
|
valueRegister: '',
|
||||||
|
valueResolver: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange(e, name) {
|
||||||
|
this.state[name] = e.target.value;
|
||||||
|
this.setState(this.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkEnter(e, func) {
|
||||||
|
if (e.key !== 'Enter') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
func.apply(this, [e]);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFileUpload(e) {
|
||||||
|
this.setState({fileToUpload: [e.target]});
|
||||||
|
}
|
||||||
|
|
||||||
|
addToLog(txt) {
|
||||||
|
this.state.logs.push(txt);
|
||||||
|
this.setState({logs: this.state.logs});
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
EmbarkJS.Storage.saveText(this.state.textToSave)
|
||||||
|
.then((hash) => {
|
||||||
|
this.setState({
|
||||||
|
generatedHash: hash,
|
||||||
|
loadText: hash,
|
||||||
|
storageError: ''
|
||||||
|
});
|
||||||
|
this.addToLog("EmbarkJS.Storage.saveText('" + this.state.textToSave + "').then(function(hash) { })");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (err) {
|
||||||
|
this.setState({storageError: err.message});
|
||||||
|
console.log("Storage saveText Error => " + err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadHash(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
EmbarkJS.Storage.get(this.state.loadText)
|
||||||
|
.then((content) => {
|
||||||
|
this.setState({storedText: content, storageError: ''});
|
||||||
|
this.addToLog("EmbarkJS.Storage.get('" + this.state.loadText + "').then(function(content) { })");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (err) {
|
||||||
|
this.setState({storageError: err.message});
|
||||||
|
console.log("Storage get Error => " + err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadFile(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
EmbarkJS.Storage.uploadFile(this.state.fileToUpload)
|
||||||
|
.then((hash) => {
|
||||||
|
this.setState({
|
||||||
|
fileHash: hash,
|
||||||
|
imageToDownload: hash,
|
||||||
|
storageError: ''
|
||||||
|
});
|
||||||
|
this.addToLog("EmbarkJS.Storage.uploadFile(this.state.fileToUpload).then(function(hash) { })");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (err) {
|
||||||
|
this.setState({storageError: err.message});
|
||||||
|
console.log("Storage uploadFile Error => " + err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadFile(e) {
|
||||||
|
let _url = EmbarkJS.Storage.getUrl(this.state.imageToDownload);
|
||||||
|
this.setState({url: _url});
|
||||||
|
this.addToLog("EmbarkJS.Storage.getUrl('" + this.state.imageToDownload + "')");
|
||||||
|
}
|
||||||
|
|
||||||
|
ipnsRegister(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.setState({ registering: true, responseRegister: false });
|
||||||
|
this.addToLog("EmbarkJS.Storage.register(this.state.ipfsHash).then(function(hash) { })");
|
||||||
|
EmbarkJS.Storage.register(this.state.valueRegister, (err, name) => {
|
||||||
|
let responseRegister;
|
||||||
|
let isRegisterError = false;
|
||||||
|
if (err) {
|
||||||
|
isRegisterError = true;
|
||||||
|
responseRegister = "Name Register Error: " + (err.message || err)
|
||||||
|
} else {
|
||||||
|
responseRegister = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
registering: false,
|
||||||
|
responseRegister,
|
||||||
|
isRegisterError
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ipnsResolve(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.setState({ resolving: true, responseResolver: false });
|
||||||
|
this.addToLog("EmbarkJS.Storage.resolve(this.state.ipnsName, function(err, path) { })");
|
||||||
|
EmbarkJS.Storage.resolve(this.state.valueResolver, (err, path) => {
|
||||||
|
let responseResolver;
|
||||||
|
let isResolverError = false;
|
||||||
|
if (err) {
|
||||||
|
isResolverError = true;
|
||||||
|
responseResolver = "Name Resolve Error: " + (err.message || err)
|
||||||
|
} else {
|
||||||
|
responseResolver = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
resolving: false,
|
||||||
|
responseResolver,
|
||||||
|
isResolverError
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isIpfs(){
|
||||||
|
return EmbarkJS.Storage.currentProviderName === 'ipfs';
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <React.Fragment>
|
||||||
|
{
|
||||||
|
!this.props.enabled ?
|
||||||
|
<React.Fragment>
|
||||||
|
<Alert bsStyle="warning">The node you are using does not support IPFS. Please ensure <a
|
||||||
|
href="https://github.com/ipfs/js-ipfs-api#cors" target="_blank">CORS</a> is setup for the IPFS
|
||||||
|
node.</Alert>
|
||||||
|
</React.Fragment> : ''
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.state.storageError !== '' ?
|
||||||
|
<Alert bsStyle="danger">{this.state.storageError}</Alert>
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
<h3>Save text to storage</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.setText)}>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.textToSave}
|
||||||
|
onChange={e => this.handleChange(e, 'textToSave')}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.setText(e)}>Save Text</Button>
|
||||||
|
<HelpBlock>generated Hash: <span className="textHash">{this.state.generatedHash}</span></HelpBlock>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Load text from storage given an hash</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.loadHash)}>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
value={this.state.loadText}
|
||||||
|
onChange={e => this.handleChange(e, 'loadText')}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.loadHash(e)}>Load</Button>
|
||||||
|
<HelpBlock>result: <span className="textHash">{this.state.storedText}</span></HelpBlock>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Upload file to storage</h3>
|
||||||
|
<Form inline>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="file"
|
||||||
|
onChange={(e) => this.handleFileUpload(e)}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.uploadFile(e)}>Upload</Button>
|
||||||
|
<HelpBlock>generated hash: <span className="fileHash">{this.state.fileHash}</span></HelpBlock>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Get file or image from storage</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.loadFile)}>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
value={this.state.imageToDownload}
|
||||||
|
onChange={e => this.handleChange(e, 'imageToDownload')}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.loadFile(e)}>Download</Button>
|
||||||
|
<HelpBlock>file available at: <span><a href={this.state.url}
|
||||||
|
target="_blank">{this.state.url}</a></span></HelpBlock>
|
||||||
|
<HelpBlock><img src={this.state.url}/></HelpBlock>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
{!this.isIpfs() && <Alert bsStyle="warning">The 2 functions below are only available with IPFS</Alert>}
|
||||||
|
|
||||||
|
<h3>Register to IPNS</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.ipnsRegister)}>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
value={this.state.valueRegister}
|
||||||
|
onChange={e => this.handleChange(e, 'valueRegister')}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.ipnsRegister(e)}>
|
||||||
|
{this.state.registering ? 'Registering...' : 'Register' }
|
||||||
|
</Button>
|
||||||
|
<HelpBlock>It will take around 1 minute</HelpBlock>
|
||||||
|
{this.state.responseRegister &&
|
||||||
|
<Alert className="alert-result" bsStyle={this.state.isRegisterError ? 'danger' : 'success'}>
|
||||||
|
<span className="value">{this.state.responseRegister}</span>
|
||||||
|
</Alert>}
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Resolve name</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.ipnsResolve)}>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
value={this.state.valueResolver}
|
||||||
|
onChange={e => this.handleChange(e, 'valueResolver')}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.ipnsResolve(e)}>
|
||||||
|
{this.state.resolving ? 'Resolving...' : 'Resolve' }
|
||||||
|
</Button>
|
||||||
|
<HelpBlock>It will take around 1 minute</HelpBlock>
|
||||||
|
{this.state.responseResolver &&
|
||||||
|
<Alert className="alert-result" bsStyle={this.state.isResolverError ? 'danger' : 'success'}>
|
||||||
|
<span className="value">{this.state.responseResolver}</span>
|
||||||
|
</Alert>}
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Javascript calls being made: </p>
|
||||||
|
<div className="logs">
|
||||||
|
<p>EmbarkJS.Storage.setProvider('ipfs',{'{'}server: 'localhost', port: '5001'{'}'})</p>
|
||||||
|
{
|
||||||
|
this.state.logs.map((item, i) => <p key={i}>{item}</p>)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</React.Fragment>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Storage;
|
|
@ -0,0 +1,126 @@
|
||||||
|
import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
|
import React from 'react';
|
||||||
|
import {Alert, Form, FormGroup, FormControl, Button} from 'react-bootstrap';
|
||||||
|
|
||||||
|
class Whisper extends React.Component {
|
||||||
|
|
||||||
|
constructor (props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
listenTo: '',
|
||||||
|
channel: '',
|
||||||
|
message: '',
|
||||||
|
subscribedChannels: [],
|
||||||
|
messageList: [],
|
||||||
|
logs: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange (e, name) {
|
||||||
|
this.state[name] = e.target.value;
|
||||||
|
this.setState(this.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkEnter(e, func) {
|
||||||
|
if (e.key !== 'Enter') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
func.apply(this, [e]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
EmbarkJS.Messages.sendMessage({topic: this.state.channel, data: this.state.message});
|
||||||
|
this.addToLog("EmbarkJS.Messages.sendMessage({topic: '" + this.state.channel + "', data: '" + this.state.message + "'})");
|
||||||
|
}
|
||||||
|
|
||||||
|
listenToChannel (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const subscribedChannels = this.state.subscribedChannels;
|
||||||
|
subscribedChannels.push(<span>Subscribed to <b>{this.state.listenTo}</b>. Now try sending a message</span>);
|
||||||
|
this.setState({
|
||||||
|
subscribedChannels
|
||||||
|
});
|
||||||
|
|
||||||
|
EmbarkJS.Messages.listenTo({topic: [this.state.listenTo]}, (error, message) => {
|
||||||
|
const messageList = this.state.messageList;
|
||||||
|
if (error) {
|
||||||
|
messageList.push(<span className="alert-danger">Error: {error}</span>);
|
||||||
|
} else {
|
||||||
|
messageList.push(<span>Channel: <b>{message.topic}</b> | Message: <b>{message.data}</b></span>);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
messageList
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addToLog("EmbarkJS.Messages.listenTo({topic: ['" + this.state.listenTo + "']}).then(function(message) {})");
|
||||||
|
}
|
||||||
|
|
||||||
|
addToLog (txt) {
|
||||||
|
this.state.logs.push(txt);
|
||||||
|
this.setState({logs: this.state.logs});
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{
|
||||||
|
!this.props.enabled ?
|
||||||
|
<React.Fragment>
|
||||||
|
<Alert bsStyle="warning">The node you are using does not support Whisper</Alert>
|
||||||
|
<Alert bsStyle="warning">The node uses an unsupported version of Whisper</Alert>
|
||||||
|
</React.Fragment> : ''
|
||||||
|
}
|
||||||
|
<h3>Listen To channel</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.listenToChannel)}>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.listenTo}
|
||||||
|
placeholder="channel"
|
||||||
|
onChange={e => this.handleChange(e, 'listenTo')}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.listenToChannel(e)}>Start Listening</Button>
|
||||||
|
<div id="subscribeList">
|
||||||
|
{this.state.subscribedChannels.map((item, i) => <p key={i}>{item}</p>)}
|
||||||
|
</div>
|
||||||
|
<p>messages received:</p>
|
||||||
|
<div id="messagesList">
|
||||||
|
{this.state.messageList.map((item, i) => <p key={i}>{item}</p>)}
|
||||||
|
</div>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Send Message</h3>
|
||||||
|
<Form inline onKeyDown={(e) => this.checkEnter(e, this.sendMessage)}>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.channel}
|
||||||
|
placeholder="channel"
|
||||||
|
onChange={e => this.handleChange(e, 'channel')}/>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.message}
|
||||||
|
placeholder="message"
|
||||||
|
onChange={e => this.handleChange(e, 'message')}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.sendMessage(e)}>Send Message</Button>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<p>Javascript calls being made: </p>
|
||||||
|
<div className="logs">
|
||||||
|
<p>EmbarkJS.Messages.setProvider('whisper')</p>
|
||||||
|
{
|
||||||
|
this.state.logs.map((item, i) => <p key={i}>{item}</p>)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Whisper;
|
|
@ -0,0 +1,57 @@
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logs {
|
||||||
|
background-color: black;
|
||||||
|
font-size: 14px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
border-left: 1px solid #ddd;
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tabs {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-offline {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-top: 4px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
background: red;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-online {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-top: 4px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
background: mediumseagreen;
|
||||||
|
-moz-border-radius: 10px;
|
||||||
|
-webkit-border-radius: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.form-control {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-result {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import {Tabs, Tab} from 'react-bootstrap';
|
||||||
|
|
||||||
|
import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
|
import Blockchain from './components/blockchain';
|
||||||
|
import Whisper from './components/whisper';
|
||||||
|
import Storage from './components/storage';
|
||||||
|
import ENS from './components/ens';
|
||||||
|
|
||||||
|
import './dapp.css';
|
||||||
|
|
||||||
|
class App extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleSelect = this.handleSelect.bind(this);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
error: null,
|
||||||
|
activeKey: 1,
|
||||||
|
whisperEnabled: false,
|
||||||
|
storageEnabled: false,
|
||||||
|
blockchainEnabled: false,
|
||||||
|
ensEnabled: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
EmbarkJS.onReady((err) => {
|
||||||
|
this.setState({blockchainEnabled: true});
|
||||||
|
if (err) {
|
||||||
|
// If err is not null then it means something went wrong connecting to ethereum
|
||||||
|
// you can use this to ask the user to enable metamask for e.g
|
||||||
|
return this.setState({error: err.message || err});
|
||||||
|
}
|
||||||
|
|
||||||
|
EmbarkJS.Messages.Providers.whisper.getWhisperVersion((err, _version) => {
|
||||||
|
if (err) {
|
||||||
|
return console.log(err);
|
||||||
|
}
|
||||||
|
this.setState({whisperEnabled: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
EmbarkJS.Storage.isAvailable().then((result) => {
|
||||||
|
this.setState({storageEnabled: result});
|
||||||
|
}).catch(() => {
|
||||||
|
this.setState({storageEnabled: false});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderStatus(title, available) {
|
||||||
|
let className = available ? 'pull-right status-online' : 'pull-right status-offline';
|
||||||
|
return <React.Fragment>
|
||||||
|
{title}
|
||||||
|
<span className={className}></span>
|
||||||
|
</React.Fragment>;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSelect(key) {
|
||||||
|
this.setState({ activeKey: key });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const ensEnabled = EmbarkJS.Names.currentNameSystems && EmbarkJS.Names.isAvailable();
|
||||||
|
if (this.state.error) {
|
||||||
|
return (<div>
|
||||||
|
<div>Something went wrong connecting to ethereum. Please make sure you have a node running or are using metamask to connect to the ethereum network:</div>
|
||||||
|
<div>{this.state.error}</div>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
return (<div>
|
||||||
|
<h3>Embark - Usage Example</h3>
|
||||||
|
<Tabs onSelect={this.handleSelect} activeKey={this.state.activeKey} id="uncontrolled-tab-example">
|
||||||
|
<Tab eventKey={1} title={this._renderStatus('Blockchain', this.state.blockchainEnabled)}>
|
||||||
|
<Blockchain/>
|
||||||
|
</Tab>
|
||||||
|
<Tab eventKey={2} title={this._renderStatus('Decentralized Storage', this.state.storageEnabled)}>
|
||||||
|
<Storage enabled={this.state.storageEnabled}/>
|
||||||
|
</Tab>
|
||||||
|
<Tab eventKey={3} title={this._renderStatus('P2P communication (Whisper)', this.state.whisperEnabled)}>
|
||||||
|
<Whisper enabled={this.state.whisperEnabled}/>
|
||||||
|
</Tab>
|
||||||
|
<Tab eventKey={4} title={this._renderStatus('Naming (ENS)', ensEnabled)}>
|
||||||
|
<ENS enabled={ensEnabled}/>
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(<App></App>, document.getElementById('app'));
|
|
@ -0,0 +1,12 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Embark - SimpleStorage Demo</title>
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||||
|
</head>
|
||||||
|
<body class="container">
|
||||||
|
<div id="app">
|
||||||
|
</div>
|
||||||
|
<script src="js/dapp.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"0x4c88925b6fabc1d138606800ff7f4fb5d90b1977624f38f99576056449a6a500": {
|
||||||
|
"contracts": {
|
||||||
|
"0x0aea975ceeaff5c320a0559708c5c6f94999421a0be61587cdece9b4542cc110": {
|
||||||
|
"name": "SimpleStorage",
|
||||||
|
"address": "0x74A18cBcd27e4652cD3FE852C5362432056E6480"
|
||||||
|
},
|
||||||
|
"0x3043b04ad856d169c8f0b0509c0bc63192dc7edd92d6933c58708298a0e381be": {
|
||||||
|
"name": "ENSRegistry",
|
||||||
|
"address": "0x88D7fD23Fc1c96FF89BeAd9aEb24Ccca96432c63"
|
||||||
|
},
|
||||||
|
"0x60daddeb23aae81f0807e071c25012fc78e521a3e829d2b1fcda1b8bc40d3815": {
|
||||||
|
"name": "Resolver",
|
||||||
|
"address": "0xcF1FF793d4510E1E2838642BC4B118AB14C5B1ac"
|
||||||
|
},
|
||||||
|
"0x842276d67a5bf54ee66032015bbeb8f58ca3ce6cabf05cf7ec19b0b282c6dbc0": {
|
||||||
|
"name": "FIFSRegistrar",
|
||||||
|
"address": "0x8fcDa55C6F48A9c591eA5227837dA30B9560Ed33"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
module.exports = {
|
||||||
|
// applies to all environments
|
||||||
|
default: {
|
||||||
|
enabled: true,
|
||||||
|
rpcHost: "localhost", // HTTP-RPC server listening interface (default: "localhost")
|
||||||
|
rpcPort: 8545, // HTTP-RPC server listening port (default: 8545)
|
||||||
|
rpcCorsDomain: "auto", // Comma separated list of domains from which to accept cross origin requests (browser enforced)
|
||||||
|
// When set to "auto", Embark will automatically set the cors to the address of the webserver
|
||||||
|
wsRPC: true, // Enable the WS-RPC server
|
||||||
|
wsOrigins: "auto", // Origins from which to accept websockets requests
|
||||||
|
// When set to "auto", Embark will automatically set the cors to the address of the webserver
|
||||||
|
wsHost: "localhost", // WS-RPC server listening interface (default: "localhost")
|
||||||
|
wsPort: 8546 // WS-RPC server listening port (default: 8546)
|
||||||
|
},
|
||||||
|
|
||||||
|
// default environment, merges with the settings in default
|
||||||
|
// assumed to be the intended environment by `embark run` and `embark blockchain`
|
||||||
|
development: {
|
||||||
|
networkType: "custom", // Can be: testnet, rinkeby, livenet or custom, in which case, it will use the specified networkId
|
||||||
|
networkId: "1337", // Network id used when networkType is custom
|
||||||
|
isDev: true, // Uses and ephemeral proof-of-authority network with a pre-funded developer account, mining enabled
|
||||||
|
datadir: ".embark/development/datadir", // Data directory for the databases and keystore
|
||||||
|
mineWhenNeeded: true, // Uses our custom script (if isDev is false) to mine only when needed
|
||||||
|
nodiscover: true, // Disables the peer discovery mechanism (manual peer addition)
|
||||||
|
maxpeers: 0, // Maximum number of network peers (network disabled if set to 0) (default: 25)
|
||||||
|
proxy: true, // Proxy is used to present meaningful information about transactions
|
||||||
|
targetGasLimit: 8000000, // Target gas limit sets the artificial target gas floor for the blocks to mine
|
||||||
|
simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm", // Mnemonic used by the simulator to generate a wallet
|
||||||
|
simulatorBlocktime: 0, // Specify blockTime in seconds for automatic mining. Default is 0 and no auto-mining.
|
||||||
|
account: {
|
||||||
|
// numAccounts: 3, // When specified, creates accounts for use in the dapp. This option only works in the development environment, and can be used as a quick start option that bypasses the need for MetaMask in development. These accounts are unlocked and funded with the below settings.
|
||||||
|
// password: "config/development/password", // Password for the created accounts (as specified in the `numAccounts` setting). If `mineWhenNeeded` is enabled (and isDev is not), this password is used to create a development account controlled by the node.
|
||||||
|
// balance: "5 ether" // Balance to be given to the created accounts (as specified in the `numAccounts` setting)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run privatenet" and/or "embark blockchain privatenet"
|
||||||
|
privatenet: {
|
||||||
|
networkType: "custom",
|
||||||
|
networkId: "1337",
|
||||||
|
isDev: false,
|
||||||
|
datadir: ".embark/privatenet/datadir",
|
||||||
|
// -- mineWhenNeeded --
|
||||||
|
// This options is only valid when isDev is false.
|
||||||
|
// Enabling this option uses our custom script to mine only when needed.
|
||||||
|
// Embark creates a development account for you (using `geth account new`) and funds the account. This account can be used for
|
||||||
|
// development (and even imported in to MetaMask). To enable correct usage, a password for this account must be specified
|
||||||
|
// in the `account > password` setting below.
|
||||||
|
// NOTE: once `mineWhenNeeded` is enabled, you must run an `embark reset` on your dApp before running
|
||||||
|
// `embark blockchain` or `embark run` for the first time.
|
||||||
|
mineWhenNeeded: true,
|
||||||
|
// -- genesisBlock --
|
||||||
|
// This option is only valid when mineWhenNeeded is true (which is only valid if isDev is false).
|
||||||
|
// When enabled, geth uses POW to mine transactions as it would normally, instead of using POA as it does in --dev mode.
|
||||||
|
// On the first `embark blockchain or embark run` after this option is enabled, geth will create a new chain with a
|
||||||
|
// genesis block, which can be configured using the `genesisBlock` configuration option below.
|
||||||
|
genesisBlock: "config/privatenet/genesis.json", // Genesis block to initiate on first creation of a development node
|
||||||
|
nodiscover: true,
|
||||||
|
maxpeers: 0,
|
||||||
|
proxy: true,
|
||||||
|
account: {
|
||||||
|
// "address": "", // When specified, uses that address instead of the default one for the network
|
||||||
|
password: "config/privatenet/password" // Password to unlock the account
|
||||||
|
},
|
||||||
|
targetGasLimit: 8000000,
|
||||||
|
wsHost: "localhost",
|
||||||
|
wsPort: 8546,
|
||||||
|
simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm",
|
||||||
|
simulatorBlocktime: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run testnet" and/or "embark blockchain testnet"
|
||||||
|
testnet: {
|
||||||
|
networkType: "testnet",
|
||||||
|
syncMode: "light",
|
||||||
|
account: {
|
||||||
|
password: "config/testnet/password"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run livenet" and/or "embark blockchain livenet"
|
||||||
|
livenet: {
|
||||||
|
networkType: "livenet",
|
||||||
|
syncMode: "light",
|
||||||
|
rpcCorsDomain: "http://localhost:8000",
|
||||||
|
wsOrigins: "http://localhost:8000",
|
||||||
|
account: {
|
||||||
|
password: "config/livenet/password"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// you can name an environment with specific settings and then specify with
|
||||||
|
// "embark run custom_name" or "embark blockchain custom_name"
|
||||||
|
//custom_name: {
|
||||||
|
//}
|
||||||
|
};
|
|
@ -0,0 +1,46 @@
|
||||||
|
module.exports = {
|
||||||
|
// default applies to all environments
|
||||||
|
default: {
|
||||||
|
enabled: true,
|
||||||
|
provider: "whisper", // Communication provider. Currently, Embark only supports whisper
|
||||||
|
available_providers: ["whisper"], // Array of available providers
|
||||||
|
},
|
||||||
|
|
||||||
|
// default environment, merges with the settings in default
|
||||||
|
// assumed to be the intended environment by `embark run`
|
||||||
|
development: {
|
||||||
|
connection: {
|
||||||
|
host: "localhost", // Host of the blockchain node
|
||||||
|
port: 8546, // Port of the blockchain node
|
||||||
|
type: "ws" // Type of connection (ws or rpc)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run privatenet"
|
||||||
|
privatenet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run testnet"
|
||||||
|
testnet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run livenet"
|
||||||
|
livenet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// you can name an environment with specific settings and then specify with
|
||||||
|
// "embark run custom_name"
|
||||||
|
//custom_name: {
|
||||||
|
//}
|
||||||
|
// Use this section when you need a specific symmetric or private keys in whisper
|
||||||
|
/*
|
||||||
|
,keys: {
|
||||||
|
symmetricKey: "your_symmetric_key",// Symmetric key for message decryption
|
||||||
|
privateKey: "your_private_key" // Private Key to be used as a signing key and for message decryption
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
};
|
|
@ -0,0 +1,72 @@
|
||||||
|
module.exports = {
|
||||||
|
// default applies to all environments
|
||||||
|
default: {
|
||||||
|
// Blockchain node to deploy the contracts
|
||||||
|
deployment: {
|
||||||
|
host: "localhost", // Host of the blockchain node
|
||||||
|
port: 8545, // Port of the blockchain node
|
||||||
|
type: "rpc" // Type of connection (ws or rpc),
|
||||||
|
// Accounts to use instead of the default account to populate your wallet
|
||||||
|
/*,accounts: [
|
||||||
|
{
|
||||||
|
privateKey: "your_private_key",
|
||||||
|
balance: "5 ether" // You can set the balance of the account in the dev environment
|
||||||
|
// Balances are in Wei, but you can specify the unit with its name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
privateKeyFile: "path/to/file", // Either a keystore or a list of keys, separated by , or ;
|
||||||
|
password: "passwordForTheKeystore" // Needed to decrypt the keystore file
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mnemonic: "12 word mnemonic",
|
||||||
|
addressIndex: "0", // Optionnal. The index to start getting the address
|
||||||
|
numAddresses: "1", // Optionnal. The number of addresses to get
|
||||||
|
hdpath: "m/44'/60'/0'/0/" // Optionnal. HD derivation path
|
||||||
|
}
|
||||||
|
]*/
|
||||||
|
},
|
||||||
|
// order of connections the dapp should connect to
|
||||||
|
dappConnection: [
|
||||||
|
"$WEB3", // uses pre existing web3 object if available (e.g in Mist)
|
||||||
|
"ws://localhost:8546",
|
||||||
|
"http://localhost:8545"
|
||||||
|
],
|
||||||
|
gas: "auto",
|
||||||
|
contracts: {
|
||||||
|
SimpleStorage: {
|
||||||
|
fromIndex: 0,
|
||||||
|
args: [100]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// default environment, merges with the settings in default
|
||||||
|
// assumed to be the intended environment by `embark run`
|
||||||
|
development: {
|
||||||
|
dappConnection: [
|
||||||
|
"ws://localhost:8546",
|
||||||
|
"http://localhost:8545",
|
||||||
|
"$WEB3" // uses pre existing web3 object if available (e.g in Mist)
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run privatenet"
|
||||||
|
privatenet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run testnet"
|
||||||
|
testnet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run livenet"
|
||||||
|
livenet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// you can name an environment with specific settings and then specify with
|
||||||
|
// "embark run custom_name" or "embark blockchain custom_name"
|
||||||
|
//custom_name: {
|
||||||
|
//}
|
||||||
|
};
|
|
@ -0,0 +1,39 @@
|
||||||
|
module.exports = {
|
||||||
|
// default applies to all environments
|
||||||
|
default: {
|
||||||
|
enabled: true,
|
||||||
|
available_providers: ["ens"],
|
||||||
|
provider: "ens"
|
||||||
|
},
|
||||||
|
|
||||||
|
// default environment, merges with the settings in default
|
||||||
|
// assumed to be the intended environment by `embark run`
|
||||||
|
development: {
|
||||||
|
register: {
|
||||||
|
rootDomain: "eth",
|
||||||
|
subdomains: {
|
||||||
|
'embark': '0x1a2f3b98e434c02363f3dac3174af93c1d690914'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run privatenet"
|
||||||
|
privatenet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run testnet"
|
||||||
|
testnet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run livenet"
|
||||||
|
livenet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// you can name an environment with specific settings and then specify with
|
||||||
|
// "embark run custom_name" or "embark blockchain custom_name"
|
||||||
|
//custom_name: {
|
||||||
|
//}
|
||||||
|
};
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"homesteadBlock": 0,
|
||||||
|
"byzantiumBlock": 0,
|
||||||
|
"daoForkSupport": true
|
||||||
|
},
|
||||||
|
"nonce": "0x0000000000000042",
|
||||||
|
"difficulty": "0x0",
|
||||||
|
"alloc": {
|
||||||
|
"0x3333333333333333333333333333333333333333": {"balance": "15000000000000000000"}
|
||||||
|
},
|
||||||
|
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"coinbase": "0x3333333333333333333333333333333333333333",
|
||||||
|
"timestamp": "0x00",
|
||||||
|
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"extraData": "0x",
|
||||||
|
"gasLimit": "0x7a1200"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
dev_password
|
|
@ -0,0 +1,59 @@
|
||||||
|
module.exports = {
|
||||||
|
// default applies to all environments
|
||||||
|
default: {
|
||||||
|
enabled: true,
|
||||||
|
ipfs_bin: "ipfs",
|
||||||
|
provider: "ipfs",
|
||||||
|
available_providers: ["ipfs"],
|
||||||
|
upload: {
|
||||||
|
host: "localhost",
|
||||||
|
port: 5001
|
||||||
|
},
|
||||||
|
dappConnection: [
|
||||||
|
{
|
||||||
|
provider:"ipfs",
|
||||||
|
host: "localhost",
|
||||||
|
port: 5001,
|
||||||
|
getUrl: "http://localhost:8080/ipfs/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
// Configuration to start Swarm in the same terminal as `embark run`
|
||||||
|
/*,account: {
|
||||||
|
address: "YOUR_ACCOUNT_ADDRESS", // Address of account accessing Swarm
|
||||||
|
password: "PATH/TO/PASSWORD/FILE" // File containing the password of the account
|
||||||
|
},
|
||||||
|
swarmPath: "PATH/TO/SWARM/EXECUTABLE" // Path to swarm executable (default: swarm)*/
|
||||||
|
},
|
||||||
|
|
||||||
|
// default environment, merges with the settings in default
|
||||||
|
// assumed to be the intended environment by `embark run`
|
||||||
|
development: {
|
||||||
|
enabled: true,
|
||||||
|
provider: "ipfs",
|
||||||
|
upload: {
|
||||||
|
host: "localhost",
|
||||||
|
port: 5001,
|
||||||
|
getUrl: "http://localhost:8080/ipfs/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run privatenet"
|
||||||
|
privatenet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run testnet"
|
||||||
|
testnet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// merges with the settings in default
|
||||||
|
// used with "embark run livenet"
|
||||||
|
livenet: {
|
||||||
|
},
|
||||||
|
|
||||||
|
// you can name an environment with specific settings and then specify with
|
||||||
|
// "embark run custom_name"
|
||||||
|
//custom_name: {
|
||||||
|
//}
|
||||||
|
};
|
|
@ -0,0 +1 @@
|
||||||
|
test_password
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
enabled: true,
|
||||||
|
host: "localhost",
|
||||||
|
openBrowser: true,
|
||||||
|
port: 8000
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
pragma solidity ^0.4.25;
|
||||||
|
|
||||||
|
contract SimpleStorage {
|
||||||
|
uint public storedData;
|
||||||
|
address owner;
|
||||||
|
|
||||||
|
constructor(uint initialValue) public {
|
||||||
|
storedData = initialValue;
|
||||||
|
owner = msg.sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set(uint x) public {
|
||||||
|
storedData = x;
|
||||||
|
require(msg.sender != owner);
|
||||||
|
storedData = x + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get() public view returns (uint retVal) {
|
||||||
|
return storedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"contracts": ["contracts/**"],
|
||||||
|
"app": {
|
||||||
|
"js/dapp.js": ["app/dapp.js"],
|
||||||
|
"index.html": "app/index.html",
|
||||||
|
"images/": ["app/images/**"]
|
||||||
|
},
|
||||||
|
"buildDir": "dist/",
|
||||||
|
"config": "config/",
|
||||||
|
"versions": {
|
||||||
|
"web3": "1.0.0-beta",
|
||||||
|
"solc": "0.4.25",
|
||||||
|
"ipfs-api": "17.2.4"
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"solc": {
|
||||||
|
"optimize": true,
|
||||||
|
"optimize-runs": 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,278 @@
|
||||||
|
{
|
||||||
|
"name": "app_name",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"asap": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
||||||
|
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
|
||||||
|
},
|
||||||
|
"babel-runtime": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||||
|
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "^2.4.0",
|
||||||
|
"regenerator-runtime": "^0.11.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": {
|
||||||
|
"version": "2.5.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
|
||||||
|
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"classnames": {
|
||||||
|
"version": "2.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
|
||||||
|
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
|
||||||
|
},
|
||||||
|
"core-js": {
|
||||||
|
"version": "1.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
|
||||||
|
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
|
||||||
|
},
|
||||||
|
"dom-helpers": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg=="
|
||||||
|
},
|
||||||
|
"encoding": {
|
||||||
|
"version": "0.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
|
||||||
|
"integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
|
||||||
|
"requires": {
|
||||||
|
"iconv-lite": "~0.4.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fbjs": {
|
||||||
|
"version": "0.8.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
|
||||||
|
"integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "^1.0.0",
|
||||||
|
"isomorphic-fetch": "^2.1.1",
|
||||||
|
"loose-envify": "^1.0.0",
|
||||||
|
"object-assign": "^4.1.0",
|
||||||
|
"promise": "^7.1.1",
|
||||||
|
"setimmediate": "^1.0.5",
|
||||||
|
"ua-parser-js": "^0.7.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"iconv-lite": {
|
||||||
|
"version": "0.4.23",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
|
||||||
|
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
|
||||||
|
"requires": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"invariant": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-stream": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||||
|
},
|
||||||
|
"isomorphic-fetch": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
|
||||||
|
"integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
|
||||||
|
"requires": {
|
||||||
|
"node-fetch": "^1.0.1",
|
||||||
|
"whatwg-fetch": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"js-tokens": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||||
|
},
|
||||||
|
"keycode": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ="
|
||||||
|
},
|
||||||
|
"loose-envify": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||||
|
"requires": {
|
||||||
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
|
||||||
|
"integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
|
||||||
|
"requires": {
|
||||||
|
"encoding": "^0.1.11",
|
||||||
|
"is-stream": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"object-assign": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||||
|
},
|
||||||
|
"promise": {
|
||||||
|
"version": "7.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
|
||||||
|
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
|
||||||
|
"requires": {
|
||||||
|
"asap": "~2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prop-types": {
|
||||||
|
"version": "15.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
|
||||||
|
"integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.3.1",
|
||||||
|
"object-assign": "^4.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prop-types-extra": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-QFyuDxvMipmIVKD2TwxLVPzMnO4e5oOf1vr3tJIomL8E7d0lr6phTHd5nkPhFIzTD1idBLLEPeylL9g+rrTzRg==",
|
||||||
|
"requires": {
|
||||||
|
"react-is": "^16.3.2",
|
||||||
|
"warning": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"version": "16.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react/-/react-16.4.2.tgz",
|
||||||
|
"integrity": "sha512-dMv7YrbxO4y2aqnvA7f/ik9ibeLSHQJTI6TrYAenPSaQ6OXfb+Oti+oJiy8WBxgRzlKatYqtCjphTgDSCEiWFg==",
|
||||||
|
"requires": {
|
||||||
|
"fbjs": "^0.8.16",
|
||||||
|
"loose-envify": "^1.1.0",
|
||||||
|
"object-assign": "^4.1.1",
|
||||||
|
"prop-types": "^15.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-bootstrap": {
|
||||||
|
"version": "0.32.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.32.1.tgz",
|
||||||
|
"integrity": "sha512-RbfzKUbsukWsToWqGHfCCyMFq9QQI0TznutdyxyJw6dih2NvIne25Mrssg8LZsprqtPpyQi8bN0L0Fx3fUsL8Q==",
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "^6.11.6",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"dom-helpers": "^3.2.0",
|
||||||
|
"invariant": "^2.2.1",
|
||||||
|
"keycode": "^2.1.2",
|
||||||
|
"prop-types": "^15.5.10",
|
||||||
|
"prop-types-extra": "^1.0.1",
|
||||||
|
"react-overlays": "^0.8.0",
|
||||||
|
"react-prop-types": "^0.4.0",
|
||||||
|
"react-transition-group": "^2.0.0",
|
||||||
|
"uncontrollable": "^4.1.0",
|
||||||
|
"warning": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"version": "16.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.4.2.tgz",
|
||||||
|
"integrity": "sha512-Usl73nQqzvmJN+89r97zmeUpQDKDlh58eX6Hbs/ERdDHzeBzWy+ENk7fsGQ+5KxArV1iOFPT46/VneklK9zoWw==",
|
||||||
|
"requires": {
|
||||||
|
"fbjs": "^0.8.16",
|
||||||
|
"loose-envify": "^1.1.0",
|
||||||
|
"object-assign": "^4.1.1",
|
||||||
|
"prop-types": "^15.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-is": {
|
||||||
|
"version": "16.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.4.2.tgz",
|
||||||
|
"integrity": "sha512-rI3cGFj/obHbBz156PvErrS5xc6f1eWyTwyV4mo0vF2lGgXgS+mm7EKD5buLJq6jNgIagQescGSVG2YzgXt8Yg=="
|
||||||
|
},
|
||||||
|
"react-lifecycles-compat": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||||
|
},
|
||||||
|
"react-overlays": {
|
||||||
|
"version": "0.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.8.3.tgz",
|
||||||
|
"integrity": "sha512-h6GT3jgy90PgctleP39Yu3eK1v9vaJAW73GOA/UbN9dJ7aAN4BTZD6793eI1D5U+ukMk17qiqN/wl3diK1Z5LA==",
|
||||||
|
"requires": {
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"dom-helpers": "^3.2.1",
|
||||||
|
"prop-types": "^15.5.10",
|
||||||
|
"prop-types-extra": "^1.0.1",
|
||||||
|
"react-transition-group": "^2.2.0",
|
||||||
|
"warning": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-prop-types": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-prop-types/-/react-prop-types-0.4.0.tgz",
|
||||||
|
"integrity": "sha1-+ZsL+0AGkpya8gUefBQUpcdbk9A=",
|
||||||
|
"requires": {
|
||||||
|
"warning": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-transition-group": {
|
||||||
|
"version": "2.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.4.0.tgz",
|
||||||
|
"integrity": "sha512-Xv5d55NkJUxUzLCImGSanK8Cl/30sgpOEMGc5m86t8+kZwrPxPCPcFqyx83kkr+5Lz5gs6djuvE5By+gce+VjA==",
|
||||||
|
"requires": {
|
||||||
|
"dom-helpers": "^3.3.1",
|
||||||
|
"loose-envify": "^1.3.1",
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||||
|
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||||
|
},
|
||||||
|
"safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
|
},
|
||||||
|
"setimmediate": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||||
|
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
|
||||||
|
},
|
||||||
|
"ua-parser-js": {
|
||||||
|
"version": "0.7.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz",
|
||||||
|
"integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA=="
|
||||||
|
},
|
||||||
|
"uncontrollable": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-4.1.0.tgz",
|
||||||
|
"integrity": "sha1-4DWCkSUuGGUiLZCTmxny9J+Bwak=",
|
||||||
|
"requires": {
|
||||||
|
"invariant": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"whatwg-fetch": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"name": "app_name",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"main": "Gruntfile.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"homepage": "",
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^16.3.2",
|
||||||
|
"react-bootstrap": "0.32.1",
|
||||||
|
"react-dom": "^16.3.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*global contract, config, it, assert*/
|
||||||
|
const SimpleStorage = require('Embark/contracts/SimpleStorage');
|
||||||
|
|
||||||
|
let accounts;
|
||||||
|
|
||||||
|
// For documentation please see https://embark.status.im/docs/contracts_testing.html
|
||||||
|
config({
|
||||||
|
//deployment: {
|
||||||
|
// accounts: [
|
||||||
|
// // you can configure custom accounts with a custom balance
|
||||||
|
// // see https://embark.status.im/docs/contracts_testing.html#Configuring-accounts
|
||||||
|
// ]
|
||||||
|
//},
|
||||||
|
contracts: {
|
||||||
|
"SimpleStorage": {
|
||||||
|
args: [100]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, (_err, web3_accounts) => {
|
||||||
|
accounts = web3_accounts
|
||||||
|
});
|
||||||
|
|
||||||
|
contract("SimpleStorage", function () {
|
||||||
|
this.timeout(0);
|
||||||
|
|
||||||
|
it("should set constructor value", async function () {
|
||||||
|
let result = await SimpleStorage.methods.storedData().call();
|
||||||
|
assert.strictEqual(parseInt(result, 10), 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("set storage value", async function () {
|
||||||
|
await SimpleStorage.methods.set(150).send();
|
||||||
|
let result = await SimpleStorage.methods.get().call();
|
||||||
|
assert.strictEqual(parseInt(result, 10), 150);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have account with balance", async function() {
|
||||||
|
let balance = await web3.eth.getBalance(accounts[0]);
|
||||||
|
assert.ok(parseInt(balance, 10) > 0);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,46 +1,22 @@
|
||||||
pragma solidity ^0.4.17;
|
pragma solidity ^0.4.25;
|
||||||
|
|
||||||
import "ownable.sol";
|
contract SimpleStorage {
|
||||||
|
|
||||||
library Assert {
|
|
||||||
event TestEvent(bool passed, string message);
|
|
||||||
|
|
||||||
function triggerEvent(bool passed, string message) internal {
|
|
||||||
emit TestEvent(passed, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contract SimpleStorage is Ownable {
|
|
||||||
uint public storedData;
|
uint public storedData;
|
||||||
address public registar;
|
address owner;
|
||||||
event EventOnSet2(bool passed, string message);
|
|
||||||
|
|
||||||
function() public payable { }
|
|
||||||
|
|
||||||
constructor(uint initialValue) public {
|
constructor(uint initialValue) public {
|
||||||
storedData = initialValue;
|
storedData = initialValue;
|
||||||
|
owner = msg.sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
function set(uint x) public {
|
function set(uint x) public {
|
||||||
storedData = x;
|
storedData = x;
|
||||||
Assert.triggerEvent(true, "hi");
|
require(msg.sender == 0x0);
|
||||||
}
|
storedData = x + 2;
|
||||||
|
|
||||||
function set2(uint x) public onlyOwner {
|
|
||||||
storedData = x;
|
|
||||||
emit EventOnSet2(true, "hi");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function get() public view returns (uint retVal) {
|
function get() public view returns (uint retVal) {
|
||||||
return storedData;
|
return storedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getS() public pure returns (string d) {
|
|
||||||
return "hello";
|
|
||||||
}
|
|
||||||
|
|
||||||
function setRegistar(address x) public {
|
|
||||||
registar = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
pragma solidity ^0.4.25;
|
||||||
|
|
||||||
|
import "ownable.sol";
|
||||||
|
|
||||||
|
contract SimpleStorageTest is Ownable {
|
||||||
|
uint public storedData;
|
||||||
|
address owner;
|
||||||
|
|
||||||
|
constructor(uint initialValue) public {
|
||||||
|
storedData = initialValue;
|
||||||
|
owner = msg.sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set(uint x) public onlyOwner {
|
||||||
|
storedData = x;
|
||||||
|
require(msg.sender != owner);
|
||||||
|
storedData = x + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test(uint x) public {
|
||||||
|
uint value = 1;
|
||||||
|
assembly {
|
||||||
|
let a := 1
|
||||||
|
let b := 2
|
||||||
|
revert(0, 0)
|
||||||
|
}
|
||||||
|
value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get() public view returns (uint retVal) {
|
||||||
|
return storedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,7 +4,10 @@ import React, { Component } from 'react';
|
||||||
import EmbarkJS from 'Embark/EmbarkJS';
|
import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
import SimpleStorage from 'Embark/contracts/SimpleStorage';
|
import SimpleStorage from 'Embark/contracts/SimpleStorage';
|
||||||
import Test from 'Embark/contracts/Test';
|
import Test from 'Embark/contracts/Test';
|
||||||
import Assert from 'Embark/contracts/Assert';
|
//import Assert from 'Embark/contracts/Assert';
|
||||||
|
|
||||||
|
import SimpleStorageTest from 'Embark/contracts/SimpleStorageTest';
|
||||||
|
window.SimpleStorageTest = SimpleStorageTest
|
||||||
|
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
|
@ -23,7 +26,7 @@ import { Navbar, Jumbotron, Button } from 'react-bootstrap';
|
||||||
window.EmbarkJS = EmbarkJS;
|
window.EmbarkJS = EmbarkJS;
|
||||||
window.SimpleStorage = SimpleStorage;
|
window.SimpleStorage = SimpleStorage;
|
||||||
window.Test = Test;
|
window.Test = Test;
|
||||||
window.Assert = Assert;
|
//window.Assert = Assert;
|
||||||
|
|
||||||
window.React = React;
|
window.React = React;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,13 @@ module.exports = {
|
||||||
deployment: {
|
deployment: {
|
||||||
host: "localhost",
|
host: "localhost",
|
||||||
port: 8546,
|
port: 8546,
|
||||||
type: "ws"
|
type: "ws",
|
||||||
|
accounts: [
|
||||||
|
{
|
||||||
|
mnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm",
|
||||||
|
balance: "5 ether"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
dappConnection: [
|
dappConnection: [
|
||||||
"ws://localhost:8546",
|
"ws://localhost:8546",
|
||||||
|
@ -17,6 +23,9 @@ module.exports = {
|
||||||
Ownable: {
|
Ownable: {
|
||||||
deploy: false
|
deploy: false
|
||||||
},
|
},
|
||||||
|
SimpleStorageTest: {
|
||||||
|
args: [100]
|
||||||
|
},
|
||||||
SimpleStorage: {
|
SimpleStorage: {
|
||||||
fromIndex: 0,
|
fromIndex: 0,
|
||||||
args: [100],
|
args: [100],
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
"buildDir": "dist/",
|
"buildDir": "dist/",
|
||||||
"config": "config/",
|
"config": "config/",
|
||||||
"versions": {
|
"versions": {
|
||||||
"solc": "0.4.24",
|
"solc": "0.4.25",
|
||||||
"web3": "1.0.0-beta",
|
"web3": "1.0.0-beta",
|
||||||
"ipfs-api": "17.2.7"
|
"ipfs-api": "17.2.7"
|
||||||
},
|
},
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue