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 | |
|---|---|---|---|
|
|
a7c3fc243b | ||
|
|
173cda717e | ||
|
|
e46068165f | ||
|
|
086deb4904 | ||
|
|
5386a07a62 | ||
|
|
a240fab588 | ||
|
|
0ab5702b48 | ||
|
|
97dd816330 | ||
|
|
b878939456 | ||
|
|
59cfecb485 | ||
|
|
bd3798f5aa | ||
|
|
5f0103ba81 | ||
|
|
55ebb7b25d |
Generated
+4
-4
@@ -15,7 +15,7 @@
|
||||
"@fortawesome/react-fontawesome": "0.2.2",
|
||||
"@noble/hashes": "^1.8.0",
|
||||
"axios": "0.27.2",
|
||||
"bch-dex-lib": "2.0.3",
|
||||
"bch-dex-lib": "2.2.0",
|
||||
"bch-message-lib": "2.2.1",
|
||||
"bch-nostr": "1.3.4",
|
||||
"bch-token-sweep": "2.2.1",
|
||||
@@ -10043,9 +10043,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bch-dex-lib": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bch-dex-lib/-/bch-dex-lib-2.0.3.tgz",
|
||||
"integrity": "sha512-aPZIlDcRziZBRKRhEuAv6G/skFjZ28+sE30fkoUY8isUIAe3C0YS7yQMoOmGSA6N46/XuhRbfQi0SRQJfrASpA==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bch-dex-lib/-/bch-dex-lib-2.2.0.tgz",
|
||||
"integrity": "sha512-SORqn4qNmbxfL2SbbapOpbcCB+FtqasR+GT0XRifdkXFjA3aDL0gwMsHjh8IzLZnKtPYSBcfgzKQFxEsXCJNug==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@chris.troutner/retry-queue": "1.0.10",
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
"@fortawesome/react-fontawesome": "0.2.2",
|
||||
"@noble/hashes": "^1.8.0",
|
||||
"axios": "0.27.2",
|
||||
"bch-dex-lib": "2.0.3",
|
||||
"bch-dex-lib": "2.2.0",
|
||||
"bch-message-lib": "2.2.1",
|
||||
"bch-nostr": "1.3.4",
|
||||
"bch-token-sweep": "2.2.1",
|
||||
|
||||
@@ -31,9 +31,12 @@ function ContentCreators (props) {
|
||||
|
||||
const [followList, setFollowList] = useState([])
|
||||
|
||||
// Get the list of profiles followed by the user.
|
||||
// It aggregates all the followers from all the relays.
|
||||
const getFollowList = useCallback(async () => {
|
||||
const list = await new Promise((resolve, reject) => {
|
||||
let list = []
|
||||
let closedRelays = 0
|
||||
const { nostrKeyPair } = appData.bchWalletState
|
||||
|
||||
const pool = RelayPool(config.nostrRelays)
|
||||
@@ -43,49 +46,62 @@ function ContentCreators (props) {
|
||||
})
|
||||
|
||||
pool.on('eose', relay => {
|
||||
console.log('Closing Relay')
|
||||
relay.close()
|
||||
/** This ensures to return an empty array if no records are found!
|
||||
* Applies for new users that don't have a follow list
|
||||
*/
|
||||
resolve(list)
|
||||
closedRelays++
|
||||
// Resolve list if all relays are closed
|
||||
if (closedRelays === config.nostrRelays.length) {
|
||||
resolve(list)
|
||||
}
|
||||
})
|
||||
|
||||
pool.on('event', (relay, subId, ev) => {
|
||||
console.log('Received event:', ev)
|
||||
list = ev.tags
|
||||
resolve(list)
|
||||
// console.log('Received event:', ev)
|
||||
// Merge list received from all relays
|
||||
list = [...list, ...ev.tags]
|
||||
})
|
||||
})
|
||||
|
||||
console.log('Follow List', list)
|
||||
// console.log('Follow List', list)
|
||||
setFollowList(list)
|
||||
}, [appData])
|
||||
|
||||
// Load profile from nostr relays
|
||||
// It uses multiple relays. It will exit after the first successful retrieval
|
||||
// from any relay. If one relay fails, it will move on to the next one.
|
||||
const loadProfile = useCallback(async (pubKey) => {
|
||||
return new Promise((resolve) => {
|
||||
// const pool = RelayPool(config.nostrRelays)
|
||||
const pool = RelayPool([config.nostrRelay])
|
||||
pool.on('open', relay => {
|
||||
relay.subscribe('subid', { limit: 5, kinds: [0], authors: [pubKey] })
|
||||
})
|
||||
// Looking for the profile in each relay sequentially
|
||||
for (let i = 0; i < config.nostrRelays.length; i++) {
|
||||
const profile = await new Promise((resolve) => {
|
||||
const relay = config.nostrRelays[i]
|
||||
// const pool = RelayPool(config.nostrRelays)
|
||||
const pool = RelayPool([relay])
|
||||
pool.on('open', relay => {
|
||||
relay.subscribe('subid', { limit: 5, kinds: [0], authors: [pubKey] })
|
||||
})
|
||||
|
||||
pool.on('eose', relay => {
|
||||
console.log('Closing Relay')
|
||||
relay.close()
|
||||
resolve(false)
|
||||
})
|
||||
|
||||
pool.on('event', (relay, subId, ev) => {
|
||||
try {
|
||||
const profile = JSON.parse(ev.content)
|
||||
// console.log('profile', profile)
|
||||
resolve(profile)
|
||||
} catch (error) {
|
||||
pool.on('eose', relay => {
|
||||
console.log('Closing Relay')
|
||||
relay.close()
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
|
||||
pool.on('event', (relay, subId, ev) => {
|
||||
try {
|
||||
const profile = JSON.parse(ev.content)
|
||||
// console.log('profile', profile)
|
||||
console.log(`Profile found for ${pubKey} at ${relay.url}`)
|
||||
resolve(profile)
|
||||
} catch (error) {
|
||||
resolve(false)
|
||||
}
|
||||
relay.close()
|
||||
})
|
||||
})
|
||||
})
|
||||
// Stop looking for profile if found
|
||||
if (profile) {
|
||||
return profile
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -25,6 +25,7 @@ function FeedCard (props) {
|
||||
const [isLiked, setIsLiked] = useState(false)
|
||||
const [likesCount, setLikesCount] = useState(null)
|
||||
const [likesFetched, setLikesFetched] = useState(false)
|
||||
const [profilePictureError, setProfilePictureError] = useState(false)
|
||||
|
||||
// function to fetch a post likes reaction
|
||||
const handleLikes = useCallback(async (post, userPubKey) => {
|
||||
@@ -76,6 +77,15 @@ function FeedCard (props) {
|
||||
console.warn(error)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleProfilePictureError = () => {
|
||||
setProfilePictureError(true)
|
||||
}
|
||||
|
||||
const handleProfilePictureLoad = () => {
|
||||
setProfilePictureError(false)
|
||||
}
|
||||
|
||||
// Get npub from pubkey
|
||||
useEffect(() => {
|
||||
const npub = nip19.npubEncode(post.pubkey)
|
||||
@@ -170,7 +180,20 @@ function FeedCard (props) {
|
||||
background: 'linear-gradient(45deg, #6c757d, #495057)'
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faUser} size='1x' color='#7c7c7d' />
|
||||
{profile?.picture && !profilePictureError
|
||||
? (
|
||||
<img
|
||||
src={profile.picture}
|
||||
alt='Profile'
|
||||
className='rounded-circle w-100 h-100'
|
||||
style={{ objectFit: 'cover' }}
|
||||
onError={handleProfilePictureError}
|
||||
onLoad={handleProfilePictureLoad}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<FontAwesomeIcon icon={faUser} size='1x' color='#7c7c7d' />
|
||||
)}
|
||||
</div>
|
||||
<div className='flex-grow-1'>
|
||||
<div className='fw-bold mb-1'>
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
/*
|
||||
Component for reading the nostr feeds.
|
||||
|
||||
TODO:
|
||||
- fetchProfile() should retrieve a profile from multiple relays. If the first relay returns a profile,
|
||||
then that profile can be used and promise resolved. If the first relay returns no profile, the next
|
||||
one should be tried until all relays are exhausted or one returns a profile.
|
||||
|
||||
- useEffect() retrieves the feeds. This should cycle through each relay and posts from each one.
|
||||
Once each relays has been tried, the posts should remove duplicate entries. Finally posts should
|
||||
be sorted by date.
|
||||
|
||||
- Clicking on a profile picture, name, or npub should open the profile for that user in a new tab.
|
||||
*/
|
||||
|
||||
// Global npm libraries
|
||||
@@ -22,16 +33,23 @@ function Feeds (props) {
|
||||
const [profiles, setProfiles] = useState({})
|
||||
|
||||
// function to fetch profile and set it to profiles state
|
||||
const fetchProfile = useCallback((pubkey) => {
|
||||
const fetchProfile = useCallback(async (pubkey) => {
|
||||
// no fetch profile again if it exist
|
||||
let hasProfileRequest = false
|
||||
setProfiles(currentProfiles => {
|
||||
if (currentProfiles[pubkey]) {
|
||||
hasProfileRequest = true
|
||||
return currentProfiles
|
||||
} else {
|
||||
const newProfiles = { ...currentProfiles }
|
||||
newProfiles[pubkey] = { loaded: false }
|
||||
return newProfiles
|
||||
}
|
||||
return currentProfiles
|
||||
})
|
||||
if (hasProfileRequest) return
|
||||
|
||||
const pool = RelayPool(config.nostrRelays)
|
||||
// const pool = RelayPool(config.nostrRelays)
|
||||
const pool = RelayPool([config.nostrRelay])
|
||||
pool.on('open', relay => {
|
||||
relay.subscribe('subid', { limit: 5, kinds: [0], authors: [pubkey] })
|
||||
})
|
||||
@@ -49,6 +67,7 @@ function Feeds (props) {
|
||||
return currentProfiles
|
||||
})
|
||||
} catch (error) {
|
||||
console.warn(error)
|
||||
// skip error
|
||||
}
|
||||
})
|
||||
@@ -71,7 +90,8 @@ function Feeds (props) {
|
||||
// Get global feed posts
|
||||
useEffect(() => {
|
||||
const start = () => {
|
||||
const pool = RelayPool(config.nostrRelays)
|
||||
// const pool = RelayPool(config.nostrRelays)
|
||||
const pool = RelayPool([config.nostrRelay])
|
||||
pool.on('open', relay => {
|
||||
relay.subscribe('REQ', { limit: 10, kinds: [1], '#t': ['slpdex-socialmedia'] })
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ const NostrFormat = ({ content }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div dangerouslySetInnerHTML={{ __html: formatContent(content) }} />
|
||||
<div style={{ overflow: 'auto' }} dangerouslySetInnerHTML={{ __html: formatContent(content) }} />
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
/**
|
||||
* Component for read nostr information kind 0
|
||||
* Component to read nostr information kind 0 (normal posts)
|
||||
*
|
||||
* TODO:
|
||||
* - Currently feeds are retrieved from only one relay. It should retrieve Kind
|
||||
* 0 posts from all relays. It should then remove any duplicate entries.
|
||||
*/
|
||||
|
||||
// Global npm libraries
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Container, Button } from 'react-bootstrap'
|
||||
@@ -26,7 +31,8 @@ function ProfileRead (props) {
|
||||
const pubHexData = nip19.decode(npub)
|
||||
const pubHex = pubHexData.data
|
||||
|
||||
const pool = RelayPool(config.nostrRelays)
|
||||
// const pool = RelayPool(config.nostrRelays)
|
||||
const pool = new RelayPool([config.nostrRelay])
|
||||
pool.on('open', relay => {
|
||||
relay.subscribe('subid', { limit: 5, kinds: [0], authors: [pubHex] })
|
||||
setLoaded(true)
|
||||
|
||||
@@ -18,6 +18,7 @@ function PublicRead (props) {
|
||||
const { bchWalletState } = props.appData
|
||||
const [posts, setPosts] = useState([])
|
||||
const [loaded, setLoaded] = useState(false)
|
||||
const [profilePictureError, setProfilePictureError] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
// Get Last post from a author
|
||||
@@ -49,6 +50,14 @@ function PublicRead (props) {
|
||||
}
|
||||
}, [bchWalletState, loaded, npub])
|
||||
|
||||
const handleProfilePictureError = () => {
|
||||
setProfilePictureError(true)
|
||||
}
|
||||
|
||||
const handleProfilePictureLoad = () => {
|
||||
setProfilePictureError(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<Container className='mt-4 mb-5'>
|
||||
{/* Nostr Feed Section */}
|
||||
@@ -76,7 +85,20 @@ function PublicRead (props) {
|
||||
background: 'linear-gradient(45deg, #6c757d, #495057)'
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faUser} size='1x' color='#7c7c7d' />
|
||||
{props.profile?.picture && !profilePictureError
|
||||
? (
|
||||
<img
|
||||
src={props.profile.picture}
|
||||
alt='Profile'
|
||||
className='rounded-circle w-100 h-100'
|
||||
style={{ objectFit: 'cover' }}
|
||||
onError={handleProfilePictureError}
|
||||
onLoad={handleProfilePictureLoad}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<FontAwesomeIcon icon={faUser} size='1x' color='#7c7c7d' />
|
||||
)}
|
||||
</div>
|
||||
<div className='flex-grow-1'>
|
||||
<div className='fw-bold mb-1'>{props.profile?.name}</div>
|
||||
|
||||
Reference in New Issue
Block a user