mirror of
https://github.com/fullstack-cash/fullstack-gatsby-theme-bch-wallet.git
synced 2026-09-21 16:52:06 -07:00
Merge pull request #6 from Permissionless-Software-Foundation/dh-wallet-view
feat(wallet): Added minimal-slp-wallet and redux integration
This commit is contained in:
+2
-7
@@ -1,7 +1,2 @@
|
||||
/**
|
||||
* Implement Gatsby's Browser APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/browser-apis/
|
||||
*/
|
||||
|
||||
// You can delete this file if you're not using it
|
||||
import wrapWithProvider from "./wrap-with-provider"
|
||||
export const wrapRootElement = wrapWithProvider
|
||||
+7
-6
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Implement Gatsby's Node APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/node-apis/
|
||||
*/
|
||||
|
||||
// You can delete this file if you're not using it
|
||||
exports.onCreateWebpackConfig = ({ actions }) => {
|
||||
actions.setWebpackConfig({
|
||||
node: {
|
||||
fs: 'empty'
|
||||
},
|
||||
})
|
||||
}
|
||||
+2
-7
@@ -1,7 +1,2 @@
|
||||
/**
|
||||
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/ssr-apis/
|
||||
*/
|
||||
|
||||
// You can delete this file if you're not using it
|
||||
import wrapWithProvider from "./wrap-with-provider"
|
||||
export const wrapRootElement = wrapWithProvider
|
||||
Generated
+2888
-5
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -15,11 +15,13 @@
|
||||
"gatsby-plugin-sharp": "^2.6.9",
|
||||
"gatsby-source-filesystem": "^2.3.8",
|
||||
"gatsby-transformer-sharp": "^2.5.3",
|
||||
"minimal-slp-wallet": "^1.3.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-helmet": "^6.0.0",
|
||||
"react-qr-reader": "^2.2.1"
|
||||
"react-qr-reader": "^2.2.1",
|
||||
"react-redux": "^7.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "2.0.5"
|
||||
|
||||
@@ -1,36 +1,40 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import Audit from "./audit"
|
||||
import Configure from "./configure"
|
||||
import Icons from "./icons"
|
||||
import Settings from "./settings"
|
||||
import Wallet from "./wallet"
|
||||
|
||||
import AdminLTE, { Sidebar } from "adminlte-2-react"
|
||||
import ScannerModal from "../qr-scanner/modal"
|
||||
|
||||
import Layout from "../layout"
|
||||
import "./admin-lte.css"
|
||||
import BchWallet from "minimal-slp-wallet"
|
||||
|
||||
import { BrowserRouter as Router } from "react-router-dom"
|
||||
const { Item } = Sidebar
|
||||
|
||||
// Screen width to hide the side menu on click
|
||||
const MENU_HIDE_WIDTH = 770
|
||||
|
||||
const MENU_HIDE_WIDTH = 770
|
||||
|
||||
let _this
|
||||
class AdminLTEPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
_this = this
|
||||
this.state = {
|
||||
bchBalance: Math.random().toFixed(8),
|
||||
bchBalance: 0,
|
||||
showScannerModal: false,
|
||||
section: "Settings",
|
||||
section: "Wallet",
|
||||
menuIsHide: false,
|
||||
walletInfo: {},
|
||||
}
|
||||
_this.BchWallet = BchWallet
|
||||
}
|
||||
|
||||
sidebar = [
|
||||
<Item icon="fas-cogs" key="Portfolio" text="Settings" activeOn="/" />,
|
||||
<Item icon="fa-wallet" key="Wallet" text="Wallet" activeOn="/" />,
|
||||
<Item icon="fas-icons" key="Icons" text="Icons" />,
|
||||
<Item icon="fas-cog" key="Configure" text="Configure" />,
|
||||
<Item icon="fa-tablet-alt" key="Audit" text="Audit" />,
|
||||
@@ -49,7 +53,7 @@ class AdminLTEPage extends React.Component {
|
||||
<>
|
||||
<AdminLTE title={["FullStack.cash"]} titleShort={["PSF"]} theme="blue">
|
||||
<Sidebar.Core>
|
||||
<Item key="Balance" text="Balance" icon="fab-bitcoin" >
|
||||
<Item key="Balance" text="Balance" icon="fab-bitcoin">
|
||||
<div className="sidebar-balance">
|
||||
<div>
|
||||
<h3>BCH Balance </h3>
|
||||
@@ -63,10 +67,16 @@ class AdminLTEPage extends React.Component {
|
||||
</Sidebar.Core>
|
||||
<Layout path="/">
|
||||
<div className="components-container">
|
||||
{_this.state.section === "Settings" && <Settings />}
|
||||
{_this.state.section === "Icons" && <Icons />}
|
||||
{_this.state.section === "Configure" && <Configure />}
|
||||
{_this.state.section === "Audit" && <Audit />}
|
||||
{_this.state.section === "Wallet" && (
|
||||
<Wallet
|
||||
setWallet={_this.props.setWallet}
|
||||
walletInfo={_this.props.walletInfo}
|
||||
updateBalance={_this.props.updateBalance}
|
||||
/>
|
||||
)}
|
||||
{_this.state.section === "Icons" && <Icons />}
|
||||
{_this.state.section === "Configure" && <Configure />}
|
||||
{_this.state.section === "Audit" && <Audit />}
|
||||
</div>
|
||||
</Layout>
|
||||
</AdminLTE>
|
||||
@@ -80,12 +90,49 @@ class AdminLTEPage extends React.Component {
|
||||
</>
|
||||
)
|
||||
}
|
||||
componentDidMount() {
|
||||
// Get wallet balance
|
||||
async getBalance() {
|
||||
try {
|
||||
const { mnemonic } = _this.props.walletInfo
|
||||
if (mnemonic) {
|
||||
const bchWalletLib = new _this.BchWallet(mnemonic)
|
||||
await bchWalletLib.walletInfoPromise
|
||||
const myBalance = await bchWalletLib.getBalance()
|
||||
_this.props.updateBalance(myBalance)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
_this.customMenuItems()
|
||||
_this.dropDownBalance()
|
||||
_this.addOnClickEventToScanner()
|
||||
|
||||
_this.activeItemById("Settings")
|
||||
_this.activeItemById("Wallet")
|
||||
|
||||
await _this.updateState()
|
||||
setTimeout(() => {
|
||||
_this.getBalance()
|
||||
}, 250)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
_this.updateState()
|
||||
}
|
||||
// Update component state when props change
|
||||
updateState() {
|
||||
if (_this.props.walletInfo.mnemonic !== _this.state.walletInfo.mnemonic) {
|
||||
_this.setState({
|
||||
walletInfo: _this.props.walletInfo,
|
||||
})
|
||||
}
|
||||
if (_this.props.bchBalance !== _this.state.bchBalance) {
|
||||
_this.setState({
|
||||
bchBalance: _this.props.bchBalance,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Due to that it is not possible to add the "onClick" method
|
||||
@@ -153,13 +200,12 @@ class AdminLTEPage extends React.Component {
|
||||
try {
|
||||
const windowWidth = window.innerWidth
|
||||
//console.log("Window Width : ",windowWidth)
|
||||
if(windowWidth > MENU_HIDE_WIDTH) return
|
||||
if (windowWidth > MENU_HIDE_WIDTH) return
|
||||
const toggleEle = document.getElementsByClassName("sidebar-toggle")
|
||||
toggleEle[0].click()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Adds the "onClick" event to the QR scanner item
|
||||
@@ -170,7 +216,6 @@ class AdminLTEPage extends React.Component {
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Controller to show the QR scanner
|
||||
@@ -182,6 +227,14 @@ class AdminLTEPage extends React.Component {
|
||||
showScannerModal: !_this.state.showScannerModal,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
// Props prvided by redux
|
||||
AdminLTEPage.propTypes = {
|
||||
walletInfo: PropTypes.object.isRequired,
|
||||
bchBalance: PropTypes.number.isRequired,
|
||||
setWallet: PropTypes.func.isRequired,
|
||||
updateBalance: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
export default AdminLTEPage
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import React from "react"
|
||||
|
||||
import { Row, Col, Box, Button } from "adminlte-2-react"
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||
class NewWallet extends React.Component {
|
||||
state = {}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Row>
|
||||
<Col sm={2} />
|
||||
<Col sm={8}>
|
||||
<Box className="hover-shadow border-none mt-2">
|
||||
<Row>
|
||||
<Col sm={12} className="text-center">
|
||||
<h1>
|
||||
<FontAwesomeIcon
|
||||
className="title-icon"
|
||||
size="xs"
|
||||
icon={"plus"}
|
||||
/>
|
||||
<span>New Wallet</span>
|
||||
</h1>
|
||||
</Col>
|
||||
<Col sm={12} className="text-center mt-2 mb-2">
|
||||
<Button
|
||||
text="Create Wallet"
|
||||
type="primary"
|
||||
className="btn-lg"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Box>
|
||||
</Col>
|
||||
<Col sm={2} />
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default NewWallet
|
||||
@@ -1,24 +0,0 @@
|
||||
import React from "react"
|
||||
|
||||
import { Content } from "adminlte-2-react"
|
||||
import ImportWallet from "./import"
|
||||
import NewWallet from "./create"
|
||||
import InfoWallets from "./info"
|
||||
|
||||
class Settings extends React.Component {
|
||||
state = {}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<Content>
|
||||
<NewWallet />
|
||||
<ImportWallet />
|
||||
<InfoWallets />
|
||||
</Content>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Settings
|
||||
@@ -0,0 +1,74 @@
|
||||
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 BchWallet from "minimal-slp-wallet"
|
||||
|
||||
let _this
|
||||
class NewWallet extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
_this = this
|
||||
this.state = {}
|
||||
|
||||
_this.BchWallet = BchWallet
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<Row>
|
||||
<Col sm={2} />
|
||||
<Col sm={8}>
|
||||
<Box className="hover-shadow border-none mt-2">
|
||||
<Row>
|
||||
<Col sm={12} className="text-center">
|
||||
<h1>
|
||||
<FontAwesomeIcon
|
||||
className="title-icon"
|
||||
size="xs"
|
||||
icon={"plus"}
|
||||
/>
|
||||
<span>New Wallet</span>
|
||||
</h1>
|
||||
</Col>
|
||||
<Col sm={12} className="text-center mt-2 mb-2">
|
||||
<Button
|
||||
text="Create Wallet"
|
||||
type="primary"
|
||||
className="btn-lg"
|
||||
onClick={_this.createWallet}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Box>
|
||||
</Col>
|
||||
<Col sm={2} />
|
||||
</Row>
|
||||
</>
|
||||
)
|
||||
}
|
||||
async createWallet() {
|
||||
try {
|
||||
|
||||
const bchWalletLib = new _this.BchWallet()
|
||||
await bchWalletLib.walletInfoPromise // Wait for wallet to be created.
|
||||
const walletInfo = bchWalletLib.walletInfo
|
||||
walletInfo.from = "created"
|
||||
|
||||
const myBalance = await bchWalletLib.getBalance()
|
||||
|
||||
// Update redux state
|
||||
_this.props.setWallet(walletInfo)
|
||||
_this.props.updateBalance(myBalance)
|
||||
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
NewWallet.propTypes = {
|
||||
setWallet: PropTypes.func.isRequired,
|
||||
updateBalance: PropTypes.func.isRequired,
|
||||
}
|
||||
export default NewWallet
|
||||
+78
-8
@@ -1,7 +1,9 @@
|
||||
import React from "react"
|
||||
|
||||
import PropTypes from "prop-types"
|
||||
import { Row, Col, Box, Button, Inputs } from "adminlte-2-react"
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||
import BchWallet from "minimal-slp-wallet"
|
||||
|
||||
const { Text } = Inputs
|
||||
|
||||
let _this
|
||||
@@ -14,7 +16,9 @@ class ImportWallet extends React.Component {
|
||||
this.state = {
|
||||
mnemonic: "",
|
||||
privateKey: "",
|
||||
errMsg: "",
|
||||
}
|
||||
_this.BchWallet = BchWallet
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -44,7 +48,6 @@ class ImportWallet extends React.Component {
|
||||
placeholder="12 word mnemonic"
|
||||
label="12 word mnemonic"
|
||||
labelPosition="above"
|
||||
maxlength={12}
|
||||
onChange={_this.handleUpdate}
|
||||
/>
|
||||
<Text
|
||||
@@ -59,9 +62,19 @@ class ImportWallet extends React.Component {
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col sm={12} className="text-center">
|
||||
{_this.state.errMsg && (
|
||||
<p className="error-color">{_this.state.errMsg}</p>
|
||||
)}
|
||||
</Col>
|
||||
|
||||
<Col sm={12} className="text-center mt-2 mb-2">
|
||||
<Button text="Import" type="primary" className="btn-lg" />
|
||||
<Button
|
||||
text="Import"
|
||||
type="primary"
|
||||
className="btn-lg"
|
||||
onClick={_this.importWallet}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Box>
|
||||
@@ -70,10 +83,9 @@ class ImportWallet extends React.Component {
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
componentDidMount(){
|
||||
componentDidMount() {
|
||||
// add max length property to mnemonic input
|
||||
document.getElementById("import-mnemonic").maxLength = "12";
|
||||
|
||||
//document.getElementById("import-mnemonic").maxLength = "12"
|
||||
}
|
||||
handleUpdate(event) {
|
||||
let value = event.target.value
|
||||
@@ -83,8 +95,66 @@ class ImportWallet extends React.Component {
|
||||
_this.setState({
|
||||
[event.target.name]: value,
|
||||
})
|
||||
//console.log(_this.state)
|
||||
}
|
||||
async importWallet() {
|
||||
try {
|
||||
_this.validateInputs()
|
||||
|
||||
const bchWalletLib = new _this.BchWallet(_this.state.mnemonic)
|
||||
await bchWalletLib.walletInfoPromise // Wait for wallet to be created.
|
||||
const walletInfo = bchWalletLib.walletInfo
|
||||
walletInfo.from = "imported"
|
||||
|
||||
const myBalance = await bchWalletLib.getBalance()
|
||||
|
||||
// Update redux state
|
||||
_this.props.setWallet(walletInfo)
|
||||
_this.props.updateBalance(myBalance)
|
||||
|
||||
// Reset form and component state
|
||||
_this.resetValues()
|
||||
} catch (error) {
|
||||
console.warn(error)
|
||||
_this.setState({
|
||||
errMsg: error.message,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Reset form and component state
|
||||
resetValues() {
|
||||
_this.setState({
|
||||
mnemonic: "",
|
||||
privateKey: "",
|
||||
errMsg: "",
|
||||
})
|
||||
const mnemonicEle = document.getElementById("import-mnemonic")
|
||||
mnemonicEle.value = ""
|
||||
|
||||
const privateKeyEle = document.getElementById("privateKey")
|
||||
privateKeyEle.value = ""
|
||||
}
|
||||
|
||||
validateInputs() {
|
||||
try {
|
||||
const { mnemonic } = _this.state
|
||||
if (mnemonic) {
|
||||
const spaceCount = mnemonic.split(" ").length //mnemonic.match(/ /g).length
|
||||
|
||||
if (spaceCount !== 12) {
|
||||
console.log("reject")
|
||||
throw new Error("mnemonic must contain 12 words")
|
||||
}
|
||||
} else {
|
||||
throw new Error("12 word mnemonic is required")
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImportWallet.propTypes = {
|
||||
setWallet: PropTypes.func.isRequired,
|
||||
updateBalance: PropTypes.func.isRequired,
|
||||
}
|
||||
export default ImportWallet
|
||||
@@ -0,0 +1,54 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { Content } from "adminlte-2-react"
|
||||
import ImportWallet from "./import"
|
||||
import NewWallet from "./create"
|
||||
import InfoWallets from "./info"
|
||||
import WalletInfo from "./wallet-info"
|
||||
|
||||
let _this
|
||||
class Wallet extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
_this = this
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<Content>
|
||||
<NewWallet
|
||||
updateBalance={_this.props.updateBalance}
|
||||
setWallet={_this.props.setWallet}
|
||||
/>
|
||||
|
||||
{_this.props.walletInfo.mnemonic &&
|
||||
_this.props.walletInfo.from === "created" && (
|
||||
<WalletInfo walletInfo={_this.props.walletInfo} />
|
||||
)}
|
||||
|
||||
<ImportWallet
|
||||
updateBalance={_this.props.updateBalance}
|
||||
setWallet={_this.props.setWallet}
|
||||
/>
|
||||
|
||||
{_this.props.walletInfo.mnemonic &&
|
||||
_this.props.walletInfo.from === "imported" && (
|
||||
<WalletInfo walletInfo={_this.props.walletInfo} />
|
||||
)}
|
||||
|
||||
<InfoWallets />
|
||||
</Content>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
Wallet.propTypes = {
|
||||
setWallet: PropTypes.func.isRequired,
|
||||
walletInfo: PropTypes.object.isRequired,
|
||||
updateBalance: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
export default Wallet
|
||||
@@ -0,0 +1,193 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
|
||||
import { Row, Col, Box } from "adminlte-2-react"
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||
import "./wallet.css"
|
||||
let _this
|
||||
class WalletInfo extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
_this = this
|
||||
this.state = {
|
||||
walletInfo: _this.props.walletInfo,
|
||||
mnemonic: "",
|
||||
privateKey: "",
|
||||
cashAddress: "",
|
||||
address: "",
|
||||
slpAddress: "",
|
||||
legacyAddress: "",
|
||||
hdPath: "",
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Row>
|
||||
<Col sm={2} />
|
||||
<Col sm={8}>
|
||||
<Box className="hover-shadow border-none mt-2">
|
||||
<Row>
|
||||
<Col sm={12} className="text-center">
|
||||
<h1>
|
||||
<FontAwesomeIcon
|
||||
className="title-icon"
|
||||
size="xs"
|
||||
icon={"wallet"}
|
||||
/>
|
||||
<span>My Wallet</span>
|
||||
</h1>
|
||||
</Col>
|
||||
|
||||
<Col sm={12} className="text-center wallet-info-container">
|
||||
<Row className="wallet-info-content mt-1 text-left">
|
||||
<Col xs={10} sm={11}>
|
||||
<span>
|
||||
<b>Mnemonic:</b> {_this.state.mnemonic}
|
||||
</span>
|
||||
</Col>
|
||||
<Col xs={2} sm={1}>
|
||||
<FontAwesomeIcon
|
||||
className="icon btn-animation"
|
||||
size="lg"
|
||||
onClick={() => _this.copyToClipBoard("mnemonic")}
|
||||
icon={"copy"}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="wallet-info-content mt-1 text-left">
|
||||
<Col xs={10} sm={11}>
|
||||
<span>
|
||||
<b>Private Key: </b> {_this.state.privateKey}
|
||||
</span>
|
||||
</Col>
|
||||
<Col xs={2} sm={1}>
|
||||
<FontAwesomeIcon
|
||||
className="icon btn-animation"
|
||||
size="lg"
|
||||
onClick={() => _this.copyToClipBoard("privateKey")}
|
||||
icon={"copy"}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="wallet-info-content mt-1 text-left">
|
||||
<Col xs={10} sm={11}>
|
||||
<span>
|
||||
<b>Cash Address: </b> {_this.state.cashAddress}
|
||||
</span>
|
||||
</Col>
|
||||
<Col xs={2} sm={1}>
|
||||
<FontAwesomeIcon
|
||||
className="icon btn-animation"
|
||||
size="lg"
|
||||
onClick={() => _this.copyToClipBoard("cashAddress")}
|
||||
icon={"copy"}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="wallet-info-content mt-1 text-left">
|
||||
<Col xs={10} sm={11}>
|
||||
<span>
|
||||
<b>Address: </b> {_this.state.address}
|
||||
</span>
|
||||
</Col>
|
||||
<Col xs={2} sm={1}>
|
||||
<FontAwesomeIcon
|
||||
className="icon btn-animation"
|
||||
size="lg"
|
||||
onClick={() => _this.copyToClipBoard("address")}
|
||||
icon={"copy"}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="wallet-info-content mt-1 text-left">
|
||||
<Col xs={10} sm={11}>
|
||||
<span>
|
||||
<b>Slp Address: </b> {_this.state.slpAddress}
|
||||
</span>
|
||||
</Col>
|
||||
<Col xs={2} sm={1}>
|
||||
<FontAwesomeIcon
|
||||
className="icon btn-animation"
|
||||
size="lg"
|
||||
onClick={() => _this.copyToClipBoard("slpAddress")}
|
||||
icon={"copy"}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="wallet-info-content mt-1 text-left">
|
||||
<Col xs={10} sm={11}>
|
||||
<span>
|
||||
<b>Legacy Address: </b> {_this.state.legacyAddress}
|
||||
</span>
|
||||
</Col>
|
||||
<Col xs={2} sm={1}>
|
||||
<FontAwesomeIcon
|
||||
className="icon btn-animation"
|
||||
size="lg"
|
||||
onClick={() => _this.copyToClipBoard("legacyAddress")}
|
||||
icon={"copy"}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="wallet-info-content mt-1 text-left">
|
||||
<Col xs={10} sm={11}>
|
||||
<span>
|
||||
<b>HD Path: </b>
|
||||
<span id="hdpathValue">{_this.state.hdPath}</span>
|
||||
</span>
|
||||
</Col>
|
||||
<Col xs={2} sm={1}>
|
||||
<FontAwesomeIcon
|
||||
className="icon btn-animation"
|
||||
size="lg"
|
||||
onClick={() => _this.copyToClipBoard("hdPath")}
|
||||
icon={"copy"}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Box>
|
||||
</Col>
|
||||
<Col sm={2} />
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
// copy info to clipboard
|
||||
copyToClipBoard(key) {
|
||||
const val = _this.state[key]
|
||||
var textArea = document.createElement("textarea")
|
||||
textArea.value = val //copyText.textContent;
|
||||
document.body.appendChild(textArea)
|
||||
textArea.select()
|
||||
document.execCommand("Copy")
|
||||
textArea.remove()
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// set component state
|
||||
const wallet = _this.props.walletInfo
|
||||
Object.entries(wallet).forEach(([key, value]) => {
|
||||
_this.setState({
|
||||
[key]: value,
|
||||
})
|
||||
})
|
||||
}
|
||||
componentDidUpdate() {
|
||||
// set component state
|
||||
if (_this.props.walletInfo.mnemonic !== _this.state.mnemonic) {
|
||||
const wallet = _this.props.walletInfo
|
||||
Object.entries(wallet).forEach(([key, value]) => {
|
||||
_this.setState({
|
||||
[key]: value,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
WalletInfo.propTypes = {
|
||||
walletInfo: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
export default WalletInfo
|
||||
@@ -0,0 +1,17 @@
|
||||
.wallet-info-content{
|
||||
/* border:0.7px solid var(--main-color); */
|
||||
border-radius: 5px;
|
||||
max-width: 100%;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
margin-right: 0px;
|
||||
margin-left: 0px;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
border-left: none;
|
||||
}
|
||||
.wallet-info-content div{
|
||||
overflow:hidden;
|
||||
white-space:nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@@ -621,6 +621,12 @@ pre tt:after {
|
||||
}
|
||||
}
|
||||
|
||||
.text-right{
|
||||
text-align: right;
|
||||
}
|
||||
.text-left{
|
||||
text-align: left;
|
||||
}
|
||||
.text-center{
|
||||
text-align: center;
|
||||
}
|
||||
@@ -661,7 +667,34 @@ pre tt:after {
|
||||
.mb-3{
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.mr-1{
|
||||
margin-right: 1em;
|
||||
}
|
||||
.mr-2{
|
||||
margin-right: 2em;
|
||||
}
|
||||
.ml-3{
|
||||
margin-right: 3em;
|
||||
}
|
||||
.ml-1{
|
||||
margin-left: 1em;
|
||||
}
|
||||
.ml-2{
|
||||
margin-left: 2em;
|
||||
}
|
||||
.ml-3{
|
||||
margin-left: 3em;
|
||||
}
|
||||
.title-icon{
|
||||
margin-right: 7px;
|
||||
color: var(--main-color);
|
||||
}
|
||||
}
|
||||
|
||||
.icon{
|
||||
cursor: pointer;
|
||||
color: var(--main-color);
|
||||
}
|
||||
.btn-animation:active {
|
||||
box-shadow: 0 5px #666;
|
||||
transform: translateY(4px);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Local storage handler
|
||||
|
||||
|
||||
const localStorageWalletKey = "fullstack-wallet-info"
|
||||
|
||||
// Detect if the app is running in a browser.
|
||||
export const isBrowser = () => typeof window !== "undefined"
|
||||
|
||||
export const getWalletInfo = () =>
|
||||
isBrowser() && window.localStorage.getItem(localStorageWalletKey)
|
||||
? JSON.parse(window.localStorage.getItem(localStorageWalletKey))
|
||||
: {}
|
||||
|
||||
export const setWalletInfo = wallet =>
|
||||
window.localStorage.setItem(localStorageWalletKey, JSON.stringify(wallet))
|
||||
+18
-4
@@ -1,16 +1,30 @@
|
||||
import React from 'react'
|
||||
import React from "react"
|
||||
import { connect } from "react-redux"
|
||||
|
||||
let AdminLTE =
|
||||
typeof window !== `undefined`
|
||||
? require('../components/admin-lte').default
|
||||
? require("../components/admin-lte").default
|
||||
: null
|
||||
const mapStateToProps = ({ walletInfo, bchBalance }) => {
|
||||
return { walletInfo,bchBalance }
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
setWallet: value => dispatch({ type: `SET_WALLET`, value }),
|
||||
updateBalance: value =>dispatch({ type: `UPDATE_BALANCE`, value })
|
||||
}
|
||||
}
|
||||
|
||||
let ConnectedDashboard = AdminLTE
|
||||
? connect(mapStateToProps, mapDispatchToProps)(AdminLTE)
|
||||
: null
|
||||
|
||||
class AdminLTEPage extends React.Component {
|
||||
state = {}
|
||||
|
||||
|
||||
render() {
|
||||
return <>{AdminLTE && <AdminLTE />}</>
|
||||
return <>{ConnectedDashboard && <ConnectedDashboard />}</>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { createStore as reduxCreateStore } from "redux"
|
||||
// Wallet from localStorage
|
||||
import { getWalletInfo, setWalletInfo } from "../components/localWallet"
|
||||
|
||||
const reducer = (state, action) => {
|
||||
// Update walletInfo state property
|
||||
if (action.type === `SET_WALLET`) {
|
||||
setWalletInfo(action.value) // Add wallet to local storage
|
||||
return Object.assign({}, state, {
|
||||
walletInfo: action.value,
|
||||
})
|
||||
}
|
||||
|
||||
// Update bchBalance state property
|
||||
if (action.type === `UPDATE_BALANCE`) {
|
||||
// Convert satoshis to bch
|
||||
const satoshis = action.value
|
||||
const bch = satoshis / 100000000
|
||||
return Object.assign({}, state, {
|
||||
bchBalance: Number(bch.toFixed(8)),
|
||||
})
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
// Wallet info from local storage
|
||||
const localWallet = getWalletInfo()
|
||||
|
||||
const initialState = {
|
||||
walletInfo: localWallet.mnemonic ? localWallet : {},
|
||||
bchBalance: 0,
|
||||
}
|
||||
|
||||
const createStore = () => reduxCreateStore(reducer, initialState)
|
||||
export default createStore
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from "react"
|
||||
import { Provider } from "react-redux"
|
||||
|
||||
import createStore from "./src/redux/createStore"
|
||||
|
||||
// eslint-disable-next-line react/display-name,react/prop-types
|
||||
export default ({ element }) => {
|
||||
// Instantiating store in `wrapRootElement` handler ensures:
|
||||
// - there is fresh store for each SSR page
|
||||
// - it will be called only once in browser, when React mounts
|
||||
const store = createStore()
|
||||
return <Provider store={store}>{element}</Provider>
|
||||
}
|
||||
Reference in New Issue
Block a user