mirror of https://github.com/embarklabs/embark.git
feat(scaffold): use ipfs in scaffold and upload file
This commit is contained in:
parent
168d774551
commit
9854368c24
|
@ -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) => {
|
||||
|
|
|
@ -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}}
|
||||
|
@ -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>
|
||||
|
@ -117,6 +197,7 @@ class {{capitalize name}}Form{{@index}} extends Component {
|
|||
</FormGroup>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if payable}}
|
||||
<FormGroup>
|
||||
<ControlLabel>Value</ControlLabel>
|
||||
|
|
Loading…
Reference in New Issue