mirror of
https://github.com/Permissionless-Software-Foundation/bch-dex-taker-v2.git
synced 2026-09-21 16:52:01 -07:00
Merge pull request #4 from Permissionless-Software-Foundation/dh-buy-modal
feat(buy): Added buy modal to DEX taker wallet
This commit is contained in:
@@ -36,6 +36,11 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.buy-modal {
|
||||
top: 30%!important;
|
||||
width: auto!important;
|
||||
}
|
||||
|
||||
|
||||
/* Remove input number arrows Chrome, Safari, Edge, Opera */
|
||||
input::-webkit-outer-spin-button,
|
||||
|
||||
+3
-3
@@ -73,16 +73,16 @@ function App (props) {
|
||||
|
||||
// Load the P2WDB libraries.
|
||||
addToModal('Loading P2WDB Libraries', appData)
|
||||
const {p2wdbRead, p2wdbWrite} = asyncLoad.getP2WDBLib({bchWallet: walletTemp})
|
||||
const { p2wdbRead, p2wdbWrite } = asyncLoad.getP2WDBLib({ bchWallet: walletTemp })
|
||||
|
||||
// Load the DEX library.
|
||||
addToModal('Loading DEX Library', appData)
|
||||
const dexLib = asyncLoad.getDexLib({bchWallet: walletTemp, p2wdbRead, p2wdbWrite})
|
||||
const dexLib = asyncLoad.getDexLib({ bchWallet: walletTemp, p2wdbRead, p2wdbWrite })
|
||||
appData.setDexLib(dexLib)
|
||||
|
||||
// Load the Nostr library.
|
||||
addToModal('Loading Nostr Library', appData)
|
||||
const nostrLib = asyncLoad.getNostrLib({bchWallet: walletTemp})
|
||||
const nostrLib = asyncLoad.getNostrLib({ bchWallet: walletTemp })
|
||||
appData.setNostr(nostrLib)
|
||||
|
||||
// Update state
|
||||
|
||||
@@ -5,49 +5,86 @@
|
||||
|
||||
// Global npm libraries
|
||||
import React, { useState } from 'react'
|
||||
import { Button, Modal, Container, Row, Col } from 'react-bootstrap'
|
||||
import { Button, Modal, Container, Row, Col, Spinner } from 'react-bootstrap'
|
||||
|
||||
function BuyButton (props) {
|
||||
const { token, appData } = props
|
||||
|
||||
const [show, setShow] = useState(false)
|
||||
const { token, appData, onSuccess } = props
|
||||
console.log('props: ', props)
|
||||
const [show, setShow] = useState(false) // show the modal
|
||||
const [onFetch, setOnFetch] = useState(false) // show the spinner
|
||||
const [error, setError] = useState(false) // show the error message
|
||||
// const [eventId, setEventId] = useState(false) // show the event id
|
||||
const [noteId, setNoteId] = useState(false) // show the note id
|
||||
const [success, setSuccess] = useState(false) // show the success message
|
||||
const [showConfirmation, setShowConfirmation] = useState(true) // show the confirmation view
|
||||
|
||||
const handleBuy = async () => {
|
||||
console.log('handleBuy()')
|
||||
console.log('token: ', token)
|
||||
console.log('appData: ', appData)
|
||||
try {
|
||||
console.log('handleBuy()')
|
||||
console.log('token: ', token)
|
||||
console.log('appData: ', appData)
|
||||
setShowConfirmation(false)
|
||||
setOnFetch(true)
|
||||
|
||||
const targetOffer = token.nostrEventId
|
||||
console.log('targetOffer: ', targetOffer)
|
||||
/* // dev-test success view
|
||||
setShowConfirmation(false)
|
||||
setSuccess(true)
|
||||
setNoteId('note12986q83gre76vl9dldpnnhej7y67h76xzw0tx0hm4mq6uradr6lskch7v9')
|
||||
setOnFetch(false)
|
||||
return
|
||||
*/
|
||||
const targetOffer = token.nostrEventId
|
||||
console.log('targetOffer: ', targetOffer)
|
||||
|
||||
// TODO: Launch modal to let user know that the purchase is in progress.
|
||||
// Generate a counter offer.
|
||||
const bchDexLib = appData.dexLib
|
||||
const { offerData, partialHex } = await bchDexLib.take.takeOffer(
|
||||
targetOffer
|
||||
)
|
||||
|
||||
// Generate a counter offer.
|
||||
const bchDexLib = appData.dexLib
|
||||
const { offerData, partialHex } = await bchDexLib.take.takeOffer(targetOffer)
|
||||
console.log('offerData: ', offerData)
|
||||
console.log('partialHex: ', partialHex)
|
||||
|
||||
console.log('offerData: ', offerData)
|
||||
console.log('partialHex: ', partialHex)
|
||||
// Upload the counter offer to Nostr.
|
||||
const nostr = appData.nostr
|
||||
const { eventId, noteId } = await nostr.testNostrUpload({
|
||||
offerData,
|
||||
partialHex
|
||||
})
|
||||
|
||||
// Upload the counter offer to Nostr.
|
||||
const nostr = appData.nostr
|
||||
const { eventId, noteId } = await nostr.testNostrUpload({ offerData, partialHex })
|
||||
console.log(
|
||||
`Counter Offer uploaded to Nostr with this event ID: ${eventId}`
|
||||
)
|
||||
console.log(`https://astral.psfoundation.info/${noteId}`)
|
||||
|
||||
console.log(`Counter Offer uploaded to Nostr with this event ID: ${eventId}`)
|
||||
console.log(`https://astral.psfoundation.info/${noteId}`)
|
||||
setNoteId(noteId)
|
||||
setSuccess(true)
|
||||
setOnFetch(false)
|
||||
} catch (error) {
|
||||
setOnFetch(false)
|
||||
setError(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
console.log('handleClose()')
|
||||
// Deny close if the purchase is in progress.
|
||||
if (onFetch) {
|
||||
return
|
||||
}
|
||||
|
||||
// Call onSuccess() callback if the modal close after a success purchase.
|
||||
if (success && onSuccess) {
|
||||
onSuccess()
|
||||
}
|
||||
// Reset the state.
|
||||
setError(false)
|
||||
setSuccess(false)
|
||||
setNoteId(false)
|
||||
setShow(false)
|
||||
// props.instance.setState({ showModal: false })
|
||||
setOnFetch(false)
|
||||
setShowConfirmation(true)
|
||||
}
|
||||
|
||||
const handleOpen = () => {
|
||||
console.log('handleOpen()')
|
||||
setShow(true)
|
||||
}
|
||||
|
||||
// Replace with dummy button until token data is loaded.
|
||||
if (!props.token.tokenData) {
|
||||
return (
|
||||
@@ -59,45 +96,94 @@ function BuyButton (props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button variant='success' disabled={props.disabled} onClick={handleBuy}>Buy</Button>
|
||||
<Modal show={show} onHide={handleClose}>
|
||||
<Button
|
||||
variant='success'
|
||||
disabled={props.disabled}
|
||||
onClick={() => {
|
||||
setShow(true)
|
||||
}}
|
||||
>
|
||||
Buy
|
||||
</Button>
|
||||
<Modal show={show} onHide={handleClose} dialogClassName='buy-modal'>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>Token Information</Modal.Title>
|
||||
<Modal.Title>
|
||||
{success
|
||||
? (
|
||||
<span style={{ color: 'green' }}>Successful Purchase</span>
|
||||
)
|
||||
: (
|
||||
'Processing Purchase'
|
||||
)}
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<Container>
|
||||
<Row>
|
||||
<Col xs={4}><b>Ticker</b>:</Col>
|
||||
<Col xs={8}>{props.token.ticker}</Col>
|
||||
</Row>
|
||||
<Modal.Body className='text-center'>
|
||||
{/** If the purchase is not confirmed, display the token details. and confirm button. */}
|
||||
{showConfirmation && (
|
||||
<Container className='text-start'>
|
||||
<Row>
|
||||
<Col xs={4}>
|
||||
<b>Ticker</b>:
|
||||
</Col>
|
||||
<Col xs={8}>{token.ticker}</Col>
|
||||
</Row>
|
||||
|
||||
<Row style={{ backgroundColor: '#eee' }}>
|
||||
<Col xs={4}><b>Name</b>:</Col>
|
||||
<Col xs={8}>{props.token.tokenData.genesisData.name}</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col xs={4}>
|
||||
<b>Name</b>:
|
||||
</Col>
|
||||
<Col xs={8}>{props.token.tokenData.genesisData.name}</Col>
|
||||
</Row>
|
||||
<Row style={{ backgroundColor: '#eee' }}>
|
||||
<Col xs={4}>
|
||||
<b>Price</b>:
|
||||
</Col>
|
||||
<Col xs={8}>
|
||||
<strong>{token.usdPrice}</strong>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
)}
|
||||
|
||||
<Row>
|
||||
<Col xs={4}><b>Token ID</b>:</Col>
|
||||
<Col xs={8} style={{ wordBreak: 'break-all' }}>
|
||||
<a href={`https://explorer.tokentiger.com/?tokenid=${props.token.tokenId}`} target='_blank' rel='noreferrer'>
|
||||
{props.token.tokenId}
|
||||
</a>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row style={{ backgroundColor: '#eee' }}>
|
||||
<Col xs={4}><b>Decimals</b>:</Col>
|
||||
<Col xs={8}>{props.token.tokenData.genesisData.decimals}</Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Col xs={4}><b>Token Type</b>:</Col>
|
||||
<Col xs={8}>{props.token.tokenType}</Col>
|
||||
</Row>
|
||||
{/** show purchase progress */}
|
||||
<Container style={{ wordBreak: 'break-word' }}>
|
||||
{onFetch && <Spinner animation='border' variant='primary' />}
|
||||
{error && (
|
||||
<span style={{ color: 'red', fontStyle: 'italic' }}>{error}</span>
|
||||
)}
|
||||
|
||||
{success && (
|
||||
<>
|
||||
<p>
|
||||
Note ID :
|
||||
<a
|
||||
href={`https://astral.psfoundation.info/${noteId}`}
|
||||
target='_blank'
|
||||
rel='noreferrer'
|
||||
>
|
||||
{' '}
|
||||
{noteId}
|
||||
</a>
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</Container>
|
||||
</Modal.Body>
|
||||
<Modal.Footer />
|
||||
<Modal.Footer className='text-center'>
|
||||
{showConfirmation && (
|
||||
<Row style={{ width: '100%' }}>
|
||||
<Col xs={12} className='text-center'>
|
||||
<Button
|
||||
variant='success'
|
||||
style={{ minWidth: '100px' }}
|
||||
onClick={handleBuy}
|
||||
>
|
||||
Buy
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -221,6 +221,7 @@ function NftsForSale (props) {
|
||||
<TokenCard
|
||||
appData={appData}
|
||||
token={thisToken}
|
||||
handleRefresh={handleRefresh}
|
||||
key={`${thisToken.tokenId + i}`}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ import InfoButton from './info-button'
|
||||
import BuyButton from './buy-button'
|
||||
|
||||
function TokenCard (props) {
|
||||
const { token, appData } = props
|
||||
const { token, appData, handleRefresh } = props
|
||||
const [icon, setIcon] = useState(token.icon)
|
||||
const [tokenData, setTokenData] = useState(token.tokenData)
|
||||
|
||||
@@ -72,7 +72,7 @@ function TokenCard (props) {
|
||||
<Col />
|
||||
|
||||
<Col>
|
||||
<BuyButton token={token} disabled={!token.tokenData} appData={appData} />
|
||||
<BuyButton token={token} disabled={!token.tokenData} appData={appData} onSuccess={handleRefresh} />
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ class AsyncLoad {
|
||||
try {
|
||||
const { bchWallet, p2wdbRead, p2wdbWrite } = inObj
|
||||
|
||||
const dexLib = new BchDexLib({bchWallet, p2wdbRead, p2wdbWrite})
|
||||
const dexLib = new BchDexLib({ bchWallet, p2wdbRead, p2wdbWrite })
|
||||
|
||||
return dexLib
|
||||
} catch (error) {
|
||||
@@ -219,7 +219,7 @@ class AsyncLoad {
|
||||
try {
|
||||
const { bchWallet } = inObj
|
||||
|
||||
const nostrLib = new Nostr({bchWallet})
|
||||
const nostrLib = new Nostr({ bchWallet })
|
||||
|
||||
return nostrLib
|
||||
} catch (error) {
|
||||
@@ -234,9 +234,9 @@ class AsyncLoad {
|
||||
const { bchWallet } = inObj
|
||||
|
||||
const p2wdbRead = new P2WDB.Read()
|
||||
const p2wdbWrite = new P2WDB.Write({bchWallet})
|
||||
const p2wdbWrite = new P2WDB.Write({ bchWallet })
|
||||
|
||||
return {p2wdbRead, p2wdbWrite}
|
||||
return { p2wdbRead, p2wdbWrite }
|
||||
} catch (error) {
|
||||
console.error('Error in getP2WDBLib', error)
|
||||
throw error
|
||||
@@ -244,8 +244,6 @@ class AsyncLoad {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function sleep (ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user