feat(scaffold): use ipfs in scaffold and upload file

This commit is contained in:
Anthony Laibe 2018-12-06 13:45:22 +00:00 committed by Iuri Matias
parent 168d774551
commit 9854368c24
2 changed files with 134 additions and 10 deletions

View File

@ -1,5 +1,6 @@
import Handlebars from "handlebars";
import * as path from "path";
import { ABIDefinition } from "web3/types";
import { Contract } from "../../../../../typings/contract";
import { Embark } from "../../../../../typings/embark";
@ -11,6 +12,12 @@ const fs = require("../../../../core/fs");
const utils = require("../../../../utils/utils");
require("../../handlebarHelpers");
interface ABIDefinitionDecorated extends ABIDefinition {
isIpfsText?: boolean;
isIpfsFile?: boolean;
isStandard?: boolean;
}
const indexTemplatePath = path.join(__dirname, "templates", "index.html.hbs");
const dappTemplatePath = path.join(__dirname, "templates", "dapp.js.hbs");
@ -64,12 +71,48 @@ export class ReactBuilder implements Builder {
const dappData = {
contractName,
functions: contract.abiDefinition.filter((entry) => entry.type === "function"),
functions: this.getFunctions(contract),
};
return [indexTemplate(indexData), dappTemplate(dappData)];
}
private getFunctions(contract: Contract) {
const ipfsAttributes = this.description.ipfsAttributes(contract.className);
return contract.abiDefinition.filter((entry) => entry.type === "function").map((entry) => {
const decorated: ABIDefinitionDecorated = entry;
const inputName = entry.inputs && entry.inputs.length > 1 ? entry.inputs[1].name.substring(1, entry.inputs[1].name.length) : "";
const functionName = entry.name || "";
Object.keys(ipfsAttributes).forEach((name) => {
let text = false;
if (ipfsAttributes[name] === "ipfsText") {
text = true;
}
let ipfs = false;
if (name === inputName || `get${name.charAt(0).toUpperCase() + name.slice(1)}` === functionName) {
ipfs = true;
}
if (ipfs) {
if (text) {
decorated.isIpfsText = true;
} else {
decorated.isIpfsFile = true;
}
}
});
if (!decorated.isIpfsText && !decorated.isIpfsFile) {
decorated.isStandard = true;
}
return decorated;
});
}
private installDependencies() {
const cmd = "npm install react react-bootstrap react-dom";
return new Promise<void>((resolve, reject) => {

View File

@ -32,13 +32,19 @@ class {{capitalize name}}Form{{@index}} extends Component {
};
}
handleChange(e, name){
handleChangeFile(e) {
const {input} = this.state;
input.file = [e.target];
this.setState({input});
}
handleChange(e, name) {
const {input} = this.state;
input[name] = e.target.value;
this.setState({input});
}
handleCheckbox(e, name){
handleCheckbox(e, name) {
const {input} = this.state;
input[name] = e.target.checked;
this.setState({input});
@ -52,6 +58,7 @@ class {{capitalize name}}Form{{@index}} extends Component {
this.setState({output: null, error: null, receipt: null});
try {
{{#if isStandard}}
{{#ifview stateMutability}}
const result = await {{../contractName}}.methods{{methodname ../functions name inputs}}({{#each inputs}}input.{{#ifeq name ''}}field{{else}}{{trim name}}{{/ifeq}}{{#unless @last}}, {{/unless}}{{/each}}).call();
{{#iflengthgt outputs 1}}
@ -59,10 +66,10 @@ class {{capitalize name}}Form{{@index}} extends Component {
{{#each outputs}}
{{emptyname name @index}}: result[{{@index}}]{{#unless @last}},{{/unless}}
{{/each}}
}});
}});
{{else}}
this.setState({output: result});
{{/iflengthgt}}
this.setState({output: result});
{{/iflengthgt}}
{{else}}
{{#each inputs}}
{{#ifarr type}}
@ -73,7 +80,7 @@ class {{capitalize name}}Form{{@index}} extends Component {
const toSend = {{../contractName}}.methods{{methodname ../functions name inputs}}({{#each inputs}}input.{{#ifeq name ''}}field{{else}}{{trim name}}{{/ifeq}}{{#unless @last}}, {{/unless}}{{/each}});
const estimatedGas = await toSend.estimateGas({from: web3.eth.defaultAccount});
const receipt = await toSend.send({
{{#if payable}}
value: value,
@ -86,6 +93,51 @@ class {{capitalize name}}Form{{@index}} extends Component {
this.setState({receipt});
{{/ifview}}
{{/if}}
{{#if isIpfsText}}
{{#ifview stateMutability}}
const result = await {{../contractName}}.methods{{methodname ../functions name inputs}}({{#each inputs}}input.{{#ifeq name ''}}field{{else}}{{trim name}}{{/ifeq}}{{#unless @last}}, {{/unless}}{{/each}}).call();
const data = await EmbarkJS.Storage.get(result);
this.setState({output: data});
{{else}}
const hash = await EmbarkJS.Storage.saveText(input.{{inputs.1.name}});
const toSend = {{../contractName}}.methods{{methodname ../functions name inputs}}(input.{{inputs.0.name}}, hash);
const estimatedGas = await toSend.estimateGas({from: web3.eth.defaultAccount});
const receipt = await toSend.send({
from: web3.eth.defaultAccount,
gasLimit: estimatedGas
});
console.log(receipt);
this.setState({receipt});
{{/ifview}}
{{/if}}
{{#if isIpfsFile}}
{{#ifview stateMutability}}
const result = await {{../contractName}}.methods{{methodname ../functions name inputs}}({{#each inputs}}input.{{#ifeq name ''}}field{{else}}{{trim name}}{{/ifeq}}{{#unless @last}}, {{/unless}}{{/each}}).call();
const url = EmbarkJS.Storage.getUrl(result);
this.setState({output: url});
{{else}}
const hash = await EmbarkJS.Storage.uploadFile(input.file)
const toSend = {{../contractName}}.methods{{methodname ../functions name inputs}}(input._id, hash);
const estimatedGas = await toSend.estimateGas({from: web3.eth.defaultAccount});
const receipt = await toSend.send({
from: web3.eth.defaultAccount,
gasLimit: estimatedGas
});
console.log(receipt);
this.setState({receipt});
{{/ifview}}
{{/if}}
} catch(err) {
console.error(err);
this.setState({error: err.message});
@ -99,6 +151,34 @@ class {{capitalize name}}Form{{@index}} extends Component {
<h3>{{name}}</h3>
<form>
{{#if inputs.length}}
{{#if isIpfsFile}}
{{#ifview stateMutability}}
<FormGroup>
<ControlLabel>_id</ControlLabel>
<FormControl
type="text"
placeholder="uint256"
onChange={(e) => this.handleChange(e, '_id')}
/>
</FormGroup>
{{else}}
<FormGroup>
<ControlLabel>_id</ControlLabel>
<FormControl
type="text"
placeholder="uint256"
onChange={(e) => this.handleChange(e, '_id')}
/>
</FormGroup>
<FormGroup>
<ControlLabel>File</ControlLabel>
<FormControl
type="file"
onChange={(e) => this.handleChangeFile(e)}
/>
</FormGroup>
{{/ifview}}
{{else}}
{{#each inputs}}
<FormGroup>
<ControlLabel>{{#ifeq name ''}}field{{else}}{{name}}{{/ifeq}}</ControlLabel>
@ -115,14 +195,15 @@ class {{capitalize name}}Form{{@index}} extends Component {
/>
{{/ifeq}}
</FormGroup>
{{/each}}
{{/each}}
{{/if}}
{{/if}}
{{#if payable}}
<FormGroup>
<ControlLabel>Value</ControlLabel>
<InputGroup>
<InputGroup.Addon>Ξ</InputGroup.Addon>
<FormControl
<FormControl
type="text"
defaultValue={ value }
placeholder="{{type}}"
@ -159,7 +240,7 @@ class {{capitalize name}}Form{{@index}} extends Component {
<Fragment>
<Alert bsStyle={isSuccess(receipt.status) ? 'success' : 'danger'}>{isSuccess(receipt.status) ? 'Success' : 'Failure / Revert'} - Transaction Hash: {receipt.transactionHash}</Alert>
</Fragment>
}
{{/ifview}}
</form>