Skip to content

Commit

Permalink
Feat comment Nostr (keep-starknet-strange#123)
Browse files Browse the repository at this point in the history
* add comment send & fetch + fix send note + fix hooks query tanstack with params

* fix eslint and unused var

* run yarn format

* import styles native

* only use pool for multi relays push + delete var

* run yarn lint:fix
  • Loading branch information
MSghais authored May 28, 2024
1 parent 391e3f9 commit 9b5a105
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 171 deletions.
160 changes: 99 additions & 61 deletions JoyboyCommunity/README.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,99 @@
## Mobile

Joyboy Mobile folder in React-native with Expo.
Pick a good first issue with the mobile labels, and let's contribute and keep building cool things in Open-source.

### Test

To test the project, run:

```bash
cd JoyboyCommunity
yarn install
yarn start
```

Select Expo web, Android or IOS. You can scan it with Expo GO on your phone.

### Screens of the mobile app
Recent implementation PoC on React Native.
Here is what we have on the mobile app on the first days, contributions welcome!
Check the issues with the "mobile" labels.

Done:
- Create or import Nostr account
- Feed for notes
- See user page with notes
- Create note on Nostr

WIP:
- Read Nostr tags content
- View user page details: followers and follows, replies, likes, repost with all details of the users.
- Note interactions: Replies, Likes, Report, Tips
- My profile: Update my profile
- Feed: Search, Trending fees, For you, Discover
- DM with private message: NIP-17
- Public chat: NIP-28

[UI/UX proposal for video discussions](https://github.com/keep-starknet-strange/joyboy/discussions/48#discussion-6683225)

[UI video discussions](https://t.me/JoyboyStarknet/206/397)


Home page:

<img src="../resources/screens/onboard.png" alt="onboard" height="300"/>

Create Nostr account

<img src="../resources/screens/create-account.png" alt="create account" height="300"/>

Feed by default:

<img src="../resources/screens/feed-default.png" alt="feed default" height="300"/>

User feed with notes:

<img src="../resources/screens/user-profile-details.png" alt="user-profile-details" height="300"/>

My profile page: WIP

<img src="../resources/screens/my-profile.png" alt="my-profile" height="300"/>
## Mobile

Joyboy Mobile folder in React-native with Expo.
Pick a good first issue with the mobile labels, and let's contribute and keep building cool things in Open-source.

### Test

To test the project, run:

```bash
cd JoyboyCommunity
yarn install
yarn start
```

Select Expo web, Android or IOS. You can scan it with Expo GO on your phone.

### Screens of the mobile app
Recent implementation PoC on React Native.
Here is what we have on the mobile app on the first days, contributions welcome!
Check the issues with the "mobile" labels.

Done:
- Create or import Nostr account
- Feed for notes
- See user page with notes
- Create note on Nostr

WIP:
- Read Nostr tags content
- View user page details: followers and follows, replies, likes, repost with all details of the users.
- Note interactions: Replies, Likes, Report, Tips
- My profile: Update my profile
- Feed: Search, Trending fees, For you, Discover
- DM with private message: NIP-17
- Public chat: NIP-28

[UI/UX proposal for video discussions](https://github.com/keep-starknet-strange/joyboy/discussions/48#discussion-6683225)

[UI video discussions](https://t.me/JoyboyStarknet/206/397)


Home page:

<img src="../resources/screens/onboard.png" alt="onboard" height="300"/>

Create Nostr account

<img src="../resources/screens/create-account.png" alt="create account" height="300"/>

Feed by default:

<img src="../resources/screens/feed-default.png" alt="feed default" height="300"/>

User feed with notes:

<img src="../resources/screens/user-profile-details.png" alt="user-profile-details" height="300"/>

My profile page: WIP

<img src="../resources/screens/my-profile.png" alt="my-profile" height="300"/>


## How Nostr work

- [Nostr Implementation Possibilities](https://github.com/nostr-protocol/nips)
- [JoinStr: Decentralized CoinJoin Implementation Using Nostr](https://www.nobsbitcoin.com/joinstr-decentralized-coinjoin-implementation-using-nostr/)

### NIP-1
Nostr event are described like this on NIP-1:

```ts
export interface Event {
kind: number; // 1 for note, 0 for profile,
tags: string[][]; // NIP-10 for comment root and reply
//
content: string;
created_at: number;
pubkey: string;
id: string;
sig: string;
[verifiedSymbol]?: boolean;
}
```

### NIP-10
- [NIP-10](https://github.com/nostr-protocol/nips/blob/master/10.md)

```ts
/** On the Tags string[][] of the note, you can check if the note are:
* repost, quote, reply root, reply comment, or a simple note.
*
* filter for tags :
* ["e", "note_pubkey", "relay_url", "marker as reply | root | mention", "pubkey_author"]
* ["p", "id_note","p1_note_reply"]
*
*/
```

23 changes: 18 additions & 5 deletions JoyboyCommunity/src/context/NostrContext.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,40 @@
import NDK, {NDKNip07Signer} from '@nostr-dev-kit/ndk';
import {SimplePool} from 'nostr-tools';
import {Relay, SimplePool} from 'nostr-tools';
import {createContext, useContext, useMemo} from 'react';

import {RELAYS_PROD} from '../utils/relay';
import {JOYBOY_RELAYS, RELAYS_PROD} from '../utils/relay';

export type NostrContextType = {
pool: SimplePool;
relays: string[];
relayJoyboy?: Relay;
othersRelays?: string[];
connectRelayJoyboy: () => Promise<Relay>;
ndk: NDK;
};

export const NostrContext = createContext<NostrContextType | null>(null);

export const NostrProvider: React.FC<React.PropsWithChildren> = ({children}) => {
const pool = useMemo(() => new SimplePool(), []);
const relays = RELAYS_PROD;

const relays = JOYBOY_RELAYS;
const othersRelays = RELAYS_PROD;

/** This Websocket connection to the Relay need to be closed after each utilization*/
const connectRelayJoyboy = async () => {
const relayJoyboy = await Relay.connect(JOYBOY_RELAYS[0]);
return relayJoyboy;
};
const ndk = useMemo(() => {
const nip07signer = new NDKNip07Signer();
return new NDK({signer: nip07signer});
}, []);

return <NostrContext.Provider value={{pool, relays, ndk}}>{children}</NostrContext.Provider>;
return (
<NostrContext.Provider value={{pool, relays, ndk, othersRelays, connectRelayJoyboy}}>
{children}
</NostrContext.Provider>
);
};

export const useNostrContext = () => {
Expand Down
62 changes: 47 additions & 15 deletions JoyboyCommunity/src/hooks/useNostr.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
import {Event as EventNostr} from 'nostr-tools';
import {Event as EventNostr, SimplePool} from 'nostr-tools';
import {finalizeEvent, NostrEvent, parseReferences, VerifiedEvent, verifyEvent} from 'nostr-tools';

import {useNostrContext} from '../context/NostrContext';
import {IPoolEventsByQuery, IPoolEventsFromPubkey, ISendNotePayload, IUserQuery} from '../types';
import {JOYBOY_RELAYS} from '../utils/relay';

export const useGetPoolEventById = (id: string) => {
const {pool, relays} = useNostrContext();
Expand Down Expand Up @@ -73,16 +74,41 @@ export const useGetPoolUserQuery = ({id = '0', ...query}: IUserQuery) => {
});
};

export const useGetPoolEventsByQuery = ({ids = ['1', '3'], ...query}: IPoolEventsByQuery) => {
const {pool, relays} = useNostrContext();
export const useGetPoolEventsByQuery = ({
ids = ['1', '3'],
kinds = [1],
filter,
pool = new SimplePool(),
relaysToUsed,
}: IPoolEventsByQuery) => {
return useQuery({
queryFn: () =>
pool?.querySync(relaysToUsed, {
ids,
kinds,
...filter,
}),
queryKey: ['getPoolEventsByQuery', ids, kinds, filter, relaysToUsed, pool],
placeholderData: [],
});
};

export const useGetPoolEventsTagsByQuery = ({
ids,
kinds = [1],
filter,
pool = new SimplePool(),
relaysToUsed,
}: IPoolEventsByQuery) => {
return useQuery({
queryFn: () =>
pool.querySync(query.relaysProps ?? relays, {
pool?.querySync(relaysToUsed, {
ids,
...query.filter,
kinds,
...filter,
}),
queryKey: ['getPoolEventsByQuery', query.relaysProps, query.filter, ids],
enabled: !!filter?.search,
queryKey: ['getPoolEventsByQuery', ids, kinds, filter, pool, relaysToUsed],
placeholderData: [],
});
};
Expand Down Expand Up @@ -110,22 +136,28 @@ export const useGetUser = (pubkey: string) => {
});
};

/** Check if a note is valid and publish not on relayer if event valid */
export const useSendNote = () => {
const queryClient = useQueryClient();
const {pool, relays, connectRelayJoyboy} = useNostrContext();

return useMutation({
mutationFn: sendNote,
onSuccess(data) {
mutationFn: isValidSendNote,
async onSuccess(data) {
queryClient.invalidateQueries({
queryKey: [''],
});
const event = data?.event;
/** @TODO add option to send note on different relays and add list of relays */
await pool.publish(JOYBOY_RELAYS, event);
return data;
},
});
};

// FUNCTIONS

export const sendNote = async ({
export const isValidSendNote = async ({
content,
sk,
tags,
Expand All @@ -147,17 +179,17 @@ export const sendNote = async ({

const isGood = verifyEvent(event);

if (isGood) {
return {
event,
isValid: true,
};
} else {
if (!isGood) {
return {
event,
isValid: false,
};
}

return {
event,
isValid: true,
};
} catch (e) {
console.log('issue sendNote', e);
return {
Expand Down
Loading

0 comments on commit 9b5a105

Please sign in to comment.