Tabula Rasa
This commit is contained in:
parent
ddec5b3b76
commit
94a63ab4f9
Binary file not shown.
After Width: | Height: | Size: 7.8 KiB |
|
@ -1,7 +1,5 @@
|
|||
import EmbarkJS from 'Embark/EmbarkJS';
|
||||
import React, { Fragment, Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import SpaceshipToken from 'Embark/contracts/SpaceshipToken';
|
||||
import { Form, FormGroup, FormControl, InputGroup, Button, Grid, Row, Col, ControlLabel} from 'react-bootstrap';
|
||||
import Spinner from 'react-spinkit';
|
||||
|
||||
|
@ -29,74 +27,14 @@ class AddToken extends Component {
|
|||
handleClick(e){
|
||||
e.preventDefault();
|
||||
|
||||
const { mint } = SpaceshipToken.methods;
|
||||
|
||||
this.setState({isSubmitting: true});
|
||||
|
||||
let attributes = {
|
||||
"name": "Nave Espacial",
|
||||
"image": "",
|
||||
"attributes": {
|
||||
"energy": this.state.energy,
|
||||
"lasers": this.state.lasers,
|
||||
"shield": this.state.shield
|
||||
}
|
||||
}
|
||||
|
||||
let toSend;
|
||||
|
||||
// Cargamos la imagen a IPFS
|
||||
EmbarkJS.Storage.uploadFile(this.state.fileToUpload)
|
||||
.then(fileHash => {
|
||||
// Agregamos los datos a la lista de atributos
|
||||
attributes.imageHash = fileHash;
|
||||
attributes.image = 'https://ipfs.io/ipfs/' + fileHash;
|
||||
|
||||
// Guardamos la lista de atributos
|
||||
return EmbarkJS.Storage.saveText(JSON.stringify(attributes))
|
||||
})
|
||||
.then(attrHash => {
|
||||
|
||||
// El hash que retorna IPFS se almacenara dentro de los datos del token
|
||||
// El precio lo convertimos de ether a wei
|
||||
toSend = mint(web3.utils.toHex(attrHash),
|
||||
this.state.energy,
|
||||
this.state.lasers,
|
||||
this.state.shield,
|
||||
web3.utils.toWei(this.state.price, "ether"));
|
||||
|
||||
return toSend.estimateGas();
|
||||
})
|
||||
.then(estimatedGas => {
|
||||
return toSend.send({from: web3.eth.defaultAccount,
|
||||
gas: estimatedGas + 1000});
|
||||
})
|
||||
.then(receipt => {
|
||||
console.log(receipt);
|
||||
|
||||
// Vaciar formulario
|
||||
this.setState({
|
||||
fileToUpload: [],
|
||||
energy: '',
|
||||
lasers: '',
|
||||
shield: '',
|
||||
price: ''
|
||||
});
|
||||
|
||||
this.props.loadShipsForSale();
|
||||
|
||||
// TODO: show success
|
||||
|
||||
return true;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
// TODO: show error blockchain / ipfs
|
||||
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({isSubmitting: false});
|
||||
});
|
||||
// TODO: Implementar llamada al contrato para crear el token
|
||||
// Un token espera los siguientes atributos: energy, lasers, shield and price
|
||||
// al igual que una imagen
|
||||
// La siguiente funcion se puede llamar para actualizar la lista de tokens
|
||||
this.props.loadShipsForSale();
|
||||
this.setState({isSubmitting: false});
|
||||
}
|
||||
|
||||
render(){
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import EmbarkJS from 'Embark/EmbarkJS';
|
||||
import React, { Fragment, Component } from 'react';
|
||||
import Toggle from 'react-toggle'
|
||||
import SpaceshipToken from 'Embark/contracts/SpaceshipToken';
|
||||
import SpaceshipMarketplace from 'Embark/contracts/SpaceshipMarketplace';
|
||||
import ShipList from './shipList.js'
|
||||
|
||||
class MarketPlace extends Component {
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
import React, { Component, Fragment } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import EmbarkJS from 'Embark/EmbarkJS';
|
||||
import web3 from "Embark/web3"
|
||||
import { Button, FormControl, InputGroup } from 'react-bootstrap';
|
||||
import SpaceshipToken from 'Embark/contracts/SpaceshipToken';
|
||||
import SpaceshipMarketplace from 'Embark/contracts/SpaceshipMarketplace';
|
||||
import Spinner from 'react-spinkit';
|
||||
import MarketPlace from './marketplace';
|
||||
|
||||
|
@ -27,25 +23,17 @@ class Ship extends Component {
|
|||
}
|
||||
|
||||
componentDidMount(){
|
||||
EmbarkJS.onReady((err) => {
|
||||
this._loadAttributes();
|
||||
});
|
||||
// TODO: cuando se carga el componente se deben buscar los atributos del token
|
||||
this._loadAttributes();
|
||||
}
|
||||
|
||||
_loadAttributes(){
|
||||
// Cargar los atributos involucra leer la metadata
|
||||
EmbarkJS.Storage.get(web3.utils.toAscii(this.props.metadataHash))
|
||||
.then(content => {
|
||||
const jsonMetadata = JSON.parse(content);
|
||||
|
||||
// Podemos usar este metodo
|
||||
const _url = EmbarkJS.Storage.getUrl(jsonMetadata.imageHash);
|
||||
|
||||
// o leer el url que grabamos en la metadata
|
||||
// const _url = jsonMetadata.image
|
||||
|
||||
this.setState({image: _url})
|
||||
});
|
||||
// TODO: implementar carga de atributos aca
|
||||
// El unico atributo interesante es la imagen
|
||||
// Guardar el url en this.state.image
|
||||
|
||||
// Ejemplo
|
||||
this.setState({image: "./images/sampleShip.png"});
|
||||
}
|
||||
|
||||
showSellForm = (show) => {
|
||||
|
@ -53,93 +41,34 @@ class Ship extends Component {
|
|||
}
|
||||
|
||||
sellShip = () => {
|
||||
const { forSale } = SpaceshipMarketplace.methods;
|
||||
const { sellPrice } = this.state;
|
||||
const { id } = this.props;
|
||||
|
||||
// TODO: vender una nave para que otro usuario la pueda comprar
|
||||
// En props esta el atributo 'id', que podemos usar para determinar el id del token
|
||||
// El precio esta en el estado this.state.sellPrice
|
||||
|
||||
this.setState({isSubmitting: true});
|
||||
|
||||
const toSend = forSale(id, web3.utils.toWei(sellPrice, 'ether'))
|
||||
|
||||
toSend.estimateGas()
|
||||
.then(estimatedGas => {
|
||||
return toSend.send({from: web3.eth.defaultAccount,
|
||||
gas: estimatedGas + 1000});
|
||||
})
|
||||
.then(receipt => {
|
||||
console.log(receipt);
|
||||
|
||||
this.props.onAction();
|
||||
|
||||
// TODO: show success
|
||||
return true;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
// TODO: show error blockchain
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({isSubmitting: false});
|
||||
});
|
||||
// Llamar la siguiente funcion para refrescar las listas
|
||||
this.props.onAction();
|
||||
this.setState({isSubmitting: false});
|
||||
}
|
||||
|
||||
buyFromStore = () => {
|
||||
const { buySpaceship } = SpaceshipToken.methods;
|
||||
const toSend = buySpaceship(this.props.id)
|
||||
// TODO: comprar token recien creado
|
||||
// En props esta el atributo 'id' y 'price', que podemos usar para determinar el id del token
|
||||
|
||||
this.setState({isSubmitting: true});
|
||||
|
||||
toSend.estimateGas({value: this.props.price })
|
||||
.then(estimatedGas => {
|
||||
return toSend.send({from: web3.eth.defaultAccount,
|
||||
value: this.props.price,
|
||||
gas: estimatedGas + 1000000});
|
||||
})
|
||||
.then(receipt => {
|
||||
console.log(receipt);
|
||||
|
||||
console.log("Updating ships");
|
||||
this.props.onAction();
|
||||
|
||||
// TODO: show success
|
||||
return true;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
// TODO: show error blockchain
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({isSubmitting: false});
|
||||
});
|
||||
// Llamar la siguiente funcion para refrescar las listas
|
||||
this.props.onAction();
|
||||
this.setState({isSubmitting: false});
|
||||
}
|
||||
|
||||
buyFromMarket = () => {
|
||||
const { buy } = SpaceshipMarketplace.methods;
|
||||
const toSend = buy(this.props.saleId);
|
||||
|
||||
// TODO: comprar tokens puestos a la venta por otra persona
|
||||
// En props esta el 'saleId' y 'price' para poder comprarlo
|
||||
|
||||
this.setState({isSubmitting: true});
|
||||
|
||||
toSend.estimateGas({value: this.props.price })
|
||||
.then(estimatedGas => {
|
||||
return toSend.send({from: web3.eth.defaultAccount,
|
||||
value: this.props.price,
|
||||
gas: estimatedGas + 1000000});
|
||||
})
|
||||
.then(receipt => {
|
||||
console.log(receipt);
|
||||
|
||||
this.props.onAction();
|
||||
|
||||
// TODO: show success
|
||||
return true;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
// TODO: show error blockchain
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({isSubmitting: false});
|
||||
});
|
||||
// Llamar la siguiente funcion para refrescar las listas
|
||||
this.props.onAction();
|
||||
this.setState({isSubmitting: false});
|
||||
}
|
||||
|
||||
render(){
|
||||
|
@ -164,7 +93,7 @@ class Ship extends Component {
|
|||
: '')
|
||||
}
|
||||
|
||||
{ showSellForm
|
||||
{ showSellForm && salesEnabled
|
||||
? <Fragment>
|
||||
<InputGroup>
|
||||
<FormControl
|
||||
|
|
|
@ -17,41 +17,20 @@ class ShipList extends Component {
|
|||
}
|
||||
|
||||
componentDidMount(){
|
||||
EmbarkJS.onReady((err) => {
|
||||
// Al cargar la lista de naves, determinamos si estan aprobadas para la venta
|
||||
const { isApprovedForAll } = SpaceshipToken.methods;
|
||||
isApprovedForAll(web3.eth.defaultAccount, SpaceshipMarketplace.options.address)
|
||||
.call()
|
||||
.then(isApproved => {
|
||||
this.setState({salesEnabled: isApproved});
|
||||
});
|
||||
});
|
||||
// TODO: nos interesa saber si las ventas estan habilidatas o no para los tokens
|
||||
// El estado que maneja esto es 'salesEnabled'.
|
||||
// Aqui lo seteamos en true, solo para ver que funcione, pero debe venir del contrato
|
||||
this.setState({salesEnabled: false});
|
||||
}
|
||||
|
||||
enableMarketplace = () => {
|
||||
const { setApprovalForAll } = SpaceshipToken.methods;
|
||||
|
||||
// TODO: esta funcion la llama el toggle de mas abajo cuando se clickea
|
||||
// Debe setear siempre el valor de 'salesEnabled'
|
||||
// Las siguientes lineas solo muestran el funcionamiento en el UI
|
||||
// pero debe implementarse creando una transaccion
|
||||
this.setState({isSubmitting: true});
|
||||
|
||||
const toSend = setApprovalForAll(SpaceshipMarketplace.options.address, !this.state.salesEnabled);
|
||||
|
||||
toSend.estimateGas()
|
||||
.then(estimatedGas => {
|
||||
return toSend.send({from: web3.eth.defaultAccount,
|
||||
gas: estimatedGas + 1000});
|
||||
})
|
||||
.then(receipt => {
|
||||
this.setState({salesEnabled: !this.state.salesEnabled});
|
||||
console.log(receipt);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
// TODO: show error blockchain
|
||||
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({isSubmitting: false});
|
||||
});
|
||||
this.setState({salesEnabled: !this.state.salesEnabled});
|
||||
this.setState({isSubmitting: false});
|
||||
}
|
||||
|
||||
render = () => {
|
||||
|
|
|
@ -16,55 +16,25 @@ class WithdrawBalance extends Component {
|
|||
}
|
||||
|
||||
componentDidMount(){
|
||||
EmbarkJS.onReady((err) => {
|
||||
// Al cargar el componente, obtenemos el balance
|
||||
this._getBalance();
|
||||
});
|
||||
// TODO: Al cargar el componente, debemos obtener el balance
|
||||
// podemos hacerlo llamando a this._getBalance();
|
||||
}
|
||||
|
||||
_getBalance(){
|
||||
|
||||
// Se consulta el balance del contrato
|
||||
web3.eth.getBalance(SpaceshipToken.options.address)
|
||||
.then(newBalance => {
|
||||
this.setState({
|
||||
balance: web3.utils.fromWei(newBalance, "ether")
|
||||
});
|
||||
});
|
||||
// TODO: implementar, el estado a actualizar es 'balance'
|
||||
|
||||
}
|
||||
|
||||
handleClick(e){
|
||||
const { withdrawBalance } = SpaceshipToken.methods;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// TODO: este metodo se debe llamar al hacer click en retirar fondos
|
||||
// Debe extraer el balance total del contrato del token, y actualizar el UI
|
||||
// para mostrar que no hay balance disponible
|
||||
|
||||
this.setState({isSubmitting: true});
|
||||
|
||||
// Retiramos el balance total del contrato
|
||||
// Estimamos primero el gas para saber cuanto gas enviar
|
||||
|
||||
const toSend = withdrawBalance();
|
||||
toSend.estimateGas()
|
||||
.then(estimatedGas => {
|
||||
// Es una buena practica mandar siempre algo mas del gas estimado
|
||||
return toSend.send({from: web3.eth.defaultAccount,
|
||||
gas: estimatedGas + 1000});
|
||||
})
|
||||
.then(receipt => {
|
||||
console.log(receipt);
|
||||
this._getBalance();
|
||||
// TODO mostrar info
|
||||
|
||||
return true;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
// TODO: mostrar error
|
||||
})
|
||||
.finally(() => {
|
||||
this.setState({isSubmitting: false});
|
||||
});
|
||||
this._getBalance();
|
||||
this.setState({isSubmitting: false});
|
||||
}
|
||||
|
||||
render(){
|
||||
|
|
143
app/js/index.js
143
app/js/index.js
|
@ -1,8 +1,5 @@
|
|||
import EmbarkJS from 'Embark/EmbarkJS';
|
||||
import React, { Fragment, Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import SpaceshipToken from 'Embark/contracts/SpaceshipToken';
|
||||
import SpaceshipMarketplace from 'Embark/contracts/SpaceshipMarketplace';
|
||||
import ShipList from './components/shipList.js';
|
||||
import WithdrawBalance from './components/withdrawBalance.js';
|
||||
import AddToken from './components/addToken.js';
|
||||
|
@ -22,96 +19,84 @@ class App extends Component {
|
|||
}
|
||||
|
||||
componentDidMount(){
|
||||
EmbarkJS.onReady((err) => {
|
||||
this._isOwner();
|
||||
this._loadEverything();
|
||||
});
|
||||
// TODO: Debemos determinar si la cuenta que estamos usando es la del dueno del token
|
||||
// y cargar tambien las naves
|
||||
this._isOwner();
|
||||
this._loadEverything();
|
||||
}
|
||||
|
||||
_loadEverything(){
|
||||
// Cargamos todas las naves que estan a la venta, que estan en mi wallet y en el mercado
|
||||
|
||||
this._loadShipsForSale();
|
||||
this._loadMyShips();
|
||||
this._loadMarketPlace();
|
||||
}
|
||||
|
||||
_isOwner(){
|
||||
// Nos interesa saber si somos el dueno del contrato para mostrar el formulario de tokens
|
||||
SpaceshipToken.methods.owner()
|
||||
.call()
|
||||
.then(owner => {
|
||||
this.setState({isOwner: owner == web3.eth.defaultAccount});
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
_loadMarketPlace = async () => {
|
||||
const { nSale, sales, saleInformation } = SpaceshipMarketplace.methods;
|
||||
const { spaceships } = SpaceshipToken.methods;
|
||||
|
||||
const total = await nSale().call();
|
||||
const list = [];
|
||||
if(total){
|
||||
for (let i = total-1; i >= 0; i--) {
|
||||
const sale = await sales(i).call();
|
||||
const _info = await spaceships(sale.spaceshipId).call();
|
||||
const ship = {
|
||||
owner: sale.owner,
|
||||
price: sale.price,
|
||||
id: sale.spaceshipId,
|
||||
saleId: i,
|
||||
..._info
|
||||
};
|
||||
|
||||
list.push(ship);
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({marketPlaceShips: list.reverse()});
|
||||
}
|
||||
|
||||
_loadShipsForSale = async () => {
|
||||
const { shipsForSaleN, shipsForSale, spaceshipPrices, spaceships } = SpaceshipToken.methods;
|
||||
|
||||
const total = await shipsForSaleN().call();
|
||||
const list = [];
|
||||
if(total){
|
||||
for (let i = total-1; i >= 0; i--) {
|
||||
const shipId = await shipsForSale(i).call();
|
||||
const _info = await spaceships(shipId).call();
|
||||
const _price = await spaceshipPrices(shipId).call();
|
||||
|
||||
const ship = {
|
||||
price: _price,
|
||||
id: shipId,
|
||||
..._info
|
||||
};
|
||||
list.push(ship);
|
||||
}
|
||||
}
|
||||
this.setState({shipsForSale: list.reverse()});
|
||||
// TODO: Nos interesa saber si somos el dueno del contrato para mostrar el formulario de tokens
|
||||
// Debemos actualizar el estado isOwner con la informacion del contrato
|
||||
this.setState({isOwner: true});
|
||||
}
|
||||
|
||||
_loadMyShips = async () => {
|
||||
const { balanceOf, tokenOfOwnerByIndex, spaceships } = SpaceshipToken.methods;
|
||||
|
||||
const total = await balanceOf(web3.eth.defaultAccount).call();
|
||||
const list = [];
|
||||
if(total){
|
||||
for (let i = total-1; i >= 0; i--) {
|
||||
const myShipId = await tokenOfOwnerByIndex(web3.eth.defaultAccount, i).call();
|
||||
const _info = await spaceships(myShipId).call();
|
||||
|
||||
const ship = {
|
||||
id: myShipId,
|
||||
..._info
|
||||
};
|
||||
list.push(ship);
|
||||
}
|
||||
}
|
||||
// TODO: aqui nos interesa cargar la lista de naves que posee el usuario
|
||||
// se espera un array de objetos en el estado myShips
|
||||
// cada objeto debe tener los siguientes atributos:
|
||||
// {
|
||||
// id: "id del token",
|
||||
// energy: "Atributo del token",
|
||||
// lasers: "Atributo del token",
|
||||
// shield: "Atributo del token",
|
||||
// metadataHash: "Atributo del token",
|
||||
// }
|
||||
|
||||
// Ejemplo:
|
||||
const myShip = {
|
||||
id: 1,
|
||||
energy: 10,
|
||||
lasers: 5,
|
||||
shield: 7,
|
||||
metadataHash: "METADATA"
|
||||
};
|
||||
const list = [ myShip ];
|
||||
this.setState({myShips: list.reverse()});
|
||||
}
|
||||
}
|
||||
|
||||
_loadShipsForSale = async () => {
|
||||
// TODO: aqui nos interesa cargar la lista de naves a la venta cuando generamos el token
|
||||
// se espera un array de objetos en el estado shipsForSale
|
||||
// cada objeto debe tener los siguientes atributos:
|
||||
// {
|
||||
// price: "precio de venta",
|
||||
// id: "id del token",
|
||||
// energy: "Atributo del token",
|
||||
// lasers: "Atributo del token",
|
||||
// shield: "Atributo del token",
|
||||
// metadataHash: "Atributo del token",
|
||||
// }
|
||||
|
||||
let list = [];
|
||||
this.setState({shipsForSale: list.reverse()});
|
||||
}
|
||||
|
||||
_loadMarketPlace = async () => {
|
||||
// TODO: debemos cargar la lista de naves que estan a la venta en el marketplace
|
||||
// se espera un array de objetos en el estado marketPlaceShips
|
||||
// cada objeto debe tener los siguientes atributos:
|
||||
// {
|
||||
// owner: "dueno de la nave en venta",
|
||||
// price: "precio de venta",
|
||||
// id: "id del token",
|
||||
// saleId: "id de la venta",
|
||||
// energy: "Atributo del token",
|
||||
// lasers: "Atributo del token",
|
||||
// shield: "Atributo del token",
|
||||
// metadataHash: "Atributo del token",
|
||||
// }
|
||||
|
||||
let list = [];
|
||||
this.setState({marketPlaceShips: list.reverse()});
|
||||
}
|
||||
|
||||
render(){
|
||||
const { isOwner, hidePanel, shipsForSale, myShips, marketPlaceShips } = this.state;
|
||||
|
|
Loading…
Reference in New Issue