mirror of
https://github.com/fullstack-cash/explorer.fullstack.cash.git
synced 2026-09-21 16:52:05 -07:00
Forked from PSF repo
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "standard",
|
||||||
|
"env": {
|
||||||
|
"node": true,
|
||||||
|
"mocha": true
|
||||||
|
},
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 10
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"no-unused-vars": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Typescript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env*
|
||||||
|
|
||||||
|
# gatsby files
|
||||||
|
.cache/
|
||||||
|
public
|
||||||
|
|
||||||
|
# Mac files
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Yarn
|
||||||
|
yarn-error.log
|
||||||
|
.pnp/
|
||||||
|
.pnp.js
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
.cache
|
||||||
|
package.json
|
||||||
|
package-lock.json
|
||||||
|
public
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"semi": false,
|
||||||
|
"no-unused-vars": false
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
# This is a node.js v8+ JavaScript project
|
||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- "10"
|
||||||
|
|
||||||
|
# Build on Ubuntu Trusty (14.04)
|
||||||
|
# https://docs.travis-ci.com/user/reference/trusty/#javascript-and-nodejs-images
|
||||||
|
dist: xenial
|
||||||
|
sudo: required
|
||||||
|
|
||||||
|
# Use Docker
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
#- npm install -g mocha
|
||||||
|
|
||||||
|
# https://github.com/greenkeeperio/greenkeeper-lockfile/issues/156
|
||||||
|
#install: case $TRAVIS_BRANCH in greenkeeper*) npm i;; *) npm ci;; esac;
|
||||||
|
install:
|
||||||
|
- npm install
|
||||||
|
|
||||||
|
script: "npm run test"
|
||||||
|
|
||||||
|
# Send coverage data to Coveralls
|
||||||
|
after_success:
|
||||||
|
- npm run coverage
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
provider: script
|
||||||
|
skip_cleanup: true
|
||||||
|
script:
|
||||||
|
- npx semantic-release
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Permissionless Software Foundation
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<!-- AUTO-GENERATED-CONTENT:START (STARTER) -->
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://www.gatsbyjs.org" target="_blank">
|
||||||
|
<img alt="Gatsby" src="https://www.gatsbyjs.org/monogram.svg" width="60" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<h1 align="center">
|
||||||
|
<a href="https://explorer.fullstack.cash" target="_blank">
|
||||||
|
Explorer.FullStack.Cash
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
|
<h3 align="center">A 'block explorer' for the <a href="https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-service" target="_blank">pay-to-write database (P2WDB)</a></h3>
|
||||||
|
|
||||||
|
This is a Gatsby web app that allows users explore the current state of the
|
||||||
|
[pay-to-write database](https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-service) (P2WDB). This site was forked from [bch-wallet-starter](https://github.com/Permissionless-Software-Foundation/bch-wallet-starter).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE.md)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Configure your Gatsby site with this file.
|
||||||
|
*
|
||||||
|
* See: https://www.gatsbyjs.org/docs/gatsby-config/
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
/* Your site config here */
|
||||||
|
plugins: [
|
||||||
|
'gatsby-ipfs-web-wallet',
|
||||||
|
'gatsby-plugin-bch-tx-history'
|
||||||
|
]
|
||||||
|
}
|
||||||
Generated
+57319
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "explorer.fullstack.cash",
|
||||||
|
"description": "A 'block explorer' for the P2WDB",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"author": "Chris Troutner <chris.troutner@gmail.com>",
|
||||||
|
"contributors": [
|
||||||
|
"Daniel Gonzalez <danielhumgon@gmail.com>",
|
||||||
|
"Andre Cabrera <andrecabrera@protonmail.ch>"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "gatsby build",
|
||||||
|
"build:ipfs": "gatsby build --prefix-paths",
|
||||||
|
"develop": "gatsby develop",
|
||||||
|
"lint": "standard --env mocha --fix",
|
||||||
|
"start": "npm run develop",
|
||||||
|
"serve": "gatsby serve",
|
||||||
|
"clean": "gatsby clean",
|
||||||
|
"test": "npm run lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"gatsby": "^3.7.2",
|
||||||
|
"gatsby-ipfs-web-wallet": "1.25.3",
|
||||||
|
"gatsby-plugin-bch-tx-history": "^1.1.4",
|
||||||
|
"react-json-pretty": "^2.2.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Permissionless-Software-Foundation/explorer.fullstack.cash"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/Permissionless-Software-Foundation/explorer.fullstack.cash/issues"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"semantic-release": "^17.4.3",
|
||||||
|
"standard": "^16.0.3"
|
||||||
|
},
|
||||||
|
"release": {
|
||||||
|
"publish": [
|
||||||
|
{
|
||||||
|
"path": "@semantic-release/npm",
|
||||||
|
"npmPublish": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
This is a demonstration component. It helps to show how you can create new
|
||||||
|
menu items and Views in your own BCH web wallet dashboard app.
|
||||||
|
|
||||||
|
This file controls the View (the part on the right side of the dashboard) of
|
||||||
|
the component. The menu item is controlled by the menu-components.js file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import { Row, Col, Content, Box, Button } from 'adminlte-2-react'
|
||||||
|
import { getWalletInfo } from 'gatsby-ipfs-web-wallet/src/components/localWallet'
|
||||||
|
|
||||||
|
const BchWallet =
|
||||||
|
typeof window !== 'undefined'
|
||||||
|
? window.SlpWallet
|
||||||
|
: null
|
||||||
|
|
||||||
|
let _this
|
||||||
|
class DemoComponent extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
_this = this
|
||||||
|
this.state = {
|
||||||
|
unconfirmedBalance: 0,
|
||||||
|
confirmedBalance: 0,
|
||||||
|
totalBalance: 0,
|
||||||
|
inFetch: false,
|
||||||
|
bchWallet: '',
|
||||||
|
isChecked: ''
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const {
|
||||||
|
unconfirmedBalance,
|
||||||
|
confirmedBalance,
|
||||||
|
totalBalance,
|
||||||
|
inFetch,
|
||||||
|
isChecked
|
||||||
|
} = _this.state
|
||||||
|
return (
|
||||||
|
<Content
|
||||||
|
title='Demo Component'
|
||||||
|
subTitle='Check the BCH balance of an address'
|
||||||
|
browserTitle='Demo Component'
|
||||||
|
>
|
||||||
|
<Row>
|
||||||
|
<Col xs={12}>
|
||||||
|
<Box
|
||||||
|
title='BCH Balance'
|
||||||
|
type='primary'
|
||||||
|
closable
|
||||||
|
collapsable
|
||||||
|
loaded={!inFetch}
|
||||||
|
footer={
|
||||||
|
<Button
|
||||||
|
type='primary'
|
||||||
|
text='Check Balance'
|
||||||
|
onClick={_this.handleGetBalance}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
|
||||||
|
{
|
||||||
|
isChecked &&
|
||||||
|
<div>
|
||||||
|
<p>Confirmed: {confirmedBalance}</p>
|
||||||
|
<p>Unconfirmed: {unconfirmedBalance}</p>
|
||||||
|
<p>Total : <strong>{totalBalance}</strong></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Content>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
_this.instanceWallet() // Creates a web wallet instance
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get wallet balance
|
||||||
|
async handleGetBalance () {
|
||||||
|
try {
|
||||||
|
_this.setState({
|
||||||
|
inFetch: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const addr = 'bitcoincash:qr69kyzha07dcecrsvjwsj4s6slnlq4r8c30lxnur3'
|
||||||
|
|
||||||
|
const bchWallet = _this.state.bchWallet
|
||||||
|
const bchjs = bchWallet.bchjs
|
||||||
|
|
||||||
|
// Get the Balance
|
||||||
|
const balances = await bchjs.Electrumx.balance(addr)
|
||||||
|
|
||||||
|
const totalBalance = balances.balance.confirmed + balances.balance.unconfirmed
|
||||||
|
|
||||||
|
_this.setState({
|
||||||
|
inFetch: false,
|
||||||
|
unconfirmedBalance: balances.balance.unconfirmed,
|
||||||
|
confirmedBalance: balances.balance.confirmed,
|
||||||
|
totalBalance: totalBalance,
|
||||||
|
isChecked: true
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
_this.setState({
|
||||||
|
inFetch: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an instance of minimal-slp-wallet, with
|
||||||
|
// the local storage information if it exists
|
||||||
|
instanceWallet () {
|
||||||
|
try {
|
||||||
|
const localStorageInfo = getWalletInfo()
|
||||||
|
if (!localStorageInfo.mnemonic) return null
|
||||||
|
|
||||||
|
const jwtToken = localStorageInfo.JWT
|
||||||
|
const restURL = localStorageInfo.selectedServer
|
||||||
|
const bchjsOptions = {}
|
||||||
|
|
||||||
|
if (jwtToken) {
|
||||||
|
bchjsOptions.apiToken = jwtToken
|
||||||
|
}
|
||||||
|
if (restURL) {
|
||||||
|
bchjsOptions.restURL = restURL
|
||||||
|
}
|
||||||
|
const bchWalletLib = new BchWallet(localStorageInfo.mnemonic, bchjsOptions)
|
||||||
|
|
||||||
|
// Update bchjs instances of minimal-slp-wallet libraries
|
||||||
|
bchWalletLib.tokens.sendBch.bchjs = new bchWalletLib.BCHJS(bchjsOptions)
|
||||||
|
bchWalletLib.tokens.utxos.bchjs = new bchWalletLib.BCHJS(bchjsOptions)
|
||||||
|
|
||||||
|
_this.setState({
|
||||||
|
bchWallet: bchWalletLib
|
||||||
|
})
|
||||||
|
return bchWalletLib
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DemoComponent
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
import React from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
import { Row, Col, Box, Button } from "adminlte-2-react"
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
|
import JSONPretty from "react-json-pretty"
|
||||||
|
|
||||||
|
const HASH_EXPLORER = "https://p2wdb.fullstack.cash/entry/hash/" // PSF p2wdb hash explorer
|
||||||
|
const TX_EXPLORER = "https://simpleledger.info/tx/" // BCH Transaction Explorer
|
||||||
|
|
||||||
|
let _this
|
||||||
|
class Details extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
_this = this
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
entry: {},
|
||||||
|
entryData: {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { entry, entryData } = _this.state
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Row>
|
||||||
|
<Col sm={12}>
|
||||||
|
<Box className=" border-none mt-2" loaded={!this.state.inFetch}>
|
||||||
|
<Row className="text-center">
|
||||||
|
<Col sm={12}>
|
||||||
|
<h1 id="SendTokens">
|
||||||
|
<FontAwesomeIcon
|
||||||
|
className="title-icon"
|
||||||
|
size="xs"
|
||||||
|
icon="info-circle"
|
||||||
|
/>
|
||||||
|
<span>Details</span>
|
||||||
|
</h1>
|
||||||
|
{entry._id && (
|
||||||
|
<Box className="border-none details-data-content">
|
||||||
|
<p>
|
||||||
|
<b>IS VALID: </b>
|
||||||
|
{entry.isValid}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>APP ID: </b>
|
||||||
|
{entry.appId || "none"}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>CREATE AT: </b>
|
||||||
|
{new Date(entry.createdAt).toLocaleString()}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>ID: </b>
|
||||||
|
{entry._id}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>HASH: </b>
|
||||||
|
<a
|
||||||
|
href={`${HASH_EXPLORER}${entry.hash}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
{entry.hash}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>TRANSACTION ID : </b>
|
||||||
|
<a
|
||||||
|
href={`${TX_EXPLORER}${entry.key}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
{entry.key}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
{entryData && (
|
||||||
|
<>
|
||||||
|
<b>VALUE : </b>
|
||||||
|
<p>
|
||||||
|
- <b>Message : </b> {entryData.message}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
- <b>Signature : </b> {entryData.signature}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{!_this.isJson(entryData.data) && (
|
||||||
|
<>
|
||||||
|
- <b>Data : </b> {entryData.data}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{_this.isJson(entryData.data) && (
|
||||||
|
<>
|
||||||
|
- <b>Data :</b>
|
||||||
|
<JSONPretty
|
||||||
|
id="json-pretty"
|
||||||
|
data={entryData.data}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Col>
|
||||||
|
<Col sm={12}>
|
||||||
|
<div className="btn-wrapper">
|
||||||
|
<Button
|
||||||
|
text="Close"
|
||||||
|
type="primary"
|
||||||
|
className="btn-lg btn-close-entry mr-1 ml-1 mt-1"
|
||||||
|
onClick={_this.handleClose}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Box>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
_this.handleData()
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
if (_this.props.entry._id !== _this.state.entry._id) {
|
||||||
|
_this.handleData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleData() {
|
||||||
|
try {
|
||||||
|
const { entry } = _this.props
|
||||||
|
_this.setState({
|
||||||
|
entry,
|
||||||
|
entryData: entry.value,
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("Error in handleData()", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClose() {
|
||||||
|
_this.props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detects if the input is a string and converts to json object
|
||||||
|
isJson(data) {
|
||||||
|
try {
|
||||||
|
JSON.parse(data)
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Details.propTypes = {
|
||||||
|
entry: PropTypes.object,
|
||||||
|
onClose: PropTypes.func,
|
||||||
|
}
|
||||||
|
export default Details
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
.btn-close-entry{
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
.action-handler{
|
||||||
|
color: #3c8dbc;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.details-data-content{
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Row, Col, Content, Box, DataTable } from 'adminlte-2-react'
|
||||||
|
import Details from './details'
|
||||||
|
import './explorer.css'
|
||||||
|
const axios = require('axios').default
|
||||||
|
|
||||||
|
const SERVER = 'https://p2wdb.fullstack.cash/'
|
||||||
|
const EXPLORER_URL = 'https://explorer.bitcoin.com/bch/tx/'
|
||||||
|
|
||||||
|
let _this
|
||||||
|
class Explorer extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
_this = this
|
||||||
|
this.state = {
|
||||||
|
showEntry: false,
|
||||||
|
data: [],
|
||||||
|
entries: [],
|
||||||
|
entryData: null
|
||||||
|
}
|
||||||
|
|
||||||
|
this.firstColumns = [
|
||||||
|
{ title: 'Created At', data: 'createdAt' },
|
||||||
|
{
|
||||||
|
title: 'Transaction',
|
||||||
|
data: 'txid',
|
||||||
|
render: txid => (
|
||||||
|
<span className='on-click-event action-handler'>
|
||||||
|
{txid.subString}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Hash',
|
||||||
|
data: 'hash',
|
||||||
|
render: hash => (
|
||||||
|
<span className='on-click-event action-handler'>
|
||||||
|
{hash.subString}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ title: 'App Id', data: 'appId' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { data, entryData } = _this.state
|
||||||
|
return (
|
||||||
|
<Content
|
||||||
|
title='P2WDB Explorer'
|
||||||
|
subTitle='Block Explorer for P2WDB'
|
||||||
|
browserTitle='P2WDB Explorer'
|
||||||
|
>
|
||||||
|
<Row>
|
||||||
|
{entryData && (
|
||||||
|
<Col xs={12}>
|
||||||
|
<Details entry={entryData} onClose={_this.handleClose} />
|
||||||
|
</Col>
|
||||||
|
)}
|
||||||
|
<Col xs={12}>
|
||||||
|
<Box title='Block explorer for P2WDB'>
|
||||||
|
<DataTable
|
||||||
|
columns={_this.firstColumns}
|
||||||
|
data={data}
|
||||||
|
options={{
|
||||||
|
paging: true,
|
||||||
|
lengthChange: false,
|
||||||
|
searching: false,
|
||||||
|
ordering: false,
|
||||||
|
info: true,
|
||||||
|
autoWidth: false
|
||||||
|
}}
|
||||||
|
onClickEvents={{
|
||||||
|
onClickEvent: (data, rowIdx, rowData) => {
|
||||||
|
_this.handleEvents(data)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Content>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount () {
|
||||||
|
_this.handleEntries()
|
||||||
|
|
||||||
|
// Get data and update table
|
||||||
|
// every 20 seconds
|
||||||
|
setInterval(() => {
|
||||||
|
_this.handleEntries()
|
||||||
|
}, 20000)
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleEntries () {
|
||||||
|
const entries = await _this.getEntries()
|
||||||
|
_this.generateDataTable(entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
// REST petition to Get data fron the pw2db
|
||||||
|
async getEntries () {
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
method: 'GET',
|
||||||
|
url: `${SERVER}entry/all/${0}`,
|
||||||
|
data: {}
|
||||||
|
}
|
||||||
|
const result = await axios.request(options)
|
||||||
|
_this.setState({
|
||||||
|
entries: result.data.data
|
||||||
|
})
|
||||||
|
return result.data.data
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Error in getEntries() ', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate table content
|
||||||
|
generateDataTable (dataArr) {
|
||||||
|
try {
|
||||||
|
const data = []
|
||||||
|
|
||||||
|
for (let i = 0; i < dataArr.length; i++) {
|
||||||
|
const entry = dataArr[i]
|
||||||
|
const row = {
|
||||||
|
// createdAt row data
|
||||||
|
createdAt: new Date(entry.createdAt).toLocaleString(),
|
||||||
|
// Transaction id row data
|
||||||
|
txid: {
|
||||||
|
subString: _this.cutString(entry.key),
|
||||||
|
txid: entry.key
|
||||||
|
},
|
||||||
|
// Hash row data
|
||||||
|
hash: {
|
||||||
|
subString: _this.cutString(entry.hash),
|
||||||
|
hash: entry.hash,
|
||||||
|
data: entry
|
||||||
|
},
|
||||||
|
// App id row data
|
||||||
|
appId: entry.appId || 'none'
|
||||||
|
}
|
||||||
|
data.push(row)
|
||||||
|
}
|
||||||
|
_this.setState({
|
||||||
|
data
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Error in generateDataTable() ', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cutString (txid) {
|
||||||
|
try {
|
||||||
|
const subTxid = txid.slice(0, 4)
|
||||||
|
const subTxid2 = txid.slice(-4)
|
||||||
|
return `${subTxid}...${subTxid2}`
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Error in cutString() ', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTxIdClick (txid) {
|
||||||
|
try {
|
||||||
|
window.open(`${EXPLORER_URL}${txid}`, '_blank')
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Error in handleTxIdClick() ', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleHashClick (data) {
|
||||||
|
try {
|
||||||
|
data.isValid = data.isValid.toString()
|
||||||
|
_this.setState({
|
||||||
|
entryData: data
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
_this.setState({
|
||||||
|
entryData: null
|
||||||
|
})
|
||||||
|
console.warn('Error in handleHashClick() ', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleEvents (eventData) {
|
||||||
|
try {
|
||||||
|
const { txid, hash, data } = eventData
|
||||||
|
|
||||||
|
if (txid) {
|
||||||
|
_this.handleTxIdClick(txid)
|
||||||
|
}
|
||||||
|
if (hash && data) {
|
||||||
|
_this.handleHashClick(data)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Error in handleEvents() ', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClose () {
|
||||||
|
_this.setState({
|
||||||
|
entryData: null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Explorer
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
This is an example of using Gatsby 'Component Shadowing' to overwrite the
|
||||||
|
default Wallet View. It injects the same TX History component at the bottom
|
||||||
|
of the Wallet View.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import Wallet from 'gatsby-ipfs-web-wallet/src/components/admin-lte/wallet/index'
|
||||||
|
|
||||||
|
// import TXHistory from 'gatsby-plugin-bch-tx-history/src/components/txhistory'
|
||||||
|
import TXHistory from 'gatsby-plugin-bch-tx-history'
|
||||||
|
|
||||||
|
class Wallet2 extends Wallet {
|
||||||
|
// class Wallet2 extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
console.log('Loading new example view.')
|
||||||
|
|
||||||
|
// console.log('Wallet info: ', props.walletInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Wallet {...this.props} importComponents={this.addCards()} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
addCards () {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TXHistory
|
||||||
|
walletInfo={this.props.walletInfo}
|
||||||
|
bchWallet={this.props.bchWallet}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Wallet2
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
This file is how you add new menu items to your site. It uses the Gatsby
|
||||||
|
concept of Component Shadowing:
|
||||||
|
https://www.gatsbyjs.org/blog/2019-04-29-component-shadowing/
|
||||||
|
|
||||||
|
It over-rides he default file in the gatsby-ipfs-web-wallet Theme.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import { Sidebar } from 'adminlte-2-react'
|
||||||
|
|
||||||
|
// Example/Demo component. This is how you would build a component internal to
|
||||||
|
// your wallet app/site.
|
||||||
|
import DemoComponent from '../../demo-component'
|
||||||
|
|
||||||
|
// TX History Plugin.
|
||||||
|
// This is an example of an external plugin for the wallet. It's a modular
|
||||||
|
// approach to sharing 'lego blocks' between wallet apps.
|
||||||
|
// import TXHistory from 'gatsby-plugin-bch-tx-history/src/components/txhistory'
|
||||||
|
import TXHistory from 'gatsby-plugin-bch-tx-history'
|
||||||
|
|
||||||
|
// Default components from gatsby-ipfs-web-wallet.
|
||||||
|
import Wallet from 'gatsby-ipfs-web-wallet/src/components/admin-lte/wallet'
|
||||||
|
import Tokens from 'gatsby-ipfs-web-wallet/src/components/admin-lte/tokens'
|
||||||
|
import Configure from 'gatsby-ipfs-web-wallet/src/components/admin-lte/configure'
|
||||||
|
import SendReceive from 'gatsby-ipfs-web-wallet/src/components/admin-lte/send-receive'
|
||||||
|
import Explorer from '../../explorer'
|
||||||
|
|
||||||
|
const { Item } = Sidebar
|
||||||
|
|
||||||
|
const MenuComponents = props => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
active: true, // Set this view as default
|
||||||
|
key: 'Explorer',
|
||||||
|
component: <Explorer key='Explorer' {...props} />,
|
||||||
|
menuItem: <Item icon='fas-binoculars' key='Explorer' text='Explorer' />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Tokens',
|
||||||
|
component: <Tokens key='Tokens' {...props} />,
|
||||||
|
menuItem: <Item icon='fas-coins' key='Tokens' text='Tokens' />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Send/Receive BCH',
|
||||||
|
component: <SendReceive key='Send/Receive BCH' {...props} />,
|
||||||
|
menuItem: (
|
||||||
|
<Item
|
||||||
|
icon='fa-exchange-alt'
|
||||||
|
key='Send/Receive BCH'
|
||||||
|
text='Send/Receive BCH'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Wallet',
|
||||||
|
component: <Wallet key='Wallet' {...props} />,
|
||||||
|
menuItem: <Item icon='fa-wallet' key='Wallet' text='Wallet' />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Configure',
|
||||||
|
component: <Configure key='Configure' {...props} />,
|
||||||
|
menuItem: <Item icon='fas-cog' key='Configure' text='Configure' />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'TX History',
|
||||||
|
component: <TXHistory key='TX History' {...props} />,
|
||||||
|
menuItem: <Item icon='fas-cog' key='TX History' text='TX History' />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Demo Component',
|
||||||
|
component: <DemoComponent key='Demo Component' {...props} />,
|
||||||
|
menuItem: (
|
||||||
|
<Item icon='fas-cog' key='Demo Component' text='Demo Component' />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MenuComponents
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
This file is intended to be overwritten. It provides a common place to store
|
||||||
|
site configuration data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
title: 'Wallet Demo',
|
||||||
|
titleShort: 'Demo',
|
||||||
|
balanceText: 'BCH Balance',
|
||||||
|
balanceIcon: 'fab-bitcoin',
|
||||||
|
|
||||||
|
// The BCH address used in a memo.cash account. Used for tracking the IPFS
|
||||||
|
// hash of the mirror of this site.
|
||||||
|
memoAddr: 'bitcoincash:qzr4s6fwk55zvl7xqsjpr4k7zkqfmvcz7qapxys8t5',
|
||||||
|
|
||||||
|
// Footer Information
|
||||||
|
hostText: 'FullStack.cash',
|
||||||
|
hostUrl: 'https://fullstack.cash/',
|
||||||
|
sourceCode: 'https://github.com/Permissionless-Software-Foundation/bch-wallet-starter',
|
||||||
|
torUrl: 'tozqhxcrknbv5l3wshwgj6vp3bj5ezw7qp4jdn4bjrhcpetpcq74j7ad.onion',
|
||||||
|
clearWebUrl: 'https://demo-wallet.fullstack.cash'
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = config
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
// import { withPrefix, Link } from 'gatsby'
|
||||||
|
|
||||||
|
// window && typeof window !== 'undefined' && window.test = 'testing'
|
||||||
|
|
||||||
|
export default function HTML (props) {
|
||||||
|
return (
|
||||||
|
<html {...props.htmlAttributes}>
|
||||||
|
<head>
|
||||||
|
<meta charSet='utf-8' />
|
||||||
|
<meta httpEquiv='x-ua-compatible' content='ie=edge' />
|
||||||
|
<meta
|
||||||
|
name='viewport'
|
||||||
|
content='width=device-width, initial-scale=1, shrink-to-fit=no'
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* minimal-slp-wallet-web */}
|
||||||
|
<script src='https://unpkg.com/minimal-slp-wallet' />
|
||||||
|
|
||||||
|
{/* bch-message-lib */}
|
||||||
|
<script src='https://unpkg.com/bch-message-lib' />
|
||||||
|
|
||||||
|
{props.headComponents}
|
||||||
|
</head>
|
||||||
|
<body {...props.bodyAttributes}>
|
||||||
|
{props.preBodyComponents}
|
||||||
|
<div
|
||||||
|
key='body'
|
||||||
|
id='___gatsby'
|
||||||
|
dangerouslySetInnerHTML={{ __html: props.body }}
|
||||||
|
/>
|
||||||
|
{props.postBodyComponents}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
HTML.propTypes = {
|
||||||
|
htmlAttributes: PropTypes.object,
|
||||||
|
headComponents: PropTypes.array,
|
||||||
|
bodyAttributes: PropTypes.object,
|
||||||
|
preBodyComponents: PropTypes.array,
|
||||||
|
body: PropTypes.string,
|
||||||
|
postBodyComponents: PropTypes.array
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
Reference in New Issue
Block a user