fix: react - pt2. (#28)
This commit is contained in:
parent
6cf911741b
commit
f4781943ec
|
@ -0,0 +1,6 @@
|
||||||
|
node_modules/
|
||||||
|
.vscode/
|
||||||
|
phoenix.db
|
||||||
|
examples/
|
||||||
|
test/
|
||||||
|
.editorconfig
|
|
@ -1,11 +1,34 @@
|
||||||
#
|
phoenix - react example
|
||||||
```
|
===
|
||||||
In the parent folder:
|
Simple application using a react observable component to receive a stream of emitted events. This app will deploy a test contract to **Ganache**.
|
||||||
yarn link
|
|
||||||
|
|
||||||
In the current folder:
|
## Requirements
|
||||||
|
- `ganache-cli`
|
||||||
|
- `yarn` or `npm` installed.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
In the parent folder, link the package with `yarn` or `npm`
|
||||||
|
```
|
||||||
|
yarn link
|
||||||
|
```
|
||||||
|
Then in the current folder link `phoenix`, and install the packages
|
||||||
|
```
|
||||||
yarn link phoenix
|
yarn link phoenix
|
||||||
yarn
|
yarn
|
||||||
ganache-cli
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
In a terminal execute
|
||||||
|
```
|
||||||
|
ganache-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
In a different session, execute
|
||||||
|
```
|
||||||
yarn run start
|
yarn run start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Browse the DApp in [http://localhost:3000](http://localhost:3000)
|
||||||
|
|
||||||
|
|
||||||
|
*Note*: this is a simple example application that does not include error handling for the web3 connection. Be sure `ganache-cli` is running in `localhost:8545` before browsing the dapp.
|
|
@ -1,138 +1,50 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Phoenix from "phoenix";
|
import Phoenix from "phoenix";
|
||||||
import Web3 from "web3";
|
import { web3, MyContract, onWeb3Available } from "./ethService";
|
||||||
|
import { scan } from 'rxjs/operators';
|
||||||
|
|
||||||
import MyComponentObserver from "./MyComponentObserver";
|
import MyComponentObserver from "./MyComponentObserver";
|
||||||
|
|
||||||
const web3 = new Web3("ws://localhost:8545");
|
let MyContractInstance;
|
||||||
|
|
||||||
class App extends React.Component {
|
class App extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
escrowObservable: null
|
myEventObservable$: null
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.EscrowContract = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
(async () => {
|
// Verify if web3 connection is available
|
||||||
let accounts = await web3.eth.getAccounts();
|
onWeb3Available(async () => {
|
||||||
this.EscrowContract = await deployContract();
|
MyContractInstance = await MyContract.deploy().send({ from: web3.eth.defaultAccount });
|
||||||
|
|
||||||
await this.EscrowContract.methods.createEscrow(1, accounts[0], accounts[1]).send({ from: accounts[0] });
|
|
||||||
await this.EscrowContract.methods.createEscrow(1, accounts[1], accounts[2]).send({ from: accounts[0] });
|
|
||||||
await this.EscrowContract.methods.createEscrow(1, accounts[1], accounts[0]).send({ from: accounts[0] });
|
|
||||||
await this.EscrowContract.methods.createEscrow(1, accounts[0], accounts[2]).send({ from: accounts[0] });
|
|
||||||
|
|
||||||
const eventSyncer = new Phoenix(web3.currentProvider);
|
const eventSyncer = new Phoenix(web3.currentProvider);
|
||||||
await eventSyncer.init();
|
eventSyncer.init().then(() => {
|
||||||
|
const myEventObservable$ = eventSyncer.trackEvent(MyContractInstance, "MyEvent", {filter: {}, fromBlock: 1 });
|
||||||
|
|
||||||
this.setState({
|
// If you want to return all the events in an array, you can pipe the scan operator to the observable
|
||||||
escrowObservable: eventSyncer.trackEvent(this.EscrowContract, "Created", { filter: { buyer: accounts[0] }, fromBlock: 1 })
|
// const myEventObservable$ = eventSyncer.trackEvent(MyContractInstance, "MyEvent", {filter: {}, fromBlock: 1 })
|
||||||
|
// .pipe(scan((accum, val) => [...accum, val], []));
|
||||||
|
// Your observable component would receive the eventData as an array instead of an object
|
||||||
|
|
||||||
|
this.setState({ myEventObservable$ });
|
||||||
});
|
});
|
||||||
|
});
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createTrx = async () => {
|
createTrx = () => {
|
||||||
let accounts = await web3.eth.getAccounts();
|
MyContractInstance.methods
|
||||||
await this.EscrowContract.methods
|
.myFunction()
|
||||||
.createEscrow(Date.now(), accounts[0], accounts[1])
|
.send({ from: web3.eth.defaultAccount });
|
||||||
.send({ from: accounts[0] });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {escrowObservable} = this.state;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<button onClick={this.createTrx}>Create Trx</button>
|
<button onClick={this.createTrx}>Create a Transaction</button>
|
||||||
<MyComponentObserver escrow={escrowObservable} myCustomProperty="Test" />
|
<MyComponentObserver eventData={this.state.myEventObservable$} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function deployContract() {
|
|
||||||
let accounts = await web3.eth.getAccounts();
|
|
||||||
|
|
||||||
// pragma solidity >=0.4.22 <0.6.0;
|
|
||||||
// contract Escrow {
|
|
||||||
// event Created(uint indexed escrowId, address buyer, address seller);
|
|
||||||
// function createEscrow(uint escrowId, address buyer, address seller) external {
|
|
||||||
// emit Created(escrowId, buyer, seller);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
let abi = [
|
|
||||||
{
|
|
||||||
"constant": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "escrowId",
|
|
||||||
"type": "uint256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "buyer",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "seller",
|
|
||||||
"type": "address"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "createEscrow",
|
|
||||||
"outputs": [],
|
|
||||||
"payable": false,
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"anonymous": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"indexed": true,
|
|
||||||
"name": "escrowId",
|
|
||||||
"type": "uint256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"indexed": false,
|
|
||||||
"name": "buyer",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"indexed": false,
|
|
||||||
"name": "seller",
|
|
||||||
"type": "address"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "Created",
|
|
||||||
"type": "event"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
var contract = new web3.eth.Contract(abi)
|
|
||||||
let instance = await contract.deploy({
|
|
||||||
data: '0x608060405234801561001057600080fd5b50610184806100206000396000f3fe60806040526004361061003b576000357c01000000000000000000000000000000000000000000000000000000009004806378015cf414610040575b600080fd5b34801561004c57600080fd5b506100b96004803603606081101561006357600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506100bb565b005b827fcbd6f84bfed2ee8cc01ea152b5d9f7126a72c410dbc5ab04c486a5800627b1908383604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a250505056fea165627a7a72305820cc868ec126578f5508ee248fb823cd9f1ac6deb0562091cdf31843840b2a56410029',
|
|
||||||
arguments: []
|
|
||||||
}).send({
|
|
||||||
from: accounts[0],
|
|
||||||
gas: '4700000'
|
|
||||||
})
|
|
||||||
return instance
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {observe} from "phoenix/react";
|
import { observe } from "phoenix/react";
|
||||||
|
|
||||||
const MyComponent = props => {
|
const MyComponent = ({ eventData }) => {
|
||||||
const { escrow, myCustomProperty } = props;
|
// Handle initial state when no data is available
|
||||||
if(!escrow) return <p>Loading...</p>;
|
if (!eventData) {
|
||||||
return (
|
return <p>No data</p>;
|
||||||
<ul>
|
}
|
||||||
<li>
|
|
||||||
{escrow.buyer} {escrow.seller} - <b>EscrowID:{escrow.escrowId}</b>{" "}
|
console.log("Data received", eventData);
|
||||||
<small>{myCustomProperty}</small>
|
|
||||||
</li>
|
return <ul>
|
||||||
</ul>
|
<li><b>someValue: </b> {eventData.someValue}</li>
|
||||||
);
|
<li><b>anotherValue: </b> {eventData.anotherValue}</li>
|
||||||
|
</ul>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// MyComponent will now observe any observable prop it receives
|
||||||
|
// and update its state whenever the observable emits an event
|
||||||
export default observe(MyComponent);
|
export default observe(MyComponent);
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
import Web3 from 'web3';
|
||||||
|
|
||||||
|
export const web3 = new Web3("ws://localhost:8545");
|
||||||
|
|
||||||
|
let web3AvailableCB;
|
||||||
|
export const onWeb3Available = (cb) => {
|
||||||
|
web3AvailableCB = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
web3.eth.getAccounts().then(async accounts => {
|
||||||
|
web3.eth.defaultAccount = accounts[0];
|
||||||
|
if(web3AvailableCB){
|
||||||
|
web3AvailableCB();
|
||||||
|
}
|
||||||
|
/*SimpleStorageContract.deploy().send({ from: web3.eth.defaultAccount }).then(instance => {
|
||||||
|
SimpleStorage = instance;
|
||||||
|
});*/
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// pragma solidity ^0.5.0;
|
||||||
|
//
|
||||||
|
// contract MyContract {
|
||||||
|
// event MyEvent(uint someValue, bytes32 anotherValue);
|
||||||
|
//
|
||||||
|
// function myFunction() public {
|
||||||
|
// uint a = block.timestamp * block.number; // Just to have a pseudo random value
|
||||||
|
// bytes32 b = keccak256(abi.encodePacked(a));
|
||||||
|
//
|
||||||
|
// emit MyEvent(a, b);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
const abi = [
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "myFunction",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "someValue",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "anotherValue",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "MyEvent",
|
||||||
|
"type": "event"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const data = "0x6080604052348015600f57600080fd5b5060f38061001e6000396000f3fe6080604052600436106039576000357c010000000000000000000000000000000000000000000000000000000090048063c3780a3a14603e575b600080fd5b348015604957600080fd5b5060506052565b005b60004342029050600081604051602001808281526020019150506040516020818303038152906040528051906020012090507fc3d6130248b5b68a864c047b2f68d895d420924130388d02d64b648005fe9ac78282604051808381526020018281526020019250505060405180910390a1505056fea165627a7a72305820613e35c5d1e8684ef5b31a7d993a139f1b5bbb409039d92db0fe78ed571d2ce20029";
|
||||||
|
|
||||||
|
export const MyContract = new web3.eth.Contract(abi, {data, gas: "470000"});
|
Loading…
Reference in New Issue