From 839a6a37282e5c0856a1e380ebf018e771e8b5f6 Mon Sep 17 00:00:00 2001
From: Daniel Gonzalez
Date: Tue, 30 Jun 2020 02:24:48 -0400
Subject: [PATCH 1/3] feat(send/receive): Started the send/receive
implementation
---
package-lock.json | 15 ++
package.json | 1 +
src/components/admin-lte/index.js | 12 ++
.../admin-lte/send-receive/index.js | 41 ++++++
.../admin-lte/send-receive/receive.js | 85 +++++++++++
.../admin-lte/send-receive/send-receive.css | 59 ++++++++
src/components/admin-lte/send-receive/send.js | 134 ++++++++++++++++++
7 files changed, 347 insertions(+)
create mode 100644 src/components/admin-lte/send-receive/index.js
create mode 100644 src/components/admin-lte/send-receive/receive.js
create mode 100644 src/components/admin-lte/send-receive/send-receive.css
create mode 100644 src/components/admin-lte/send-receive/send.js
diff --git a/package-lock.json b/package-lock.json
index d64bbe2..139fb67 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -28843,6 +28843,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",
@@ -28976,6 +28981,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 02313fe..15d7560 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 22f5650..3c48c4f 100644
--- a/src/components/admin-lte/index.js
+++ b/src/components/admin-lte/index.js
@@ -13,6 +13,7 @@ import "./admin-lte.css"
import BchWallet from "minimal-slp-wallet"
import VersionStatus from "../version-status"
import { BrowserRouter as Router } from "react-router-dom"
+import SendReceive from "./send-receive"
const { Item } = Sidebar
// Screen width to hide the side menu on click
@@ -39,6 +40,8 @@ class AdminLTEPage extends React.Component {
,
,
,
+ ,
+
]
render() {
@@ -84,6 +87,15 @@ class AdminLTEPage extends React.Component {
/>
)}
{_this.state.section === "Audit" && }
+ {_this.state.section === "Send/Receive" && (
+
+ )}
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..d13ac1b
--- /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, Inputs } 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..48e9b51
--- /dev/null
+++ b/src/components/admin-lte/send-receive/send.js
@@ -0,0 +1,134 @@
+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: "",
+ }
+ _this.BchWallet = BchWallet
+
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+
+
+
+ Send
+
+
+
+
+
+
+
+
+ {_this.state.errMsg && (
+ {_this.state.errMsg}
+ )}
+
+
+
+
+
+
+
+ )
+ }
+ componentDidMount() {}
+
+ handleUpdate(event) {
+ let value = event.target.value
+ _this.setState({
+ [event.target.name]: value,
+ })
+ //console.log(_this.state)
+ }
+ async send() {
+ try {
+ const bchWalletLib = _this.props.bchWallet
+ const { address ,amountSat} = _this.state
+ const receivers = [
+ {
+ address,
+ // amount in satoshis, 1 satoshi = 0.00000001 Bitcoin
+ amountSat :Number(amountSat)
+ }
+ ];
+ // Update instance with JWT
+ if (!bchWalletLib) {
+ throw new Error("Wallet not found")
+ }
+
+
+ await bchWalletLib.walletInfoPromise
+
+ console.log('receivers',receivers)
+
+ const result = await bchWalletLib.send(receivers)
+ console.log("result", result)
+
+ } catch (error) {
+ console.warn(error)
+ _this.setState({
+ errMsg: error.message,
+ })
+ }
+ }
+
+ // Reset form and component state
+ resetValues() {
+ _this.setState({
+ address: "",
+ errMsg: "",
+ })
+ }
+}
+Configure.propTypes = {
+ updateBalance: PropTypes.func.isRequired,
+ bchWallet: PropTypes.object,
+}
+
+export default Configure
From 29fc2e11b711dfde1c34d5ea2517cd99b12b4cc0 Mon Sep 17 00:00:00 2001
From: Daniel Gonzalez
Date: Wed, 1 Jul 2020 02:37:12 -0400
Subject: [PATCH 2/3] feat(send): Finished the bch send implementation
---
.../admin-lte/send-receive/receive.js | 4 +-
src/components/admin-lte/send-receive/send.js | 103 ++++++++++++++----
src/components/app-colors.css | 3 +
3 files changed, 88 insertions(+), 22 deletions(-)
diff --git a/src/components/admin-lte/send-receive/receive.js b/src/components/admin-lte/send-receive/receive.js
index d13ac1b..b8e8aac 100644
--- a/src/components/admin-lte/send-receive/receive.js
+++ b/src/components/admin-lte/send-receive/receive.js
@@ -1,7 +1,7 @@
import React from "react"
import PropTypes from "prop-types"
import { Content } from "adminlte-2-react"
-import { Row, Col, Box, Inputs } from "adminlte-2-react"
+import { Row, Col, Box } from "adminlte-2-react"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
var QRCode = require("qrcode.react")
@@ -44,7 +44,7 @@ class Receive extends React.Component {
fgColor={"#333"}
/>
{_this.state.addr}
-
)}
+ {_this.state.txId &&(
+ Transaction ID: {_this.state.txId}
+ )}
@@ -88,32 +91,64 @@ class Configure extends React.Component {
}
async send() {
try {
+ _this.validateInputs()
+
const bchWalletLib = _this.props.bchWallet
- const { address ,amountSat} = _this.state
+ const { address, amountSat } = _this.state
+
const receivers = [
{
- address,
- // amount in satoshis, 1 satoshi = 0.00000001 Bitcoin
- amountSat :Number(amountSat)
- }
- ];
- // Update instance with JWT
- if (!bchWalletLib) {
- throw new Error("Wallet not found")
- }
-
-
- await bchWalletLib.walletInfoPromise
-
+ address,
+ // amount in satoshis, 1 satoshi = 0.00000001 Bitcoin
+ amountSat: Number(amountSat) * 100000000,
+ },
+ ]
console.log('receivers',receivers)
+ if (!bchWalletLib) {
+ throw new Error("Wallet not found")
+ }
+
+
+
+ // The following line of code solved the 'UTXOS list empty' problem
+ // The Function below is called at creating an instance of the library
+ // https://github.com/Permissionless-Software-Foundation/minimal-slp-wallet/blob/master/lib/utxos.js#L88-L97
+ //
+ // This function stores the utxos in the variable bchUtxos
+ // I don't find the reason why the instance of the library returns an empty array
+ // console.log('bch utxos ', bchWalletLib.utxos.bchUtxos )
+
+ bchWalletLib.utxos.bchUtxos = await bchWalletLib.utxos.getBchUtxos()
const result = await bchWalletLib.send(receivers)
- console.log("result", result)
+ // console.log('result',result)
- } catch (error) {
- console.warn(error)
_this.setState({
- errMsg: error.message,
+ 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:""
+ }
})
}
}
@@ -122,8 +157,36 @@ class Configure extends React.Component {
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 = {
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
From 8c727081aecaf5a19128eb0e29125556e9549fa5 Mon Sep 17 00:00:00 2001
From: Chris Troutner
Date: Wed, 1 Jul 2020 18:45:01 -0700
Subject: [PATCH 3/3] fix(rounding): Fixing rounding bug
---
src/components/admin-lte/send-receive/send.js | 32 +++++++------------
1 file changed, 12 insertions(+), 20 deletions(-)
diff --git a/src/components/admin-lte/send-receive/send.js b/src/components/admin-lte/send-receive/send.js
index 49056ee..90688bb 100644
--- a/src/components/admin-lte/send-receive/send.js
+++ b/src/components/admin-lte/send-receive/send.js
@@ -68,7 +68,7 @@ class Configure extends React.Component {
{_this.state.errMsg && (
{_this.state.errMsg}
)}
- {_this.state.txId &&(
+ {_this.state.txId && (
Transaction ID: {_this.state.txId}
)}
@@ -95,31 +95,25 @@ class Configure extends React.Component {
const bchWalletLib = _this.props.bchWallet
const { address, amountSat } = _this.state
-
+
const receivers = [
{
address,
// amount in satoshis, 1 satoshi = 0.00000001 Bitcoin
- amountSat: Number(amountSat) * 100000000,
+ amountSat: Math.floor(Number(amountSat) * 100000000),
},
]
- console.log('receivers',receivers)
+ // 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)
-
- // The following line of code solved the 'UTXOS list empty' problem
- // The Function below is called at creating an instance of the library
- // https://github.com/Permissionless-Software-Foundation/minimal-slp-wallet/blob/master/lib/utxos.js#L88-L97
- //
- // This function stores the utxos in the variable bchUtxos
- // I don't find the reason why the instance of the library returns an empty array
- // console.log('bch utxos ', bchWalletLib.utxos.bchUtxos )
-
- bchWalletLib.utxos.bchUtxos = await bchWalletLib.utxos.getBchUtxos()
-
+ // Send the BCH.
const result = await bchWalletLib.send(receivers)
// console.log('result',result)
@@ -131,23 +125,21 @@ class Configure extends React.Component {
setTimeout(async () => {
const myBalance = await bchWalletLib.getBalance()
_this.props.updateBalance(myBalance)
-
}, 1000)
_this.resetValues()
} catch (error) {
let errMsg
- if(error.message){
+ if (error.message) {
errMsg = error.message
- }else if(error.error){
+ } else if (error.error) {
errMsg = error.error
-
}
_this.setState(prevState => {
return {
...prevState,
errMsg,
- txId:""
+ txId: "",
}
})
}