mirror of
https://github.com/Permissionless-Software-Foundation/bch-dex-taker-v2.git
synced 2026-09-21 16:52:01 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d708d88c3c | ||
|
|
f80c43f35e | ||
|
|
3d73b7943d | ||
|
|
13ad04cde1 |
+36
-3
@@ -14,6 +14,7 @@ import NavMenu from './components/nav-menu'
|
|||||||
import useAppState from './hooks/state'
|
import useAppState from './hooks/state'
|
||||||
import { UninitializedView, InitializedView } from './components/starter-views'
|
import { UninitializedView, InitializedView } from './components/starter-views'
|
||||||
|
|
||||||
|
const sigleViewPaths = ['/profile']
|
||||||
function App (props) {
|
function App (props) {
|
||||||
// Load all the app state into a single object that can be passed to child
|
// Load all the app state into a single object that can be passed to child
|
||||||
// components.
|
// components.
|
||||||
@@ -30,12 +31,44 @@ function App (props) {
|
|||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const isSignleView = useCallback(async () => {
|
||||||
|
// Get current path
|
||||||
|
const currentPath = window.location.pathname
|
||||||
|
// Get hash from url
|
||||||
|
const hash = window.location.hash
|
||||||
|
const allowedPath = sigleViewPaths.find((val) => { return currentPath.match(val) })
|
||||||
|
|
||||||
|
if (hash === '#single-view' && allowedPath) {
|
||||||
|
addToModal('Loading minimal-slp-wallet', appData)
|
||||||
|
const asyncLoad = new AsyncLoad()
|
||||||
|
if (!appData.wallet) {
|
||||||
|
await asyncLoad.loadWalletLib()
|
||||||
|
const walletTemp = await asyncLoad.initStarterWallet(appData.serverUrl, appData.lsState.mnemonic, appData)
|
||||||
|
appData.setWallet(walletTemp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Modal State
|
||||||
|
appData.setIsSingleView(true)
|
||||||
|
appData.setHideSpinner(true)
|
||||||
|
appData.setShowStartModal(false)
|
||||||
|
appData.setDenyClose(false)
|
||||||
|
|
||||||
|
/* // Update the startup state.
|
||||||
|
appData.setAsyncInitFinished(true)
|
||||||
|
appData.setAsyncInitSucceeded(false) */
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}, [appData, addToModal])
|
||||||
|
|
||||||
/** Load all required data before component start. */
|
/** Load all required data before component start. */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function asyncEffect () {
|
async function asyncEffect () {
|
||||||
console.log('asyncInitStarted: ', appData.asyncInitStarted)
|
const singleView = await isSignleView()
|
||||||
|
|
||||||
if (!appData.asyncInitStarted) {
|
console.log('asyncInitStarted: ', appData.asyncInitStarted)
|
||||||
|
console.log('is single view : ', singleView)
|
||||||
|
if (!appData.asyncInitStarted && !singleView) {
|
||||||
try {
|
try {
|
||||||
// Instantiate the async load object.
|
// Instantiate the async load object.
|
||||||
const asyncLoad = new AsyncLoad()
|
const asyncLoad = new AsyncLoad()
|
||||||
@@ -112,7 +145,7 @@ function App (props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
asyncEffect()
|
asyncEffect()
|
||||||
}, [appData, addToModal])
|
}, [appData, addToModal, isSignleView])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ function ContentCard (props) {
|
|||||||
}, [creator.profile])
|
}, [creator.profile])
|
||||||
|
|
||||||
const goToProfile = () => {
|
const goToProfile = () => {
|
||||||
const profileUrl = `${window.location.origin}/profile/${creator.npub}`
|
const profileUrl = `${window.location.origin}/profile/${creator.npub}#single-view`
|
||||||
window.open(profileUrl, '_blank')
|
window.open(profileUrl, '_blank')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ import * as nip19 from 'nostr-tools/nip19'
|
|||||||
|
|
||||||
function ProfileRead (props) {
|
function ProfileRead (props) {
|
||||||
const { npub } = props
|
const { npub } = props
|
||||||
const { bchWalletState } = props.appData
|
|
||||||
console.log('npub prop', npub)
|
|
||||||
const { setProfile } = props
|
const { setProfile } = props
|
||||||
const [post, setPost] = useState({})
|
const [post, setPost] = useState({})
|
||||||
const [loaded, setLoaded] = useState(false)
|
const [loaded, setLoaded] = useState(false)
|
||||||
@@ -24,7 +22,6 @@ function ProfileRead (props) {
|
|||||||
const start = () => {
|
const start = () => {
|
||||||
const pubHexData = nip19.decode(npub)
|
const pubHexData = nip19.decode(npub)
|
||||||
const pubHex = pubHexData.data
|
const pubHex = pubHexData.data
|
||||||
console.log('pubhex', pubHex)
|
|
||||||
const psf = 'wss://nostr-relay.psfoundation.info'
|
const psf = 'wss://nostr-relay.psfoundation.info'
|
||||||
|
|
||||||
const pool = RelayPool([psf])
|
const pool = RelayPool([psf])
|
||||||
@@ -56,7 +53,7 @@ function ProfileRead (props) {
|
|||||||
if (!loaded && npub) {
|
if (!loaded && npub) {
|
||||||
start()
|
start()
|
||||||
}
|
}
|
||||||
}, [bchWalletState, loaded, setProfile, npub])
|
}, [loaded, setProfile, npub])
|
||||||
|
|
||||||
const handleImageError = (type) => {
|
const handleImageError = (type) => {
|
||||||
setImageError(prev => ({ ...prev, [type]: true }))
|
setImageError(prev => ({ ...prev, [type]: true }))
|
||||||
@@ -117,13 +114,13 @@ function ProfileRead (props) {
|
|||||||
<div className='text-muted small mb-3 d-flex align-items-center flex-column flex-md-row'>
|
<div className='text-muted small mb-3 d-flex align-items-center flex-column flex-md-row'>
|
||||||
<span className='text-truncate me-2 mb-2 mb-md-0'>
|
<span className='text-truncate me-2 mb-2 mb-md-0'>
|
||||||
<span className='d-md-none'>
|
<span className='d-md-none'>
|
||||||
{`${bchWalletState.nostrKeyPair.npub.slice(0, 8)}...${bchWalletState.nostrKeyPair.npub.slice(-5)}`}
|
{`${npub?.slice(0, 8)}...${npub?.slice(-5)}`}
|
||||||
</span>
|
</span>
|
||||||
<span className='d-none d-md-inline'>
|
<span className='d-none d-md-inline'>
|
||||||
{bchWalletState.nostrKeyPair.npub}
|
{npub}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<CopyOnClick walletProp='npub' appData={props.appData} value={bchWalletState.nostrKeyPair.npub} />
|
<CopyOnClick walletProp='npub' appData={props.appData} value={npub} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* About Section */}
|
{/* About Section */}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ function PublicRead (props) {
|
|||||||
<div className='flex-grow-1'>
|
<div className='flex-grow-1'>
|
||||||
<div className='fw-bold mb-1'>{props.profile?.name}</div>
|
<div className='fw-bold mb-1'>{props.profile?.name}</div>
|
||||||
<small className='text-muted'>
|
<small className='text-muted'>
|
||||||
{`${bchWalletState.nostrKeyPair.npub.slice(0, 8)}...${bchWalletState.nostrKeyPair.npub.slice(-5)}`}
|
{`${npub.slice(0, 8)}...${npub.slice(-5)}`}
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<small className='text-muted'>
|
<small className='text-muted'>
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ function SlpTokensDisplay (props) {
|
|||||||
const getTokens = async () => {
|
const getTokens = async () => {
|
||||||
try {
|
try {
|
||||||
const { nostrKeyPair } = bchWalletState
|
const { nostrKeyPair } = bchWalletState
|
||||||
if (nostrKeyPair.npub === npub) {
|
if (nostrKeyPair?.npub === npub) {
|
||||||
setTokens(bchWalletState.slpTokens)
|
setTokens(bchWalletState.slpTokens)
|
||||||
setLoaded(true)
|
setLoaded(true)
|
||||||
return
|
return
|
||||||
|
|||||||
+107
-103
@@ -15,8 +15,7 @@ import Logo from './psf-logo.png'
|
|||||||
|
|
||||||
function NavMenu (props) {
|
function NavMenu (props) {
|
||||||
// Get the current path
|
// Get the current path
|
||||||
const { currentPath, bchWalletState } = props.appData
|
const { currentPath, bchWalletState, isSingleView } = props.appData
|
||||||
|
|
||||||
// Navbar state
|
// Navbar state
|
||||||
const [expanded, setExpanded] = useState(false)
|
const [expanded, setExpanded] = useState(false)
|
||||||
|
|
||||||
@@ -25,125 +24,130 @@ function NavMenu (props) {
|
|||||||
// Collapse the navbar
|
// Collapse the navbar
|
||||||
setExpanded(false)
|
setExpanded(false)
|
||||||
}
|
}
|
||||||
|
const goToHome = () => {
|
||||||
|
if (isSingleView) {
|
||||||
|
window.location.href = '/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Navbar expanded={expanded} onToggle={setExpanded} expand='xxxl' bg='dark' variant='dark' style={{ paddingRight: '20px' }}>
|
<Navbar expanded={expanded} onToggle={setExpanded} expand='xxxl' bg='dark' variant='dark' style={{ paddingRight: '20px' }}>
|
||||||
<Navbar.Brand href='#home' style={{ paddingLeft: '20px' }}>
|
<Navbar.Brand href='#home' style={{ paddingLeft: '20px' }} onClick={goToHome}>
|
||||||
<Image src={Logo} thumbnail width='50' />{' '}
|
<Image src={Logo} thumbnail width='50' />{' '}
|
||||||
DEX
|
DEX
|
||||||
</Navbar.Brand>
|
</Navbar.Brand>
|
||||||
|
|
||||||
<Navbar.Toggle aria-controls='responsive-navbar-nav' />
|
{!isSingleView && <Navbar.Toggle aria-controls='responsive-navbar-nav' />}
|
||||||
<Navbar.Collapse id='responsive-navbar-nav'>
|
{!isSingleView && (
|
||||||
<Nav className='mr-auto'>
|
<Navbar.Collapse id='responsive-navbar-nav'>
|
||||||
|
<Nav className='mr-auto'>
|
||||||
|
<NavLink
|
||||||
|
className={(currentPath === '/nfts-for-sale' || currentPath === '/') ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
|
to='/nfts-for-sale'
|
||||||
|
onClick={handleClickEvent}
|
||||||
|
>
|
||||||
|
NFTs
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
<NavLink
|
<NavLink
|
||||||
className={(currentPath === '/nfts-for-sale' || currentPath === '/') ? 'nav-link-active' : 'nav-link-inactive'}
|
className={currentPath === '/offers' ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
to='/nfts-for-sale'
|
to='/offers'
|
||||||
onClick={handleClickEvent}
|
onClick={handleClickEvent}
|
||||||
>
|
>
|
||||||
NFTs
|
Fungible Tokens
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|
||||||
<NavLink
|
<hr />
|
||||||
className={currentPath === '/offers' ? 'nav-link-active' : 'nav-link-inactive'}
|
|
||||||
to='/offers'
|
|
||||||
onClick={handleClickEvent}
|
|
||||||
>
|
|
||||||
Fungible Tokens
|
|
||||||
</NavLink>
|
|
||||||
|
|
||||||
<hr />
|
<NavLink
|
||||||
|
className={currentPath === '/global-feed' ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
|
to='/feeds'
|
||||||
|
onClick={handleClickEvent}
|
||||||
|
>
|
||||||
|
Feeds
|
||||||
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
className={currentPath === '/nostr-post' ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
|
to='/nostr-post'
|
||||||
|
onClick={handleClickEvent}
|
||||||
|
>
|
||||||
|
Nostr Post
|
||||||
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
className={currentPath === '/profile' ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
|
to={`/profile/${bchWalletState?.nostrKeyPair?.npub}`}
|
||||||
|
onClick={handleClickEvent}
|
||||||
|
>
|
||||||
|
Nostr Profile
|
||||||
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
className={currentPath === '/content-creators' ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
|
to='/content-creators'
|
||||||
|
onClick={handleClickEvent}
|
||||||
|
>
|
||||||
|
Content Creators
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
<NavLink
|
<hr />
|
||||||
className={currentPath === '/global-feed' ? 'nav-link-active' : 'nav-link-inactive'}
|
|
||||||
to='/feeds'
|
|
||||||
onClick={handleClickEvent}
|
|
||||||
>
|
|
||||||
Feeds
|
|
||||||
</NavLink>
|
|
||||||
<NavLink
|
|
||||||
className={currentPath === '/nostr-post' ? 'nav-link-active' : 'nav-link-inactive'}
|
|
||||||
to='/nostr-post'
|
|
||||||
onClick={handleClickEvent}
|
|
||||||
>
|
|
||||||
Nostr Post
|
|
||||||
</NavLink>
|
|
||||||
<NavLink
|
|
||||||
className={currentPath === '/profile' ? 'nav-link-active' : 'nav-link-inactive'}
|
|
||||||
to={`/profile/${bchWalletState?.nostrKeyPair?.npub}`}
|
|
||||||
onClick={handleClickEvent}
|
|
||||||
>
|
|
||||||
Nostr Profile
|
|
||||||
</NavLink>
|
|
||||||
<NavLink
|
|
||||||
className={currentPath === '/content-creators' ? 'nav-link-active' : 'nav-link-inactive'}
|
|
||||||
to='/content-creators'
|
|
||||||
onClick={handleClickEvent}
|
|
||||||
>
|
|
||||||
Content Creators
|
|
||||||
</NavLink>
|
|
||||||
|
|
||||||
<hr />
|
<NavLink
|
||||||
|
className={(currentPath === '/bch') ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
|
to='/bch'
|
||||||
|
onClick={handleClickEvent}
|
||||||
|
>
|
||||||
|
BCH
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
<NavLink
|
<NavLink
|
||||||
className={(currentPath === '/bch') ? 'nav-link-active' : 'nav-link-inactive'}
|
className={currentPath === '/slp-tokens' ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
to='/bch'
|
to='/slp-tokens'
|
||||||
onClick={handleClickEvent}
|
onClick={handleClickEvent}
|
||||||
>
|
>
|
||||||
BCH
|
Tokens
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|
||||||
<NavLink
|
<NavLink
|
||||||
className={currentPath === '/slp-tokens' ? 'nav-link-active' : 'nav-link-inactive'}
|
className={currentPath === '/wallet' ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
to='/slp-tokens'
|
to='/wallet'
|
||||||
onClick={handleClickEvent}
|
onClick={handleClickEvent}
|
||||||
>
|
>
|
||||||
Tokens
|
Wallet
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|
||||||
<NavLink
|
<NavLink
|
||||||
className={currentPath === '/wallet' ? 'nav-link-active' : 'nav-link-inactive'}
|
className={(currentPath === '/balance') ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
to='/wallet'
|
to='/balance'
|
||||||
onClick={handleClickEvent}
|
onClick={handleClickEvent}
|
||||||
|
>
|
||||||
|
Check Balance
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
>
|
<NavLink
|
||||||
Wallet
|
className={(currentPath === '/sweep') ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
</NavLink>
|
to='/sweep'
|
||||||
|
onClick={handleClickEvent}
|
||||||
|
>
|
||||||
|
Sweep
|
||||||
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
className={(currentPath === '/sign') ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
|
to='/sign'
|
||||||
|
onClick={handleClickEvent}
|
||||||
|
>
|
||||||
|
Sign
|
||||||
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
className={currentPath === '/configuration' ? 'nav-link-active' : 'nav-link-inactive'}
|
||||||
|
to='/configuration'
|
||||||
|
onClick={handleClickEvent}
|
||||||
|
>
|
||||||
|
Configuration
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
<NavLink
|
</Nav>
|
||||||
className={(currentPath === '/balance') ? 'nav-link-active' : 'nav-link-inactive'}
|
</Navbar.Collapse>
|
||||||
to='/balance'
|
)}
|
||||||
onClick={handleClickEvent}
|
|
||||||
>
|
|
||||||
Check Balance
|
|
||||||
</NavLink>
|
|
||||||
|
|
||||||
<NavLink
|
|
||||||
className={(currentPath === '/sweep') ? 'nav-link-active' : 'nav-link-inactive'}
|
|
||||||
to='/sweep'
|
|
||||||
onClick={handleClickEvent}
|
|
||||||
>
|
|
||||||
Sweep
|
|
||||||
</NavLink>
|
|
||||||
<NavLink
|
|
||||||
className={(currentPath === '/sign') ? 'nav-link-active' : 'nav-link-inactive'}
|
|
||||||
to='/sign'
|
|
||||||
onClick={handleClickEvent}
|
|
||||||
>
|
|
||||||
Sign
|
|
||||||
</NavLink>
|
|
||||||
<NavLink
|
|
||||||
className={currentPath === '/configuration' ? 'nav-link-active' : 'nav-link-inactive'}
|
|
||||||
to='/configuration'
|
|
||||||
onClick={handleClickEvent}
|
|
||||||
>
|
|
||||||
Configuration
|
|
||||||
</NavLink>
|
|
||||||
|
|
||||||
</Nav>
|
|
||||||
</Navbar.Collapse>
|
|
||||||
</Navbar>
|
</Navbar>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
+4
-1
@@ -39,6 +39,7 @@ function useAppState () {
|
|||||||
const [modalBody, setModalBody] = useState([])
|
const [modalBody, setModalBody] = useState([])
|
||||||
const [hideSpinner, setHideSpinner] = useState(false)
|
const [hideSpinner, setHideSpinner] = useState(false)
|
||||||
const [denyClose, setDenyClose] = useState(false)
|
const [denyClose, setDenyClose] = useState(false)
|
||||||
|
const [isSingleView, setIsSingleView] = useState(false)
|
||||||
|
|
||||||
// NFTs for sale stored data to improve performance
|
// NFTs for sale stored data to improve performance
|
||||||
const [nftForSaleCacheData, setNftForSaleCacheData] = useState(lsState.nftData || {})
|
const [nftForSaleCacheData, setNftForSaleCacheData] = useState(lsState.nftData || {})
|
||||||
@@ -153,7 +154,9 @@ function useAppState () {
|
|||||||
setNftForSaleCacheData,
|
setNftForSaleCacheData,
|
||||||
updateNFTCachedData,
|
updateNFTCachedData,
|
||||||
lastFeedTab,
|
lastFeedTab,
|
||||||
setLastFeedTab
|
setLastFeedTab,
|
||||||
|
isSingleView,
|
||||||
|
setIsSingleView
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -283,6 +283,47 @@ class AsyncLoad {
|
|||||||
npub
|
npub
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize the BCH wallet without initialize() promise
|
||||||
|
async initStarterWallet (restURL, mnemonic, appData) {
|
||||||
|
try {
|
||||||
|
const options = {
|
||||||
|
interface: 'consumer-api',
|
||||||
|
restURL,
|
||||||
|
noUpdate: true
|
||||||
|
}
|
||||||
|
|
||||||
|
let wallet
|
||||||
|
if (mnemonic) {
|
||||||
|
// Load the wallet from the mnemonic, if it's available from local storage.
|
||||||
|
wallet = new this.BchWallet(mnemonic, options)
|
||||||
|
} else {
|
||||||
|
// Generate a new mnemonic and wallet.
|
||||||
|
wallet = new this.BchWallet(null, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
await wallet.walletInfoPromise
|
||||||
|
|
||||||
|
// Get Nostr key pair from WIF
|
||||||
|
const nostrKeyPair = this.nostrKeyPairFromWIF(wallet.walletInfo.privateKey)
|
||||||
|
const walletInfo = wallet.walletInfo
|
||||||
|
walletInfo.nostrKeyPair = nostrKeyPair
|
||||||
|
// Update the state of the wallet.
|
||||||
|
appData.updateBchWalletState({ walletObj: walletInfo, appData })
|
||||||
|
// Save the mnemonic to local storage.
|
||||||
|
if (!mnemonic) {
|
||||||
|
const newMnemonic = wallet.walletInfo.mnemonic
|
||||||
|
appData.updateLocalStorage({ mnemonic: newMnemonic })
|
||||||
|
}
|
||||||
|
|
||||||
|
this.wallet = wallet
|
||||||
|
|
||||||
|
return wallet
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error initStarterWallet: ', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sleep (ms) {
|
function sleep (ms) {
|
||||||
|
|||||||
Reference in New Issue
Block a user