Merge branch 'master' into dh-redux-devtool

This commit is contained in:
Chris Troutner
2021-05-21 05:51:20 -07:00
11 changed files with 252 additions and 195 deletions
+2
View File
@@ -19,3 +19,5 @@ 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.
Have Fun!
+1 -1
View File
@@ -46,7 +46,7 @@ class JsonWebTokens extends React.Component {
id='jwt'
name='JWT'
placeholder='Enter FullStack.cash JWT'
label='FullStack.cash JWT'
label='Enter FullStack.cash JWT to increase rate limits.'
labelPosition='above'
onChange={_this.handleUpdate}
/>
@@ -211,13 +211,11 @@ class Send extends React.Component {
async getMaxAmount () {
try {
const bchWalletLib = _this.props.bchWallet
// Ensure the wallet UTXOs are up-to-date.
const walletAddr = bchWalletLib.walletInfo.address
await bchWalletLib.utxos.initUtxoStore(walletAddr)
const utxos = bchWalletLib.utxos.bchUtxos
const utxos = bchWalletLib.utxos.utxoStore.bchUtxos
if (!utxos.length) {
throw new Error('No BCH Utxos to spend!')
}
+22 -13
View File
@@ -91,17 +91,21 @@ class Tokens extends React.Component {
<>
<Row>
{_this.state.tokens.map((val, i) => {
return (
<Col sm={4} key={`token-${i}`}>
<TokenCard
key={`token-${i}`}
id={`token-${i}`}
token={val}
showToken={_this.showToken}
selectToken={_this.selectToken}
/>
</Col>
)
if (val.qty > 0) {
return (
<Col sm={4} key={`token-${i}`}>
<TokenCard
key={`token-${i}`}
id={`token-${i}`}
token={val}
showToken={_this.showToken}
selectToken={_this.selectToken}
/>
</Col>
)
} else {
return <span key={`token-${i}`} />
}
})}
</Row>
</>
@@ -109,6 +113,7 @@ class Tokens extends React.Component {
</Content>
)}
<TokenModal
bchWallet={_this.props.bchWallet}
token={
_this.state.selectedTokenToView
? _this.state.selectedTokenToView
@@ -116,6 +121,7 @@ class Tokens extends React.Component {
}
handleOnHide={_this.onHandleToggleModal}
show={_this.state.showModal}
explorerURL={_this.state.explorerURL}
/>
</>
)
@@ -198,10 +204,13 @@ class Tokens extends React.Component {
ele.scrollIntoView({ behavior: 'smooth' })
}
onHandleToggleModal () {
onHandleToggleModal (refresh = null) {
_this.setState({
showModal: !_this.state.showModal
})
if (refresh) {
_this.handleGetTokens(true)
}
}
handleError (error) {
@@ -247,7 +256,7 @@ class Tokens extends React.Component {
let explorerURL
if (bchjs.restURL.includes('abc.fullstack')) {
explorerURL = 'https://explorer.bitcoinabc.org/tx'
explorerURL = 'https://explorer.be.cash/tx'
} else {
explorerURL = 'https://explorer.bitcoin.com/bch/tx'
}
+15 -7
View File
@@ -139,10 +139,23 @@ class SendTokens extends React.Component {
// console.log(_this.state)
}
// Sets the qty property with
// the corresponding token decimals
floorQty (qty, decimals) {
try {
const a = qty * Math.pow(10, decimals)
const b = Math.floor(a)
const result = b / Math.pow(10, decimals)
return result
} catch (error) {
console.warn(error)
}
}
async handleSendMax () {
const { qty } = _this.props.selectedToken
const { qty, decimals } = _this.props.selectedToken
_this.setState({
amountSat: qty
amountSat: _this.floorQty(qty, decimals)
})
}
@@ -182,11 +195,6 @@ class SendTokens extends React.Component {
const walletAddr = bchWalletLib.walletInfo.address
await bchWalletLib.utxos.initUtxoStore(walletAddr)
// For some reason, the utxo categories do not get populated, so we have
// to do it manually.
bchWalletLib.utxos.bchUtxos = await bchWalletLib.utxos.getBchUtxos()
bchWalletLib.utxos.tokenUtxos = await bchWalletLib.utxos.getTokenUtxos()
// Used for debugging.
// console.log(`receiver: ${JSON.stringify(receiver, null, 2)}`)
// console.log(
@@ -13,7 +13,7 @@ class TokenCard extends React.Component {
render () {
const token = _this.props.token
console.log(`token: ${JSON.stringify(token, null, 2)}`)
// console.log(`token: ${JSON.stringify(token, null, 2)}`)
return (
<>
+194 -134
View File
@@ -11,7 +11,10 @@ class TokenModal extends React.Component {
_this = this
this.state = {
copySuccess: '',
isBurnView: false
isBurnView: false,
txId: '',
errMsg: '',
inFetch: false
}
this.modalFooter = (
@@ -36,6 +39,15 @@ class TokenModal extends React.Component {
/>
</>
)
this.onDoneFooter = (
<>
<Button
text='Close'
pullLeft
onClick={() => this.handleBurnAll(false)}
/>
</>
)
}
render () {
@@ -46,7 +58,11 @@ class TokenModal extends React.Component {
title={_this.state.isBurnView ? `Burn All ${token.name}` : token.name}
modal
modalFooter={
_this.state.isBurnView ? this.burnFooter : this.modalFooter
!_this.state.isBurnView
? this.modalFooter
: _this.state.txId || _this.state.errMsg
? this.onDoneFooter
: this.burnFooter
}
show={_this.props.show}
modalCloseButton
@@ -54,138 +70,159 @@ class TokenModal extends React.Component {
>
<Row>
<Col sm={12}>
{_this.state.isBurnView
? (
{_this.state.isBurnView && !_this.state.txId && (
<Box loaded={!_this.state.inFetch} className='border-none'>
<p>
Are you sure you want to burn {`${token.qty} `}
tokens?
</p>
)
: (
<Box className=' border-none '>
<Row>
<Col
sm={12}
className='text-center tokenModal-info-container'
>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>TokenId:</b>
</Col>
<Col xs={9} sm={7}>
{token.tokenId}
</Col>
<Col
xs={3}
sm={2}
className={
</Box>
)}
{_this.state.isBurnView && _this.state.txId && (
<div className='text-center '>
<p>Transaction ID:</p>
<a
target='_blank'
rel='noopener noreferrer'
href={`${_this.props.explorerURL}/${_this.state.txId}`}
>
{_this.state.txId}
</a>
</div>
)}
{_this.state.isBurnView && _this.state.errMsg && (
<div className='text-center'>
<p className='error-color'> {_this.state.errMsg}</p>
</div>
)}
{!_this.state.isBurnView && (
<Box className=' border-none '>
<Row>
<Col
sm={12}
className='text-center tokenModal-info-container'
>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>TokenId:</b>
</Col>
<Col xs={9} sm={7}>
{token.tokenId}
</Col>
<Col
xs={3}
sm={2}
className={
_this.state.copySuccess ? 'nopadding' : ''
}
>
{_this.state.copySuccess === 'tokenId'
? (
<div className='copied-text'>
<span>Copied!</span>
</div>
)
: (
<FontAwesomeIcon
className='icon btn-animation'
style={{ cssFloat: 'right' }}
size='lg'
onClick={() =>
_this.copyToClipBoard('tokenId')}
icon='copy'
/>
)}
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>URL:</b>
</Col>
<Col xs={12} sm={9}>
<a
href={`http://${token.url}`}
target='_blank'
rel='noopener noreferrer'
>
{_this.state.copySuccess === 'tokenId'
? (
<div className='copied-text'>
<span>Copied!</span>
</div>
)
: (
<FontAwesomeIcon
className='icon btn-animation'
style={{ cssFloat: 'right' }}
size='lg'
onClick={() =>
_this.copyToClipBoard('tokenId')}
icon='copy'
/>
)}
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>URL:</b>
</Col>
<Col xs={12} sm={9}>
<a
href={`http://${token.url}`}
target='_blank'
rel='noopener noreferrer'
>
{token.url}
</a>
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>Ticker:</b>
</Col>
<Col xs={12} sm={9}>
{token.ticker}
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>Name:</b>
</Col>
<Col xs={12} sm={9}>
{token.name}
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>Balance:</b>
</Col>
<Col xs={12} sm={9}>
{token.qty}
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>Decimals:</b>
</Col>
<Col xs={12} sm={9}>
{token.decimals}
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>TokenType:</b>
</Col>
<Col xs={12} sm={9}>
{token.tokenType}
</Col>
</Row>
</Col>
</Row>
</Col>
</Row>
</Box>
)}
{token.url}
</a>
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>Ticker:</b>
</Col>
<Col xs={12} sm={9}>
{token.ticker}
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>Name:</b>
</Col>
<Col xs={12} sm={9}>
{token.name}
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>Balance:</b>
</Col>
<Col xs={12} sm={9}>
{token.qty}
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>Decimals:</b>
</Col>
<Col xs={12} sm={9}>
{token.decimals}
</Col>
</Row>
</Col>
</Row>
<Row className='tokenModal-info-content mt-1 text-left'>
<Col xs={12}>
<Row>
<Col xs={12} sm={3}>
<b>TokenType:</b>
</Col>
<Col xs={12} sm={9}>
{token.tokenType}
</Col>
</Row>
</Col>
</Row>
</Col>
</Row>
</Box>
)}
</Col>
</Row>
</Content>
@@ -224,19 +261,24 @@ class TokenModal extends React.Component {
}
handleModal () {
_this.props.handleOnHide()
// if txId exist refresh tokens on close
_this.props.handleOnHide(_this.state.txId)
setTimeout(() => {
_this.setState({
isBurnView: false
isBurnView: false,
txId: '',
errMsg: '',
inFetch: false
})
}, 200)
}
handleBurnAll (isConfirmed) {
async handleBurnAll (isConfirmed) {
try {
// Dismiss
if (!isConfirmed) {
_this.hideModal()
_this.handleModal()
return
}
@@ -244,13 +286,31 @@ class TokenModal extends React.Component {
* BURN ALL
*
*/
console.log('Hello Word')
} catch (error) {}
_this.setState({
inFetch: true
})
const { bchWallet, token } = _this.props
const result = await bchWallet.burnAll(token.tokenId)
console.log('burn txid: ', result)
_this.setState({
txId: result,
inFetch: false
})
} catch (error) {
console.warn(error)
_this.setState({
errMsg: error.message,
inFetch: false
})
}
}
}
TokenModal.propTypes = {
token: PropTypes.object.isRequired,
show: PropTypes.bool.isRequired,
handleOnHide: PropTypes.func.isRequired
handleOnHide: PropTypes.func.isRequired,
bchWallet: PropTypes.object, // get minimal-slp-wallet instance
explorerURL: PropTypes.string
}
export default TokenModal
+4 -7
View File
@@ -4,10 +4,7 @@ import { Row, Col, Box, Button, Inputs } from 'adminlte-2-react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
// import BchWallet from 'minimal-slp-wallet'
const BchWallet =
typeof window !== 'undefined'
? window.SlpWallet
: null
const BchWallet = typeof window !== 'undefined' ? window.SlpWallet : null
const { Text } = Inputs
@@ -50,7 +47,7 @@ class ImportWallet extends React.Component {
<Col sm={12} className='text-center mt-2 mb-2'>
<Row className='flex justify-content-center'>
<Col sm={8}>
<div>
<form autoComplete='off'>
<Text
id='import-mnemonic'
name='mnemonic'
@@ -59,7 +56,7 @@ class ImportWallet extends React.Component {
labelPosition='above'
onChange={_this.handleUpdate}
/>
</div>
</form>
</Col>
</Row>
</Col>
@@ -151,7 +148,7 @@ class ImportWallet extends React.Component {
let currentRate
if (bchjs.restURL.includes('abc.fullstack')) {
currentRate = await bchjs.Price.getBchaUsd() * 100
currentRate = (await bchjs.Price.getBchaUsd()) * 100
} else {
// BCHN price.
currentRate = (await bchjs.Price.getUsd()) * 100
@@ -147,29 +147,6 @@ class WalletInfo extends React.Component {
)}
</Col>
</Row>
<Row className='wallet-info-content mt-1 text-left'>
<Col xs={8} sm={9} lg={10}>
<span>
<b>Address: </b> {_this.state.address}
</span>
</Col>
<Col xs={4} sm={3} lg={2} className='text-right'>
{_this.state.copySuccess === 'address'
? (
<div className='copied-text'>
<span>Copied!</span>
</div>
)
: (
<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={8} sm={9} lg={10}>
<span>
+1 -1
View File
@@ -51,7 +51,7 @@ class Footer extends React.Component {
this.setState({
ipfsHash: hash,
ipfsHashLink: `https://ipfs-gateway.fullstack.cash/ipfs/${hash}`
ipfsHashLink: `https://ipfs.io/ipfs/${hash}`
})
}
+11 -5
View File
@@ -3,17 +3,23 @@ import React from 'react'
class VersionStatus extends React.Component {
constructor (props) {
super(props)
this.state = {}
this.state = {
show: false
}
}
render () {
return (
<>
<div className='version-status'>
<div>
<p><b>Warning: Open Alpha - things will break</b></p>
{this.state.show && (
<div className='version-status'>
<div>
<p>
<b>Warning: Open Beta - this app is under active develpment.</b>
</p>
</div>
</div>
</div>
)}
</>
)
}