feat(rate-limits): Display rate limit error to the users

This commit is contained in:
Daniel Gonzalez
2020-07-15 18:56:05 -04:00
parent 8b0efdf6da
commit d88188c3b1
6 changed files with 244 additions and 154 deletions
+9 -11
View File
@@ -8,7 +8,7 @@ const { Text } = Inputs
let _this
class Configure extends React.Component {
constructor (props) {
constructor(props) {
super(props)
_this = this
@@ -21,7 +21,7 @@ class Configure extends React.Component {
_this.BchWallet = BchWallet
}
render () {
render() {
return (
<Content>
<Row>
@@ -113,11 +113,11 @@ class Configure extends React.Component {
)
}
componentDidMount () {
componentDidMount() {
_this.setJwt()
}
setJwt () {
setJwt() {
const { JWT } = _this.props.walletInfo
if (JWT) {
const jwtElem = document.getElementById('jwt')
@@ -125,27 +125,26 @@ class Configure extends React.Component {
}
}
handleUpdate (event) {
handleUpdate(event) {
const value = event.target.value
_this.setState({
[event.target.name]: value
})
console.log(_this.state.JWT)
}
async handleUpdateJWT () {
async handleUpdateJWT() {
try {
const { mnemonic, selectedServer } = _this.props.walletInfo
const apiToken = _this.state.JWT
// Update instance with JWT
if (mnemonic && apiToken) {
if (mnemonic) {
const bchjsOptions = { apiToken: apiToken }
if (selectedServer) {
bchjsOptions.restURL = selectedServer
}
console.log('bchjs options : ', bchjsOptions)
//console.log('bchjs options : ', bchjsOptions)
const bchWalletLib = new _this.BchWallet(mnemonic, bchjsOptions)
// Update bchjs instances of minimal-slp-wallet libraries
@@ -161,7 +160,6 @@ class Configure extends React.Component {
_this.props.setWalletInfo(walletInfo)
} catch (error) {
console.warn(error)
_this.setState({
errMsg: error.message
})
@@ -169,7 +167,7 @@ class Configure extends React.Component {
}
// Reset form and component state
resetValues () {
resetValues() {
_this.setState({
JWT: '',
errMsg: ''
+39 -19
View File
@@ -18,7 +18,8 @@ class Send extends React.Component {
amountSat: '',
errMsg: '',
txId: '',
showScan: false
showScan: false,
inFetch: false
}
_this.BchWallet = BchWallet
}
@@ -30,7 +31,9 @@ class Send extends React.Component {
<Row>
<Col sm={2} />
<Col sm={8}>
<Box className='hover-shadow border-none mt-2'>
<Box
loaded={!_this.state.inFetch}
className='hover-shadow border-none mt-2'>
<Row>
<Col sm={12} className='text-center'>
<h1>
@@ -102,7 +105,6 @@ class Send extends React.Component {
_this.setState({
[event.target.name]: value
})
// console.log(_this.state)
}
async handleSend () {
@@ -124,6 +126,9 @@ class Send extends React.Component {
if (!bchWalletLib) {
throw new Error('Wallet not found')
}
_this.setState({
inFetch:true
})
// Ensure the wallet UTXOs are up-to-date.
const walletAddr = bchWalletLib.walletInfo.address
@@ -147,19 +152,8 @@ class Send extends React.Component {
_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: ''
}
})
_this.handleError(error)
}
}
@@ -168,7 +162,8 @@ class Send extends React.Component {
_this.setState({
address: '',
amountSat: '',
errMsg: ''
errMsg: '',
inFetch: false
})
const amountEle = document.getElementById('amountToSend')
amountEle.value = ''
@@ -180,7 +175,6 @@ class Send extends React.Component {
validateInputs () {
const { address, amountSat } = _this.state
const amountNumber = Number(amountSat)
console.log(_this.state)
if (!address) {
throw new Error('Address is required')
@@ -255,7 +249,33 @@ class Send extends React.Component {
}
}
componentDidMount () {}
handleError(error){
//console.error(error)
let errMsg = ''
if (error.message) {
errMsg = error.message
}
if (error.error) {
if (error.error.match('rate limits')) {
errMsg = <span>
Rate limits exceeded, increase rate limits with a JWT token from
<a style={{marginLeft:'5px'}}
target="_blank"
href="https://fullstack.cash">FullStack.cash</a>
</span>
} else {
errMsg = error.error
}
}
_this.setState(prevState => {
return {
...prevState,
errMsg,
txId: '',
inFetch:false
}
})
}
}
Send.propTypes = {
updateBalance: PropTypes.func.isRequired,
+103 -80
View File
@@ -9,7 +9,7 @@ import SendTokens from './send-tokens'
let _this
class Tokens extends React.Component {
constructor (props) {
constructor(props) {
super(props)
_this = this
this.state = {
@@ -17,13 +17,13 @@ class Tokens extends React.Component {
selectedTokenToView: '',
showModal: false,
inFetch: true,
onEmptyTokensMsg: 'No tokens found on this wallet..',
errMsg: '',
selectedTokenToSend: '',
showForm: false
}
}
render () {
render() {
const { JWT } = _this.props.walletInfo
return (
@@ -46,59 +46,59 @@ class Tokens extends React.Component {
<img alt='Loading...' src={Spinner} width={100} />
</div>
) : (
<Content>
{!JWT && (
<Box padding='true' className='container-nofound'>
<Row>
<Col xs={12}>
<FontAwesomeIcon
className='icon btn-animation'
size='lg'
icon='exclamation-triangle'
/>
</Col>
<Content>
{!JWT && (
<Box padding='true' className='container-nofound'>
<Row>
<Col xs={12}>
<FontAwesomeIcon
className='icon btn-animation'
size='lg'
icon='exclamation-triangle'
/>
</Col>
<Col xs={12}>
<em>
You don't have a registered JWT, you could encounter
errors viewing some of your tokens.
<Col xs={12}>
<em>
You don't have a registered JWT, you could encounter
errors viewing some of your tokens.
</em>
</Col>
</Row>
</Box>
)}
<br />
{!_this.state.tokens.length && (
<Box padding='true' className='container-nofound'>
<Row>
<Col xs={12}>
<em>{_this.state.onEmptyTokensMsg}</em>
</Col>
</Row>
</Box>
)}
</Col>
</Row>
</Box>
)}
<br />
{_this.state.errMsg && (
<Box padding='true' className='container-nofound'>
<Row>
<Col xs={12}>
<em>{_this.state.errMsg}</em>
</Col>
</Row>
</Box>
)}
{_this.state.tokens.length > 0 && (
<>
<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>
)
})}
</Row>
</>
)}
</Content>
)}
{_this.state.tokens.length > 0 && (
<>
<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>
)
})}
</Row>
</>
)}
</Content>
)}
<TokenModal
token={
_this.state.selectedTokenToView
@@ -112,58 +112,54 @@ class Tokens extends React.Component {
)
}
onHandleForm () {
onHandleForm() {
_this.setState({
showForm: !_this.state.showForm
})
}
async getTokens () {
async getTokens() {
_this.setState({
inFetch: true
})
const { mnemonic } = _this.props.walletInfo
const bchWallet = _this.props.bchWallet
let tokens = []
let { onEmptyTokensMsg } = _this.state
if (mnemonic && bchWallet) {
try {
await bchWallet.walletInfoPromise
tokens = await bchWallet.listTokens()
} catch (error) {
console.error(error)
if (error.error) {
if (error.error.match('rate limits')) onEmptyTokensMsg = error.error
}
if (error.message) {
onEmptyTokensMsg = error.message
}
try {
if (!mnemonic || !bchWallet)
throw new Error('You need to create or import a wallet first, to view tokens')
await bchWallet.walletInfoPromise
tokens = await bchWallet.listTokens()
if (!tokens.length) {
throw new Error('No tokens found on this wallet.')
}
} else {
onEmptyTokensMsg =
'You need to create or import a wallet first, to view tokens'
_this.setState({
tokens,
inFetch: false,
})
} catch (error) {
_this.handleError(error)
}
_this.setState({
tokens,
inFetch: false,
onEmptyTokensMsg
})
}
async componentDidMount () {
async componentDidMount() {
await _this.getTokens()
}
showToken (selectedTokenToView) {
showToken(selectedTokenToView) {
_this.setState({
selectedTokenToView
})
_this.onHandleToggleModal()
}
selectToken (selectedTokenToSend) {
selectToken(selectedTokenToSend) {
_this.setState({
selectedTokenToSend
})
@@ -173,11 +169,38 @@ class Tokens extends React.Component {
ele.scrollIntoView({ behavior: 'smooth' })
}
onHandleToggleModal () {
onHandleToggleModal() {
_this.setState({
showModal: !_this.state.showModal
})
}
handleError(error) {
let errMsg = ''
if (error.message) {
errMsg = error.message
}
if (error.error) {
if (error.error.match('rate limits')) {
errMsg = <span>
Rate limits exceeded, increase rate limits with a JWT token from
<a style={{ marginLeft: '5px' }}
target="_blank"
href="https://fullstack.cash">FullStack.cash</a>
</span>
} else {
errMsg = error.error
}
}
_this.setState(prevState => {
return {
...prevState,
errMsg: errMsg,
txId: '',
inFetch: false
}
})
}
}
Tokens.propTypes = {
walletInfo: PropTypes.object.isRequired, // wallet info
+28 -16
View File
@@ -173,20 +173,7 @@ class SendTokens extends React.Component {
_this.props.handleSend()
}, 1000)
} catch (error) {
let errMsg
if (error.message) {
errMsg = error.message
} else if (error.error) {
errMsg = error.error
}
_this.setState(prevState => {
return {
...prevState,
errMsg,
txId: '',
inFetch: false
}
})
_this.handleError(error)
}
}
@@ -207,7 +194,6 @@ class SendTokens extends React.Component {
validateInputs () {
const { address, amountSat } = _this.state
const amountNumber = Number(amountSat)
console.log(_this.state)
if (!address) {
throw new Error('Address is required')
@@ -282,7 +268,33 @@ class SendTokens extends React.Component {
}
}
componentDidMount () {}
handleError(error){
//console.error(error)
let errMsg = ''
if (error.message) {
errMsg = error.message
}
if (error.error) {
if (error.error.match('rate limits')) {
errMsg = <span>
Rate limits exceeded, increase rate limits with a JWT token from
<a style={{marginLeft:'5px'}}
target="_blank"
href="https://fullstack.cash">FullStack.cash</a>
</span>
} else {
errMsg = error.error
}
}
_this.setState(prevState => {
return {
...prevState,
errMsg,
txId: '',
inFetch: false
}
})
}
}
SendTokens.propTypes = {
walletInfo: PropTypes.object.isRequired, // wallet info
+33 -15
View File
@@ -6,7 +6,7 @@ import BchWallet from 'minimal-slp-wallet'
let _this
class NewWallet extends React.Component {
constructor (props) {
constructor(props) {
super(props)
_this = this
this.state = {
@@ -17,7 +17,7 @@ class NewWallet extends React.Component {
_this.BchWallet = BchWallet
}
render () {
render() {
return (
<>
<Row>
@@ -38,11 +38,6 @@ class NewWallet extends React.Component {
<span>New Wallet</span>
</h1>
</Col>
<Col sm={12} className='text-center '>
{_this.state.errMsg && (
<p className='error-color mt-2'>{_this.state.errMsg}</p>
)}
</Col>
<Col sm={12} className='text-center mt-2 mb-2'>
<Button
text='Create Wallet'
@@ -51,6 +46,11 @@ class NewWallet extends React.Component {
onClick={_this.handleCreateWallet}
/>
</Col>
<Col sm={12} className='text-center '>
{_this.state.errMsg && (
<p className='error-color mt-2'>{_this.state.errMsg}</p>
)}
</Col>
</Row>
</Box>
</Col>
@@ -60,7 +60,7 @@ class NewWallet extends React.Component {
)
}
async handleCreateWallet () {
async handleCreateWallet() {
try {
const currentWallet = _this.props.walletInfo
@@ -85,7 +85,6 @@ class NewWallet extends React.Component {
if (restURL) {
bchjsOptions.restURL = restURL
}
console.log('bchjs options : ', bchjsOptions)
}
const bchWalletLib = new _this.BchWallet(null, bchjsOptions)
@@ -102,7 +101,7 @@ class NewWallet extends React.Component {
Object.assign(currentWallet, walletInfo)
const myBalance = await bchWalletLib.getBalance()
// console.log("myBalance", myBalance)
// Update redux state
_this.props.setWalletInfo(currentWallet)
_this.props.updateBalance(myBalance)
@@ -113,13 +112,32 @@ class NewWallet extends React.Component {
errMsg: ''
})
} catch (error) {
console.error(error)
_this.setState({
inFetch: false,
errMsg: error.message
})
_this.handleError(error)
}
}
handleError(error) {
//console.error(error)
let errMsg = ''
if (error.message) {
errMsg = error.message
}
if (error.error) {
if (error.error.match('rate limits')) {
errMsg = <span>
Rate limits exceeded, increase rate limits with a JWT token from
<a style={{ marginLeft: '5px' }}
target="_blank"
href="https://fullstack.cash">FullStack.cash</a>
</span>
} else {
errMsg = error.error
}
}
_this.setState({
inFetch: false,
errMsg: errMsg
})
}
}
NewWallet.propTypes = {
walletInfo: PropTypes.object.isRequired,
+32 -13
View File
@@ -58,13 +58,7 @@ 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'>
<Col sm={12} className='text-center mb-2'>
<Button
text='Import'
type='primary'
@@ -72,6 +66,11 @@ class ImportWallet extends React.Component {
onClick={_this.handleImportWallet}
/>
</Col>
<Col sm={12} className='text-center'>
{_this.state.errMsg && (
<p className='error-color'>{_this.state.errMsg}</p>
)}
</Col>
</Row>
</Box>
</Col>
@@ -155,11 +154,8 @@ class ImportWallet extends React.Component {
inFetch: false
})
} catch (error) {
console.warn(error)
_this.setState({
errMsg: error.message,
inFetch: false
})
_this.handleError(error)
}
}
@@ -180,13 +176,36 @@ class ImportWallet extends React.Component {
const spaceCount = mnemonic.split(' ').length // mnemonic.match(/ /g).length
if (spaceCount !== 12) {
console.log('reject')
// console.log('reject')
throw new Error('mnemonic must contain 12 words')
}
} else {
throw new Error('12 word mnemonic is required')
}
}
handleError(error){
//console.error(error)
let errMsg = ''
if (error.message) {
errMsg = error.message
}
if (error.error) {
if (error.error.match('rate limits')) {
errMsg = <span>
Rate limits exceeded, increase rate limits with a JWT token from
<a style={{marginLeft:'5px'}}
target="_blank"
href="https://fullstack.cash">FullStack.cash</a>
</span>
} else {
errMsg = error.error
}
}
_this.setState({
inFetch: false,
errMsg: errMsg
})
}
}
ImportWallet.propTypes = {