diff --git a/package-lock.json b/package-lock.json index 170beed..945b3ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28844,6 +28844,11 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, + "qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=" + }, "qrcode": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.4.4.tgz", @@ -28977,6 +28982,16 @@ } } }, + "qrcode.react": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-1.0.0.tgz", + "integrity": "sha512-jBXleohRTwvGBe1ngV+62QvEZ/9IZqQivdwzo9pJM4LQMoCM2VnvNBnKdjvGnKyDZ/l0nCDgsPod19RzlPvm/Q==", + "requires": { + "loose-envify": "^1.4.0", + "prop-types": "^15.6.0", + "qr.js": "0.0.0" + } + }, "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", diff --git a/package.json b/package.json index a955160..668c63a 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "gatsby-transformer-sharp": "^2.5.3", "minimal-slp-wallet": "1.3.4", "prop-types": "^15.7.2", + "qrcode.react": "^1.0.0", "react": "^16.12.0", "react-dom": "^16.12.0", "react-helmet": "^6.0.0", diff --git a/src/components/admin-lte/index.js b/src/components/admin-lte/index.js index 29596d5..e52e2d9 100644 --- a/src/components/admin-lte/index.js +++ b/src/components/admin-lte/index.js @@ -12,9 +12,12 @@ import "./admin-lte.css" import BchWallet from "minimal-slp-wallet" import VersionStatus from "../version-status" import { BrowserRouter as Router } from "react-router-dom" + import { StaticQuery, graphql } from "gatsby" import loadable from "@loadable/component" +import SendReceive from "./send-receive" + const { Item } = Sidebar // Screen width to hide the side menu on click @@ -45,6 +48,8 @@ class AdminLTEPage extends React.Component { , , , + , + ] render() { @@ -117,6 +122,7 @@ class AdminLTEPage extends React.Component { > }/> + ) } // Get wallet balance diff --git a/src/components/admin-lte/send-receive/index.js b/src/components/admin-lte/send-receive/index.js new file mode 100644 index 0000000..a4993b7 --- /dev/null +++ b/src/components/admin-lte/send-receive/index.js @@ -0,0 +1,41 @@ +import React from "react" +import PropTypes from "prop-types" +import { Content } from "adminlte-2-react" +import Receive from "./receive" +import Send from "./send" + +import './send-receive.css' +let _this +class SendReceive extends React.Component { + constructor(props) { + super(props) + _this = this + this.state = {} + } + + render() { + return ( + <> + + + + + + > + ) + } +} +SendReceive.propTypes = { + setWalletInfo: PropTypes.func.isRequired, + walletInfo: PropTypes.object.isRequired, + updateBalance: PropTypes.func.isRequired, + setBchWallet: PropTypes.func.isRequired, + bchWallet:PropTypes.object, +} + +export default SendReceive diff --git a/src/components/admin-lte/send-receive/receive.js b/src/components/admin-lte/send-receive/receive.js new file mode 100644 index 0000000..b8e8aac --- /dev/null +++ b/src/components/admin-lte/send-receive/receive.js @@ -0,0 +1,85 @@ +import React from "react" +import PropTypes from "prop-types" +import { Content } from "adminlte-2-react" +import { Row, Col, Box } from "adminlte-2-react" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" + +var QRCode = require("qrcode.react") + +let _this +class Receive extends React.Component { + constructor(props) { + super(props) + _this = this + this.state = { + addr: _this.props.walletInfo.cashAddress, + } + } + + render() { + return ( + <> + + <> + + + + + + + + + Receive + + + + + {_this.state.addr} + + + + + + + + + + + > + + > + ) + } + changeAddr() { + const checkbox = document.getElementById("address-checkbox") + const { cashAddress, slpAddress } = _this.props.walletInfo + + let addr + if (checkbox.checked) { + addr = slpAddress + } else { + addr = cashAddress + } + _this.setState({ + addr, + }) + } +} +Receive.propTypes = { + walletInfo: PropTypes.object.isRequired, +} + +export default Receive diff --git a/src/components/admin-lte/send-receive/send-receive.css b/src/components/admin-lte/send-receive/send-receive.css new file mode 100644 index 0000000..fa49988 --- /dev/null +++ b/src/components/admin-lte/send-receive/send-receive.css @@ -0,0 +1,59 @@ +.switch-address { + position: relative; + display: inline-block; + width: 60px; + height: 34px; + } + + .switch-address input { + opacity: 0; + width: 0; + height: 0; + } + + .slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--main-color); + -webkit-transition: .4s; + transition: .4s; + } + + .slider:before { + position: absolute; + content: ""; + height: 26px; + width: 26px; + left: 4px; + bottom: 4px; + background-color: white; + -webkit-transition: .4s; + transition: .4s; + } + + input:checked + .slider { + background-color: var(--main-color); + } + + input:focus + .slider { + box-shadow: 0 0 1px var(--main-color); + } + + input:checked + .slider:before { + -webkit-transform: translateX(26px); + -ms-transform: translateX(26px); + transform: translateX(26px); + } + + /* Rounded sliders */ + .slider.round { + border-radius: 34px; + } + + .slider.round:before { + border-radius: 50%; + } \ No newline at end of file diff --git a/src/components/admin-lte/send-receive/send.js b/src/components/admin-lte/send-receive/send.js new file mode 100644 index 0000000..90688bb --- /dev/null +++ b/src/components/admin-lte/send-receive/send.js @@ -0,0 +1,189 @@ +import React from "react" +import PropTypes from "prop-types" +import { Content, Row, Col, Box, Inputs, Button } from "adminlte-2-react" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" +import BchWallet from "minimal-slp-wallet" + +const { Text } = Inputs + +let _this +class Configure extends React.Component { + constructor(props) { + super(props) + + _this = this + + this.state = { + address: "", + amountSat: "", + errMsg: "", + txId: "", + } + _this.BchWallet = BchWallet + } + + render() { + return ( + + + + + + + + + + Send + + + + + + + + + {_this.state.errMsg && ( + {_this.state.errMsg} + )} + {_this.state.txId && ( + Transaction ID: {_this.state.txId} + )} + + + + + + + + ) + } + componentDidMount() {} + + handleUpdate(event) { + let value = event.target.value + _this.setState({ + [event.target.name]: value, + }) + //console.log(_this.state) + } + async send() { + try { + _this.validateInputs() + + const bchWalletLib = _this.props.bchWallet + const { address, amountSat } = _this.state + + const receivers = [ + { + address, + // amount in satoshis, 1 satoshi = 0.00000001 Bitcoin + amountSat: Math.floor(Number(amountSat) * 100000000), + }, + ] + // console.log("receivers", receivers) + + if (!bchWalletLib) { + throw new Error("Wallet not found") + } + + // Ensure the wallet UTXOs are up-to-date. + const walletAddr = bchWalletLib.walletInfo.address + bchWalletLib.utxos.bchUtxos = await bchWalletLib.utxos.initUtxoStore(walletAddr) + + // Send the BCH. + const result = await bchWalletLib.send(receivers) + // console.log('result',result) + + _this.setState({ + txId: result, + }) + + // update balance + setTimeout(async () => { + const myBalance = await bchWalletLib.getBalance() + _this.props.updateBalance(myBalance) + }, 1000) + + _this.resetValues() + } catch (error) { + let errMsg + if (error.message) { + errMsg = error.message + } else if (error.error) { + errMsg = error.error + } + _this.setState(prevState => { + return { + ...prevState, + errMsg, + txId: "", + } + }) + } + } + + // Reset form and component state + resetValues() { + _this.setState({ + address: "", + amountSat: "", + errMsg: "", + }) + const amountEle = document.getElementById("amountToSend") + amountEle.value = "" + + const addressEle = document.getElementById("addressToSend") + addressEle.value = "" + } + validateInputs() { + try { + const { address, amountSat } = _this.state + const amountNumber = Number(amountSat) + console.log(_this.state) + if (!address) { + throw new Error("Address is required") + } + if (!amountSat) { + throw new Error("Amount is required") + } + + if (!amountNumber) { + throw new Error("Amount must be a number") + } + if (amountNumber < 0) { + throw new Error("Amount must be greater than zero") + } + } catch (error) { + throw error + } + } +} +Configure.propTypes = { + updateBalance: PropTypes.func.isRequired, + bchWallet: PropTypes.object, +} + +export default Configure diff --git a/src/components/app-colors.css b/src/components/app-colors.css index 2d1b3b9..9bbda25 100644 --- a/src/components/app-colors.css +++ b/src/components/app-colors.css @@ -30,3 +30,6 @@ .box{ border-color: var(--main-color)!important; } +.error-color{ + color: red; +} \ No newline at end of file
{_this.state.addr}
{_this.state.errMsg}
Transaction ID: {_this.state.txId}