2019-07-24 17:10:44 +00:00
|
|
|
import React from 'react';
|
2019-07-24 18:42:02 +00:00
|
|
|
import Cristal from 'react-cristal'
|
2019-07-25 17:06:10 +00:00
|
|
|
import { BlockLinks } from "./BlockLink";
|
2019-07-30 23:18:21 +00:00
|
|
|
import StorageNodeInit from "./StorageNodeInit";
|
2019-08-10 01:54:45 +00:00
|
|
|
import Address from "./Address";
|
2019-08-16 02:34:11 +00:00
|
|
|
import ChainExplorer from "./ChainExplorer";
|
2019-09-06 17:42:31 +00:00
|
|
|
import Client from "./Client";
|
2019-07-25 14:57:30 +00:00
|
|
|
|
2019-07-24 17:10:44 +00:00
|
|
|
class FullNode extends React.Component {
|
|
|
|
constructor(props) {
|
|
|
|
super(props)
|
|
|
|
|
2019-08-21 15:14:38 +00:00
|
|
|
this.state = {}
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-07-24 22:30:17 +00:00
|
|
|
this.loadInfo = this.loadInfo.bind(this)
|
2019-08-21 22:47:44 +00:00
|
|
|
this.newSecpAddr = this.newSecpAddr.bind(this)
|
|
|
|
this.newBLSAddr = this.newBLSAddr.bind(this)
|
2019-07-30 23:18:21 +00:00
|
|
|
this.startStorageMiner = this.startStorageMiner.bind(this)
|
2019-08-09 15:59:12 +00:00
|
|
|
this.add1k = this.add1k.bind(this)
|
2019-08-16 02:34:11 +00:00
|
|
|
this.explorer = this.explorer.bind(this)
|
2019-09-06 17:42:31 +00:00
|
|
|
this.client = this.client.bind(this)
|
2019-09-17 12:03:28 +00:00
|
|
|
this.stop = this.stop.bind(this)
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-09 15:59:12 +00:00
|
|
|
this.loadInfo()
|
2019-09-17 12:03:28 +00:00
|
|
|
let updates = setInterval(this.loadInfo, 2050)
|
|
|
|
this.props.client.on('close', () => clearInterval(updates))
|
2019-07-24 17:10:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async loadInfo() {
|
2019-08-09 15:59:12 +00:00
|
|
|
const id = await this.props.client.call("Filecoin.ID", [])
|
|
|
|
|
|
|
|
const version = await this.props.client.call("Filecoin.Version", [])
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-09 15:59:12 +00:00
|
|
|
const peers = await this.props.client.call("Filecoin.NetPeers", [])
|
2019-07-24 22:14:09 +00:00
|
|
|
|
2019-08-09 15:59:12 +00:00
|
|
|
const tipset = await this.props.client.call("Filecoin.ChainHead", [])
|
2019-07-25 14:57:30 +00:00
|
|
|
|
2019-08-15 15:46:34 +00:00
|
|
|
let addrs = await this.props.client.call('Filecoin.WalletList', [])
|
2019-07-25 23:26:40 +00:00
|
|
|
let defaultAddr = ""
|
2019-08-10 01:54:45 +00:00
|
|
|
if (addrs.length > 0) {
|
2019-08-09 15:59:12 +00:00
|
|
|
defaultAddr = await this.props.client.call('Filecoin.WalletDefaultAddress', [])
|
2019-07-25 23:26:40 +00:00
|
|
|
}
|
2019-08-15 15:46:34 +00:00
|
|
|
let paychs = await this.props.client.call('Filecoin.PaychList', [])
|
|
|
|
if(!paychs)
|
|
|
|
paychs = []
|
|
|
|
const vouchers = await Promise.all(paychs.map(paych => {
|
|
|
|
return this.props.client.call('Filecoin.PaychVoucherList', [paych])
|
|
|
|
}))
|
2019-07-25 14:57:30 +00:00
|
|
|
|
2019-08-21 15:14:38 +00:00
|
|
|
let minerList = await this.props.client.call('Filecoin.MinerAddresses', [])
|
|
|
|
|
2019-09-06 22:35:31 +00:00
|
|
|
let mpoolPending = (await this.props.client.call('Filecoin.MpoolPending', [tipset])).length
|
|
|
|
|
2019-08-09 16:11:46 +00:00
|
|
|
this.setState(() => ({
|
|
|
|
id: id,
|
|
|
|
version: version,
|
|
|
|
peers: peers.length,
|
|
|
|
tipset: tipset,
|
|
|
|
|
2019-09-06 22:35:31 +00:00
|
|
|
mpoolPending: mpoolPending,
|
|
|
|
|
2019-08-10 01:54:45 +00:00
|
|
|
addrs: addrs,
|
2019-08-15 15:46:34 +00:00
|
|
|
paychs: paychs,
|
|
|
|
vouchers: vouchers,
|
|
|
|
|
2019-08-21 15:14:38 +00:00
|
|
|
defaultAddr: defaultAddr,
|
2019-07-24 17:10:44 +00:00
|
|
|
|
2019-08-21 15:14:38 +00:00
|
|
|
minerList: minerList,
|
|
|
|
}))
|
2019-07-24 22:30:17 +00:00
|
|
|
}
|
|
|
|
|
2019-08-21 22:47:44 +00:00
|
|
|
async newSecpAddr() {
|
2019-07-30 23:18:21 +00:00
|
|
|
const t = "secp256k1"
|
2019-08-09 15:59:12 +00:00
|
|
|
await this.props.client.call("Filecoin.WalletNew", [t])
|
2019-07-30 23:18:21 +00:00
|
|
|
this.loadInfo()
|
|
|
|
}
|
|
|
|
|
2019-08-21 22:47:44 +00:00
|
|
|
async newBLSAddr() {
|
|
|
|
const t = "bls"
|
|
|
|
await this.props.client.call("Filecoin.WalletNew", [t])
|
|
|
|
this.loadInfo()
|
|
|
|
}
|
|
|
|
|
2019-09-09 16:01:53 +00:00
|
|
|
startStorageMiner() {
|
|
|
|
this.props.spawnStorageNode(this.props.node.Repo, this.props.client)
|
2019-08-09 15:59:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async add1k(to) {
|
|
|
|
await this.props.give1k(to)
|
2019-07-30 23:18:21 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 02:34:11 +00:00
|
|
|
explorer() {
|
|
|
|
this.props.mountWindow((onClose) => <ChainExplorer onClose={onClose} ts={this.state.tipset} client={this.props.client} mountWindow={this.props.mountWindow}/>)
|
|
|
|
}
|
|
|
|
|
2019-09-06 17:42:31 +00:00
|
|
|
client() {
|
|
|
|
this.props.mountWindow((onClose) => <Client onClose={onClose} node={this.props.node} client={this.props.client} pondClient={this.props.pondClient} mountWindow={this.props.mountWindow}/>)
|
|
|
|
}
|
|
|
|
|
2019-09-17 12:03:28 +00:00
|
|
|
async stop() {
|
|
|
|
await this.props.stop()
|
|
|
|
}
|
|
|
|
|
2019-07-24 17:10:44 +00:00
|
|
|
render() {
|
|
|
|
let runtime = <div></div>
|
2019-08-09 16:11:46 +00:00
|
|
|
|
|
|
|
if (this.state.id) {
|
2019-07-24 22:14:09 +00:00
|
|
|
let chainInfo = <div></div>
|
|
|
|
if (this.state.tipset !== undefined) {
|
|
|
|
chainInfo = (
|
2019-07-25 16:13:46 +00:00
|
|
|
<div>
|
|
|
|
Head: {
|
2019-08-09 17:32:46 +00:00
|
|
|
<BlockLinks cids={this.state.tipset.Cids} conn={this.props.client} mountWindow={this.props.mountWindow} />
|
2019-09-06 22:35:31 +00:00
|
|
|
} H:{this.state.tipset.Height} Mp:{this.state.mpoolPending} <a href="#" onClick={this.explorer}>[Explore]</a> <a href="#" onClick={this.client}>[Client]</a>
|
2019-07-25 16:13:46 +00:00
|
|
|
</div>
|
2019-07-24 22:14:09 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-08-21 16:31:14 +00:00
|
|
|
let miners = <span/>
|
2019-08-21 15:14:38 +00:00
|
|
|
if(this.state.minerList.length > 0) {
|
2019-08-21 16:31:14 +00:00
|
|
|
miners = this.state.minerList.map((a, k) => <div key={k}><Address miner={true} client={this.props.client} addr={a} mountWindow={this.props.mountWindow}/></div>)
|
2019-07-24 23:46:48 +00:00
|
|
|
}
|
|
|
|
|
2019-09-18 17:53:48 +00:00
|
|
|
let storageMine = <a href="#" onClick={this.startStorageMiner} hidden={!this.props.spawnStorageNode}>[Spawn Storage Miner]</a>
|
2019-07-30 23:18:21 +00:00
|
|
|
|
2019-08-10 01:54:45 +00:00
|
|
|
let addresses = this.state.addrs.map((addr) => {
|
2019-09-06 22:35:31 +00:00
|
|
|
let line = <Address client={this.props.client} add1k={this.add1k} add10k={true} nonce={true} addr={addr} mountWindow={this.props.mountWindow}/>
|
2019-07-25 15:13:45 +00:00
|
|
|
if (this.state.defaultAddr === addr) {
|
|
|
|
line = <b>{line}</b>
|
|
|
|
}
|
2019-08-09 16:11:46 +00:00
|
|
|
return <div key={addr}>{line}</div>
|
2019-07-25 15:13:45 +00:00
|
|
|
})
|
2019-08-15 15:46:34 +00:00
|
|
|
let paychannels = this.state.paychs.map((addr, ak) => {
|
2019-09-06 22:35:31 +00:00
|
|
|
const line = <Address client={this.props.client} add1k={this.add1k} add10k={true} addr={addr} mountWindow={this.props.mountWindow}/>
|
2019-08-15 15:46:34 +00:00
|
|
|
const vouchers = this.state.vouchers[ak].map(voucher => {
|
|
|
|
let extra = <span></span>
|
|
|
|
if(voucher.Extra) {
|
2019-08-16 17:37:04 +00:00
|
|
|
extra = <span>Verif: <<b><Address nobalance={true} client={this.props.client} addr={voucher.Extra.Actor} method={voucher.Extra.Method} mountWindow={this.props.mountWindow}/></b>></span>
|
2019-08-15 15:46:34 +00:00
|
|
|
}
|
|
|
|
|
2019-09-16 21:25:23 +00:00
|
|
|
return <div key={`${addr} ${voucher.Lane} ${voucher.Nonce}`} className="FullNode-voucher">
|
2019-08-15 15:46:34 +00:00
|
|
|
Voucher Nonce:<b>{voucher.Nonce}</b> Lane:<b>{voucher.Lane}</b> Amt:<b>{voucher.Amount}</b> TL:<b>{voucher.TimeLock}</b> MinCl:<b>{voucher.MinCloseHeight}</b> {extra}
|
|
|
|
</div>
|
|
|
|
})
|
|
|
|
return <div key={addr}>
|
|
|
|
{line}
|
|
|
|
{vouchers}
|
|
|
|
</div>
|
|
|
|
})
|
2019-07-25 14:57:30 +00:00
|
|
|
|
2019-07-24 17:10:44 +00:00
|
|
|
runtime = (
|
|
|
|
<div>
|
2019-08-09 16:11:46 +00:00
|
|
|
<div>{this.props.node.ID} - v{this.state.version.Version}, <abbr title={this.state.id}>{this.state.id.substr(-8)}</abbr>, {this.state.peers} peers</div>
|
2019-07-24 22:14:09 +00:00
|
|
|
<div>Repo: LOTUS_PATH={this.props.node.Repo}</div>
|
|
|
|
{chainInfo}
|
2019-07-25 14:57:30 +00:00
|
|
|
<div>
|
2019-08-21 16:31:14 +00:00
|
|
|
{storageMine}
|
2019-07-30 23:18:21 +00:00
|
|
|
</div>
|
|
|
|
<div>
|
2019-08-21 22:47:44 +00:00
|
|
|
<div>Balances: [New <a href="#" onClick={this.newSecpAddr}>[Secp256k1]</a> <a href="#" onClick={this.newBLSAddr}>[BLS]</a>]</div>
|
2019-08-10 01:54:45 +00:00
|
|
|
<div>{addresses}</div>
|
2019-08-21 16:31:14 +00:00
|
|
|
<div>{miners}</div>
|
2019-08-15 15:46:34 +00:00
|
|
|
<div>{paychannels}</div>
|
2019-07-25 14:57:30 +00:00
|
|
|
</div>
|
2019-07-24 22:14:09 +00:00
|
|
|
|
2019-07-24 17:10:44 +00:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-09-18 17:53:48 +00:00
|
|
|
let nodeID = this.props.node.ID ? this.props.node.ID : ''
|
|
|
|
let nodePos = this.props.node.ID ? {x: this.props.node.ID*30, y: this.props.node.ID * 30} : undefined
|
|
|
|
|
2019-07-24 17:10:44 +00:00
|
|
|
return (
|
2019-07-24 18:42:02 +00:00
|
|
|
<Cristal
|
2019-09-18 17:53:48 +00:00
|
|
|
title={"Node " + nodeID}
|
|
|
|
initialPosition={nodePos}
|
2019-09-17 12:03:28 +00:00
|
|
|
initialSize={{width: 690, height: 300}}
|
|
|
|
onClose={this.stop} >
|
2019-07-25 14:57:30 +00:00
|
|
|
<div className="CristalScroll">
|
|
|
|
<div className="FullNode">
|
|
|
|
{runtime}
|
|
|
|
</div>
|
2019-07-24 18:42:02 +00:00
|
|
|
</div>
|
|
|
|
</Cristal>
|
2019-07-24 17:10:44 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default FullNode
|