diff --git a/apps/data-backend/src/services/telegram-app.ts b/apps/data-backend/src/services/telegram-app.ts index a505f35f..056d8e3f 100644 --- a/apps/data-backend/src/services/telegram-app.ts +++ b/apps/data-backend/src/services/telegram-app.ts @@ -33,7 +33,7 @@ export function launchBot(token:string) { // Handle stop events enableGracefulStop(bot) - return bot + // return bot } catch (e) { console.log("launchBot error", e) } diff --git a/apps/mobile/src/app/Router.tsx b/apps/mobile/src/app/Router.tsx index 0277d924..93d30c87 100644 --- a/apps/mobile/src/app/Router.tsx +++ b/apps/mobile/src/app/Router.tsx @@ -10,6 +10,7 @@ import {Icon} from '../components'; import {Navbar} from '../components/Navbar'; import {useStyles, useTheme} from '../hooks'; import GroupChatDetail from '../modules/Group/groupDetail/GroupChatDetail'; +import GroupChatGroupRequest from '../modules/Group/memberAction/ViewRequest'; import GroupChat from '../modules/Group/message/GroupMessage'; import AuthSidebar from '../modules/Layout/auth-sidebar'; import DegensSidebar from '../modules/Layout/degens-sidebar'; @@ -45,7 +46,6 @@ import { RootStackParams, } from '../types'; import {retrievePublicKey} from '../utils/storage'; -import GroupChatGroupRequest from '../modules/Group/memberAction/ViewRequest'; const DrawerStack = createDrawerNavigator(); const RootStack = createNativeStackNavigator(); const AuthStack = createDrawerNavigator(); diff --git a/apps/mobile/src/assets/icons.tsx b/apps/mobile/src/assets/icons.tsx index 98ae5fd4..db5bd738 100644 --- a/apps/mobile/src/assets/icons.tsx +++ b/apps/mobile/src/assets/icons.tsx @@ -400,7 +400,6 @@ export const RepostIcon: React.FC = (props) => { ); }; - export const LikeIcon: React.FC = (props) => { return ( @@ -426,14 +425,10 @@ export const BookmarkIcon: React.FC = (props) => ( export const BookmarkFillIcon: React.FC = (props) => ( - + ); - export const LikeFillIcon: React.FC = (props) => { return ( diff --git a/apps/mobile/src/components/Filter/index.tsx b/apps/mobile/src/components/Filter/index.tsx index b517e409..69179c61 100644 --- a/apps/mobile/src/components/Filter/index.tsx +++ b/apps/mobile/src/components/Filter/index.tsx @@ -11,8 +11,8 @@ import { } from 'react-native'; import {useStyles} from '../../hooks'; +import {SORT_OPTION_EVENT_NOSTR} from '../../types/nostr'; import stylesheet from './styles'; -import { SORT_OPTION_EVENT_NOSTR } from '../../types/nostr'; interface IFilterMenuProps { visible: boolean; @@ -31,7 +31,6 @@ const NDK_KIND_OPTIONS = [ {label: 'Metadata', value: NDKKind.Metadata}, ]; - // const SORT_OPTIONS = [ // {label: 'Time', value: 'time'}, // {label: 'For You', value: 'forYou'}, @@ -78,7 +77,10 @@ const FilterMenu: React.FC = ({ {SORT_OPTIONS.map((option) => ( onSortChange(option.value.toString())} > {option.label} diff --git a/apps/mobile/src/components/HeaderScreen/index.tsx b/apps/mobile/src/components/HeaderScreen/index.tsx index 741ae898..46ad86b2 100644 --- a/apps/mobile/src/components/HeaderScreen/index.tsx +++ b/apps/mobile/src/components/HeaderScreen/index.tsx @@ -2,10 +2,10 @@ import {Image, View} from 'react-native'; import {SafeAreaView} from 'react-native-safe-area-context'; import {useStyles, useTheme} from '../../hooks'; +import {Spacing} from '../../styles'; +import {Divider} from '../Divider'; import {Text} from '../Text'; import stylesheet from './styles'; -import {Divider} from '../Divider'; -import {Spacing} from '../../styles'; export type HeaderProps = { showLogo?: boolean; diff --git a/apps/mobile/src/components/HeaderScreen/styles.ts b/apps/mobile/src/components/HeaderScreen/styles.ts index ba236ddc..ab81051b 100644 --- a/apps/mobile/src/components/HeaderScreen/styles.ts +++ b/apps/mobile/src/components/HeaderScreen/styles.ts @@ -1,5 +1,3 @@ -import {StyleSheet} from 'react-native'; - import {Spacing, ThemedStyleSheet} from '../../styles'; export default ThemedStyleSheet((theme) => ({ diff --git a/apps/mobile/src/components/Input/styles.ts b/apps/mobile/src/components/Input/styles.ts index b95b2a48..7306b8a1 100644 --- a/apps/mobile/src/components/Input/styles.ts +++ b/apps/mobile/src/components/Input/styles.ts @@ -1,7 +1,7 @@ import {Spacing, ThemedStyleSheet, Typography} from '../../styles'; export default ThemedStyleSheet( - (theme, error: boolean, left: boolean, right: boolean, paddingRight: boolean = true) => ({ + (theme, error: boolean, left: boolean, right: boolean, paddingRight = true) => ({ container: { width: '100%', }, diff --git a/apps/mobile/src/components/Navbar/index.tsx b/apps/mobile/src/components/Navbar/index.tsx index 3e36633f..e5e552e0 100644 --- a/apps/mobile/src/components/Navbar/index.tsx +++ b/apps/mobile/src/components/Navbar/index.tsx @@ -1,15 +1,15 @@ import * as React from 'react'; -import { Image, Text, TouchableOpacity, View } from 'react-native'; +import {Image, Text, TouchableOpacity, View} from 'react-native'; -import { useStyles, useWindowDimensions } from '../../hooks'; -import { Icon } from '../Icon'; +import {useStyles, useWindowDimensions} from '../../hooks'; +import {Icon} from '../Icon'; import stylesheet from './styles'; interface CustomHeaderInterface { title?: string; navigation?: any; showLogo?: boolean; } -export const Navbar = ({ title, navigation, showLogo }: CustomHeaderInterface) => { +export const Navbar = ({title, navigation, showLogo}: CustomHeaderInterface) => { const styles = useStyles(stylesheet); const dimensions = useWindowDimensions(); const isDesktop = React.useMemo(() => { @@ -27,18 +27,17 @@ export const Navbar = ({ title, navigation, showLogo }: CustomHeaderInterface) = )} {title} - {!isDesktop && + {!isDesktop && ( navigation?.openDrawer()} style={styles.burgerIcon}> - } + )} {/* {isDesktop && navigation?.openDrawer()} style={styles.burgerIcon}> } */} - ); }; diff --git a/apps/mobile/src/components/PrivateKeyImport/index.tsx b/apps/mobile/src/components/PrivateKeyImport/index.tsx index 688404d3..a56c0cd1 100644 --- a/apps/mobile/src/components/PrivateKeyImport/index.tsx +++ b/apps/mobile/src/components/PrivateKeyImport/index.tsx @@ -5,18 +5,14 @@ import {useState} from 'react'; import {TouchableOpacity, View} from 'react-native'; import {CopyIconStack, LockIcon} from '../../assets/icons'; +import {useWindowDimensions} from '../../hooks'; import {useToast} from '../../hooks/modals'; import {getPublicKeyFromSecret} from '../../utils/keypair'; -import { - retrieveAndDecryptPrivateKey, - retrievePassword, - retrievePublicKey, -} from '../../utils/storage'; +import {retrieveAndDecryptPrivateKey, retrievePublicKey} from '../../utils/storage'; import {Button} from '../Button'; import {Input} from '../Input'; import {Text} from '../Text'; import styles from './styles'; -import {useWindowDimensions} from '../../hooks'; export const PrivateKeyImport: React.FC = () => { const {publicKey, isExtension, privateKey, setAuth} = useAuth(); diff --git a/apps/mobile/src/components/PrivateMessages/Chat/index.tsx b/apps/mobile/src/components/PrivateMessages/Chat/index.tsx index 9b3f2047..77a8aa80 100644 --- a/apps/mobile/src/components/PrivateMessages/Chat/index.tsx +++ b/apps/mobile/src/components/PrivateMessages/Chat/index.tsx @@ -1,42 +1,47 @@ import React from 'react'; -import { ConversationType } from '../../../types/messages'; -import { useStyles } from '../../../hooks'; -import { View, Image, Text } from 'react-native'; -import { MessageInput } from '../PrivateMessageInput'; -import { MessagesList } from '../MessagesList.tsx'; +import {Image, Text, View} from 'react-native'; + +import {useStyles} from '../../../hooks'; +import {ConversationType} from '../../../types/messages'; +import {IconButton} from '../../IconButton'; +import {MessagesList} from '../MessagesList.tsx'; +import {MessageInput} from '../PrivateMessageInput'; import stylesheet from './styles'; -import { IconButton } from '../../IconButton'; export type ChatProps = { - conversation: ConversationType; - handleGoBack: () => void; + conversation: ConversationType; + handleGoBack: () => void; }; -export const Chat: React.FC = ({ conversation, handleGoBack }) => { - - const styles = useStyles(stylesheet); - const user = conversation.user; - const avatar = user.avatar ? {uri: user.avatar } : require('../../../assets/pepe-logo.png'); +export const Chat: React.FC = ({conversation, handleGoBack}) => { + const styles = useStyles(stylesheet); + const user = conversation.user; + const avatar = user.avatar ? {uri: user.avatar} : require('../../../assets/pepe-logo.png'); - const handleSendMessage = (message: string) => { - //todo: integrate hook here - //todo: encrypt message - //todo: send message - }; + const handleSendMessage = (message: string) => { + //todo: integrate hook here + //todo: encrypt message + //todo: send message + }; - return ( - <> - - - - - {user.name} - - - - - - - - ); + return ( + <> + + + + + {user.name} + + + + + + + + ); }; diff --git a/apps/mobile/src/components/PrivateMessages/Chat/styles.ts b/apps/mobile/src/components/PrivateMessages/Chat/styles.ts index cc7b3ae9..de16ba95 100644 --- a/apps/mobile/src/components/PrivateMessages/Chat/styles.ts +++ b/apps/mobile/src/components/PrivateMessages/Chat/styles.ts @@ -1,36 +1,36 @@ -import { ThemedStyleSheet } from "../../../styles"; +import {ThemedStyleSheet} from '../../../styles'; export default ThemedStyleSheet((theme) => ({ - container: { - flex: 1, - backgroundColor: theme.colors.background, - }, - header: { - padding: 10, - borderBottomWidth: 1, - borderBottomColor: theme.colors.divider, - alignItems: 'center', - justifyContent: 'center', - position: 'relative', - }, - headerContent: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - }, - backButton: { - position: 'absolute', - left: 10, - }, - avatar: { - width: 50, - height: 50, - borderRadius: 25, - marginBottom: 5, - }, - name: { - fontSize: 16, - fontWeight: 'bold', - color: theme.colors.text, - }, + container: { + flex: 1, + backgroundColor: theme.colors.background, + }, + header: { + padding: 10, + borderBottomWidth: 1, + borderBottomColor: theme.colors.divider, + alignItems: 'center', + justifyContent: 'center', + position: 'relative', + }, + headerContent: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + backButton: { + position: 'absolute', + left: 10, + }, + avatar: { + width: 50, + height: 50, + borderRadius: 25, + marginBottom: 5, + }, + name: { + fontSize: 16, + fontWeight: 'bold', + color: theme.colors.text, + }, })); diff --git a/apps/mobile/src/components/PrivateMessages/Conversation/index.tsx b/apps/mobile/src/components/PrivateMessages/Conversation/index.tsx index f2763bb2..25bdf9ea 100644 --- a/apps/mobile/src/components/PrivateMessages/Conversation/index.tsx +++ b/apps/mobile/src/components/PrivateMessages/Conversation/index.tsx @@ -1,28 +1,28 @@ import React from 'react'; -import { Pressable, View, Text, Image } from 'react-native'; +import {Image, Pressable, Text, View} from 'react-native'; + +import {useStyles} from '../../../hooks'; +import {ConversationType} from '../../../types/messages'; import stylesheet from './styles'; -import { useStyles } from '../../../hooks'; -import { ConversationType } from '../../../types/messages'; export type ConversationPreviewProps = { - conversation: ConversationType; - onPressed: () => void; + conversation: ConversationType; + onPressed: () => void; }; export const Conversation: React.FC = ({conversation, onPressed}) => { + const styles = useStyles(stylesheet); - const styles = useStyles(stylesheet); - - const user = conversation.user; - const avatar = user.avatar ? {uri: user.avatar } : require('../../../assets/pepe-logo.png'); + const user = conversation.user; + const avatar = user.avatar ? {uri: user.avatar} : require('../../../assets/pepe-logo.png'); - return ( - - - - {user.name} - {user.handle} - - - ); + return ( + + + + {user.name} + {user.handle} + + + ); }; diff --git a/apps/mobile/src/components/PrivateMessages/Conversation/styles.ts b/apps/mobile/src/components/PrivateMessages/Conversation/styles.ts index a7b5cc8b..0e33e0e8 100644 --- a/apps/mobile/src/components/PrivateMessages/Conversation/styles.ts +++ b/apps/mobile/src/components/PrivateMessages/Conversation/styles.ts @@ -1,29 +1,29 @@ -import { ThemedStyleSheet } from "../../../styles"; +import {ThemedStyleSheet} from '../../../styles'; export default ThemedStyleSheet((theme) => ({ - container: { - flexDirection: 'row', - alignItems: 'center', - padding: 10, - borderBottomWidth: 1, - borderBottomColor: theme.colors.divider, - }, - avatar: { - width: 50, - height: 50, - borderRadius: 25, - marginRight: 10, - }, - textContainer: { - flex: 1, - }, - name: { - fontSize: 16, - fontWeight: 'bold', - color: theme.colors.text, - }, - handle: { - fontSize: 14, - color: theme.colors.textSecondary - }, + container: { + flexDirection: 'row', + alignItems: 'center', + padding: 10, + borderBottomWidth: 1, + borderBottomColor: theme.colors.divider, + }, + avatar: { + width: 50, + height: 50, + borderRadius: 25, + marginRight: 10, + }, + textContainer: { + flex: 1, + }, + name: { + fontSize: 16, + fontWeight: 'bold', + color: theme.colors.text, + }, + handle: { + fontSize: 14, + color: theme.colors.textSecondary, + }, })); diff --git a/apps/mobile/src/components/PrivateMessages/FormPrivateMessage/index.tsx b/apps/mobile/src/components/PrivateMessages/FormPrivateMessage/index.tsx index a7a98494..35c0e8a2 100644 --- a/apps/mobile/src/components/PrivateMessages/FormPrivateMessage/index.tsx +++ b/apps/mobile/src/components/PrivateMessages/FormPrivateMessage/index.tsx @@ -1,104 +1,105 @@ +import {NDKUser} from '@nostr-dev-kit/ndk'; +import {useQueryClient} from '@tanstack/react-query'; +import {useSendPrivateMessage} from 'afk_nostr_sdk'; import React from 'react'; -import { ConversationType } from '../../../types/messages'; -import { useStyles } from '../../../hooks'; -import { View, Image, Text } from 'react-native'; -import { MessagesList } from '../MessagesList.tsx'; -import stylesheet from './styles'; -import { IconButton } from '../../IconButton'; -import { useSendPrivateMessage } from 'afk_nostr_sdk'; -import { NDKUser } from '@nostr-dev-kit/ndk'; -import { useToast } from '../../../hooks/modals'; -import { useQueryClient } from '@tanstack/react-query'; -import { Input } from '../../Input'; -import { MessageInput } from '../PrivateMessageInput'; -import { KeyboardFixedView } from '../../Skeleton/KeyboardFixedView'; -import { Divider } from '../../Divider'; +import {View} from 'react-native'; +import {useStyles} from '../../../hooks'; +import {useToast} from '../../../hooks/modals'; +import {Divider} from '../../Divider'; +import {IconButton} from '../../IconButton'; +import {Input} from '../../Input'; +import {KeyboardFixedView} from '../../Skeleton/KeyboardFixedView'; +import stylesheet from './styles'; interface IFormPrivateMessage { - publicKey?: string; - user?: NDKUser; - receiverPublicKeyProps?: string + publicKey?: string; + user?: NDKUser; + receiverPublicKeyProps?: string; } -export const FormPrivateMessage: React.FC = ({ user, publicKey, receiverPublicKeyProps }) => { - const styles = useStyles(stylesheet); - const avatar = user?.profile?.banner ?? require('../../../assets/pepe-logo.png'); - - const [receiverPublicKey, setReceiverPublicKey] = React.useState(receiverPublicKeyProps) - const [content, setContent] = React.useState() - const [message, setMessage] = React.useState() - const sendPrivateMessage = useSendPrivateMessage() - const { showToast } = useToast() - const queryClient = useQueryClient(); - - const sendMessage = async (message: string) => { - - // if (!message) { - // showToast({ title: "Please add a content", type: "error" }) - // return; - // } - - if (!receiverPublicKey) { - showToast({ title: "Please choose a Nostr public key", type: "error" }) - return; - } +export const FormPrivateMessage: React.FC = ({ + user, + publicKey, + receiverPublicKeyProps, +}) => { + const styles = useStyles(stylesheet); + const avatar = user?.profile?.banner ?? require('../../../assets/pepe-logo.png'); - //todo: integrate hook here - //todo: encrypt message - //todo: send message - await sendPrivateMessage.mutateAsync( - { receiverPublicKeyProps: receiverPublicKey, content: message, }, - { - onSuccess: () => { - showToast({title:"Message sent", type:"success"}) + const [receiverPublicKey, setReceiverPublicKey] = React.useState(receiverPublicKeyProps); + const [content, setContent] = React.useState(); + const [message, setMessage] = React.useState(); + const sendPrivateMessage = useSendPrivateMessage(); + const {showToast} = useToast(); + const queryClient = useQueryClient(); - }, - }, - ); + const sendMessage = async (message: string) => { + // if (!message) { + // showToast({ title: "Please add a content", type: "error" }) + // return; + // } - }; + if (!receiverPublicKey) { + showToast({title: 'Please choose a Nostr public key', type: 'error'}); + return; + } - const handleSendMessage = () => { + //todo: integrate hook here + //todo: encrypt message + //todo: send message + await sendPrivateMessage.mutateAsync( + {receiverPublicKeyProps: receiverPublicKey, content: message}, + { + onSuccess: () => { + showToast({title: 'Message sent', type: 'success'}); + }, + }, + ); + }; - if (!message) { - showToast({ title: "Please add a content", type: "error" }) - return; - } - if (!receiverPublicKey) { - showToast({ title: "Please choose a Nostr public key", type: "error" }) - return; - } + const handleSendMessage = () => { + if (!message) { + showToast({title: 'Please add a content', type: 'error'}); + return; + } + if (!receiverPublicKey) { + showToast({title: 'Please choose a Nostr public key', type: 'error'}); + return; + } - sendMessage(message) - } + sendMessage(message); + }; - return ( - <> - {/* + return ( + <> + {/* {user.name} */} - - - - + + + + - - + + - - - - {/* */} - - - ); + + + + {/* */} + + + ); }; diff --git a/apps/mobile/src/components/PrivateMessages/FormPrivateMessage/styles.ts b/apps/mobile/src/components/PrivateMessages/FormPrivateMessage/styles.ts index 84fa53ae..8515a2a4 100644 --- a/apps/mobile/src/components/PrivateMessages/FormPrivateMessage/styles.ts +++ b/apps/mobile/src/components/PrivateMessages/FormPrivateMessage/styles.ts @@ -1,51 +1,51 @@ -import { Spacing, ThemedStyleSheet } from "../../../styles"; +import {Spacing, ThemedStyleSheet} from '../../../styles'; export default ThemedStyleSheet((theme) => ({ - container: { - flex: 1, - backgroundColor: theme.colors.background, - }, - header: { - padding: 10, - borderBottomWidth: 1, - borderBottomColor: theme.colors.divider, - alignItems: 'center', - justifyContent: 'center', - position: 'relative', - }, - headerContent: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - }, - backButton: { - position: 'absolute', - left: 10, - }, - avatar: { - width: 50, - height: 50, - borderRadius: 25, - marginBottom: 5, - }, - name: { - fontSize: 16, - fontWeight: 'bold', - color: theme.colors.text, - }, - commentInputContainer: { - backgroundColor: theme.colors.surface, - }, - commentInputContent: { - gap: Spacing.small, - flexDirection: 'row', - alignItems: 'center', - paddingVertical: Spacing.xsmall, - paddingHorizontal: Spacing.pagePadding, - backgroundColor: theme.colors.surface, - }, - commentInput: { - flex: 1, - width: 'auto', - }, + container: { + flex: 1, + backgroundColor: theme.colors.background, + }, + header: { + padding: 10, + borderBottomWidth: 1, + borderBottomColor: theme.colors.divider, + alignItems: 'center', + justifyContent: 'center', + position: 'relative', + }, + headerContent: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + backButton: { + position: 'absolute', + left: 10, + }, + avatar: { + width: 50, + height: 50, + borderRadius: 25, + marginBottom: 5, + }, + name: { + fontSize: 16, + fontWeight: 'bold', + color: theme.colors.text, + }, + commentInputContainer: { + backgroundColor: theme.colors.surface, + }, + commentInputContent: { + gap: Spacing.small, + flexDirection: 'row', + alignItems: 'center', + paddingVertical: Spacing.xsmall, + paddingHorizontal: Spacing.pagePadding, + backgroundColor: theme.colors.surface, + }, + commentInput: { + flex: 1, + width: 'auto', + }, })); diff --git a/apps/mobile/src/components/PrivateMessages/MessagesList.tsx/index.tsx b/apps/mobile/src/components/PrivateMessages/MessagesList.tsx/index.tsx index e05c0869..70e0ca4c 100644 --- a/apps/mobile/src/components/PrivateMessages/MessagesList.tsx/index.tsx +++ b/apps/mobile/src/components/PrivateMessages/MessagesList.tsx/index.tsx @@ -1,17 +1,18 @@ import React from 'react'; -import { View, Text, FlatList } from 'react-native'; -import { Message } from '../../../types/messages'; +import {FlatList, Text, View} from 'react-native'; + +import {useStyles} from '../../../hooks'; +import {Message} from '../../../types/messages'; import stylesheet from './styles'; -import { useStyles } from '../../../hooks'; export type MessagesListProps = { - messages: Message[]; + messages: Message[]; }; -export const MessagesList: React.FC = ({ messages }) => { +export const MessagesList: React.FC = ({messages}) => { const styles = useStyles(stylesheet); - const renderItem = ({ item }: { item: Message }) => ( + const renderItem = ({item}: {item: Message}) => ( {item.message} diff --git a/apps/mobile/src/components/PrivateMessages/MessagesList.tsx/styles.ts b/apps/mobile/src/components/PrivateMessages/MessagesList.tsx/styles.ts index 7ff8d3c0..cb316889 100644 --- a/apps/mobile/src/components/PrivateMessages/MessagesList.tsx/styles.ts +++ b/apps/mobile/src/components/PrivateMessages/MessagesList.tsx/styles.ts @@ -1,25 +1,25 @@ -import { ThemedStyleSheet } from '../../../styles'; +import {ThemedStyleSheet} from '../../../styles'; export default ThemedStyleSheet((theme) => ({ - list: { - flex: 1, - padding: 10, - }, - messageContainer: { - borderRadius: 10, - padding: 10, - marginVertical: 5, - maxWidth: '80%', - }, - userMessage: { - alignSelf: 'flex-end', - backgroundColor: theme.colors.primary, - }, - otherMessage: { - alignSelf: 'flex-start', - backgroundColor: theme.colors.primaryLight, - }, - messageText: { - color: theme.colors.text, - }, + list: { + flex: 1, + padding: 10, + }, + messageContainer: { + borderRadius: 10, + padding: 10, + marginVertical: 5, + maxWidth: '80%', + }, + userMessage: { + alignSelf: 'flex-end', + backgroundColor: theme.colors.primary, + }, + otherMessage: { + alignSelf: 'flex-start', + backgroundColor: theme.colors.primaryLight, + }, + messageText: { + color: theme.colors.text, + }, })); diff --git a/apps/mobile/src/components/PrivateMessages/PrivateMessageInput/index.tsx b/apps/mobile/src/components/PrivateMessages/PrivateMessageInput/index.tsx index d72b59a8..7c7b7f8c 100644 --- a/apps/mobile/src/components/PrivateMessages/PrivateMessageInput/index.tsx +++ b/apps/mobile/src/components/PrivateMessages/PrivateMessageInput/index.tsx @@ -1,17 +1,18 @@ -import React, { useState } from 'react'; -import { View } from 'react-native'; +import React, {useState} from 'react'; +import {View} from 'react-native'; + +import {useStyles} from '../../../hooks'; +import {Divider} from '../../Divider'; +import {IconButton} from '../../IconButton'; +import {Input} from '../../Input'; +import {KeyboardFixedView} from '../../Skeleton/KeyboardFixedView'; import stylesheet from './styles'; -import { KeyboardFixedView } from '../../Skeleton/KeyboardFixedView'; -import { Divider } from '../../Divider'; -import { Input } from '../../Input'; -import { IconButton } from '../../IconButton'; -import { useStyles } from '../../../hooks'; export type MessageInputProps = { - onSend: (message: string) => void; + onSend: (message: string) => void; }; -export const MessageInput: React.FC = ({ onSend }) => { +export const MessageInput: React.FC = ({onSend}) => { const styles = useStyles(stylesheet); const [message, setMessage] = useState(''); @@ -24,18 +25,18 @@ export const MessageInput: React.FC = ({ onSend }) => { return ( - + - - + + - - - + + + ); }; diff --git a/apps/mobile/src/components/PrivateMessages/PrivateMessageInput/styles.ts b/apps/mobile/src/components/PrivateMessages/PrivateMessageInput/styles.ts index 410ab80c..82622ae8 100644 --- a/apps/mobile/src/components/PrivateMessages/PrivateMessageInput/styles.ts +++ b/apps/mobile/src/components/PrivateMessages/PrivateMessageInput/styles.ts @@ -1,7 +1,7 @@ -import { Spacing, ThemedStyleSheet } from "../../../styles"; +import {Spacing, ThemedStyleSheet} from '../../../styles'; export default ThemedStyleSheet((theme) => ({ - commentInputContainer: { + commentInputContainer: { backgroundColor: theme.colors.surface, }, commentInputContent: { diff --git a/apps/mobile/src/components/RelaysConfig/index.tsx b/apps/mobile/src/components/RelaysConfig/index.tsx index b554159b..383799c0 100644 --- a/apps/mobile/src/components/RelaysConfig/index.tsx +++ b/apps/mobile/src/components/RelaysConfig/index.tsx @@ -115,8 +115,10 @@ export const RelaysConfig: React.FC = () => { fontSize: 12, }} onPress={() => removeRelay(r)} - children="Remove" - /> + // children="Remove" + > + Remove + ); @@ -138,8 +140,10 @@ export const RelaysConfig: React.FC = () => { fontSize: 12, }} onPress={() => addRelay(relayToAdd)} - children="+" - /> + // children="+" + > + + + } paddingRight={false} value={relayToAdd} diff --git a/apps/mobile/src/components/index.ts b/apps/mobile/src/components/index.ts index b8174134..e6909bda 100644 --- a/apps/mobile/src/components/index.ts +++ b/apps/mobile/src/components/index.ts @@ -11,6 +11,9 @@ export {Modal} from './Modal'; export {Modalize} from './Modalize'; export {Picker} from './Picker'; export {PickerContainer} from './PickerContainer'; +export {Chat} from './PrivateMessages/Chat'; +export {Conversation} from './PrivateMessages/Conversation'; +export {FormPrivateMessage} from './PrivateMessages/FormPrivateMessage'; export {InputAccessoryView} from './Skeleton/InputAccessoryView'; export {KeyboardFixedView} from './Skeleton/KeyboardFixedView'; export {RootScreenContainer} from './Skeleton/RootScreenContainer'; @@ -18,6 +21,3 @@ export {SquareInput} from './SquareInput'; export {Text} from './Text'; export {TextButton} from './TextButton'; export {Toast} from './Toast'; -export {Conversation} from './PrivateMessages/Conversation' -export {Chat} from './PrivateMessages/Chat' -export {FormPrivateMessage} from './PrivateMessages/FormPrivateMessage' diff --git a/apps/mobile/src/components/search/index.tsx b/apps/mobile/src/components/search/index.tsx index b3917127..f3df4566 100644 --- a/apps/mobile/src/components/search/index.tsx +++ b/apps/mobile/src/components/search/index.tsx @@ -1,5 +1,5 @@ import {NDKKind} from '@nostr-dev-kit/ndk'; -import useSearch from 'afk_nostr_sdk/src/hooks/search/useSearch'; // Import useSearch +// Import useSearch import React, {useEffect, useState} from 'react'; import {Pressable, Text, TextInput, View} from 'react-native'; import Svg, {Path} from 'react-native-svg'; @@ -14,9 +14,8 @@ interface ISearchComponent { kinds?: NDKKind[]; setKinds?: (kinds: NDKKind[]) => void; contactList?: string[]; - setSortBy?: (sort:string) => void; - sortBy?:string; - + setSortBy?: (sort: string) => void; + sortBy?: string; } const SearchComponent: React.FC = ({ @@ -26,16 +25,16 @@ const SearchComponent: React.FC = ({ setKinds = () => {}, contactList, sortBy, - setSortBy + setSortBy, }) => { const styles = useStyles(stylesheet); const [debouncedQuery, setDebouncedQuery] = useState(searchQuery); const [isOpenFilter, setIsOpenFilter] = useState(false); - const [activeSortBy, setActiveSortBy] = useState(sortBy ?? "trending"); + const [activeSortBy, setActiveSortBy] = useState(sortBy ?? 'trending'); const handleSortChange = (sortBy: string) => { setActiveSortBy(sortBy); - setSortBy + setSortBy; }; useEffect(() => { diff --git a/apps/mobile/src/hooks/launchpad/useSellCoin.ts b/apps/mobile/src/hooks/launchpad/useSellCoin.ts index 994d6575..b02d9e24 100644 --- a/apps/mobile/src/hooks/launchpad/useSellCoin.ts +++ b/apps/mobile/src/hooks/launchpad/useSellCoin.ts @@ -1,6 +1,6 @@ import {useAccount, useNetwork, useProvider} from '@starknet-react/core'; import {LAUNCHPAD_ADDRESS} from 'common'; -import {AccountInterface, CallData, constants, RpcProvider, uint256} from 'starknet'; +import {AccountInterface, CallData, constants, RpcProvider} from 'starknet'; import {TokenQuoteBuyKeys} from '../../types/keys'; import {formatFloatToUint256} from '../../utils/format'; @@ -20,7 +20,8 @@ export const useSellCoin = () => { contractAddress?: string, ) => { if (!account) return; - const addressContract = contractAddress ?? LAUNCHPAD_ADDRESS[constants.StarknetChainId.SN_SEPOLIA]; + const addressContract = + contractAddress ?? LAUNCHPAD_ADDRESS[constants.StarknetChainId.SN_SEPOLIA]; // console.log('addressContract', addressContract); // let launchpad_contract = await prepareAndConnectContract( // provider, @@ -28,7 +29,7 @@ export const useSellCoin = () => { // account // ); - let amountUint256 = formatFloatToUint256(amount); + const amountUint256 = formatFloatToUint256(amount); // amountUint256 = uint256.bnToUint256(BigInt('0x' + amount)); const sellKeysParams = { diff --git a/apps/mobile/src/hooks/useIsDesktop.ts b/apps/mobile/src/hooks/useIsDesktop.ts index e131eaa5..c31bb880 100644 --- a/apps/mobile/src/hooks/useIsDesktop.ts +++ b/apps/mobile/src/hooks/useIsDesktop.ts @@ -1,14 +1,12 @@ -import { useMemo } from "react"; -import { useWindowDimensions } from "./useWindowDimensions"; +import {useMemo} from 'react'; +import {useWindowDimensions} from './useWindowDimensions'; export const useIsDesktop = () => { + const dimensions = useWindowDimensions(); + const isDesktop = useMemo(() => { + return dimensions.width >= 1024; + }, [dimensions]); // Adjust based on your breakpoint for desktop - const dimensions = useWindowDimensions(); - const isDesktop = useMemo(() => { - return dimensions.width >= 1024; - }, [dimensions]); // Adjust based on your breakpoint for desktop - - return isDesktop - -} + return isDesktop; +}; diff --git a/apps/mobile/src/hooks/useWebln.ts b/apps/mobile/src/hooks/useWebln.ts new file mode 100644 index 00000000..27165fd8 --- /dev/null +++ b/apps/mobile/src/hooks/useWebln.ts @@ -0,0 +1,47 @@ +export const useWebln = () => { + const handleWebln = async () => { + if (window.webln) { + try { + await window.webln.enable(); + const invoice = await window.webln.makeInvoice({ + amount: 1000, + defaultMemo: 'React Native Zap', + }); + } catch (error) {} + } else { + } + }; + + const handleGetBalance = async () => { + if (window.webln) { + try { + await window.webln.enable(); + // let connected = await window.webln.isEnabled() + // if(!connected) { + + // } + // const invoice = await window?.webln?.getBalance(); + } catch (error) {} + } else { + } + }; + + const handleMakeInvoice = async (amount: number, memo?: string) => { + if (window.webln) { + try { + await window.webln.enable(); + const invoice = await window.webln.makeInvoice({ + amount: amount ?? 1000, + defaultMemo: memo ?? 'React Native Zap', + }); + } catch (error) {} + } else { + } + }; + + return { + handleGetBalance, + handleMakeInvoice, + handleWebln, + }; +}; diff --git a/apps/mobile/src/modules/DirectMessages/index.tsx b/apps/mobile/src/modules/DirectMessages/index.tsx index a019600f..05f5aedb 100644 --- a/apps/mobile/src/modules/DirectMessages/index.tsx +++ b/apps/mobile/src/modules/DirectMessages/index.tsx @@ -1,22 +1,22 @@ -import React, { useEffect, useState } from 'react'; -import { FlatList, View } from 'react-native'; -import { useStyles } from '../../hooks'; -import { ConversationType } from '../../types/messages'; -import { conversationsData } from '../../utils/dummyData'; +import {useMyGiftWrapMessages, useMyMessagesSent} from 'afk_nostr_sdk'; +import React, {useEffect, useState} from 'react'; +import {FlatList, View} from 'react-native'; + +import {Conversation as ConversationPreview} from '../../components'; +import {Chat} from '../../components/PrivateMessages/Chat'; +import {FormPrivateMessage} from '../../components/PrivateMessages/FormPrivateMessage'; +import {useStyles} from '../../hooks'; +import {ConversationType} from '../../types/messages'; +import {conversationsData} from '../../utils/dummyData'; import stylesheet from './styles'; -import { Chat } from '../../components/PrivateMessages/Chat'; -import { Conversation as ConversationPreview, Input } from '../../components'; -import { FormPrivateMessage } from '../../components/PrivateMessages/FormPrivateMessage'; -import { useMyGiftWrapMessages, useMyMessagesSent } from 'afk_nostr_sdk'; export const DirectMessages: React.FC = () => { - const styles = useStyles(stylesheet); const [conversations, setConversations] = useState([]); const [selectedConversation, setSelectedConversation] = useState(null); - const giftMessages = useMyGiftWrapMessages() - const messagesSent = useMyMessagesSent() + const giftMessages = useMyGiftWrapMessages(); + const messagesSent = useMyMessagesSent(); useEffect(() => { // Fetch the list of messages // const { conversationsData } = useGetMessages(); @@ -27,28 +27,30 @@ export const DirectMessages: React.FC = () => { setSelectedConversation(null); }; - console.log("giftMessages", giftMessages?.data?.pages) - console.log("messagesSent", messagesSent?.data?.pages) + console.log('giftMessages', giftMessages?.data?.pages); + console.log('messagesSent', messagesSent?.data?.pages); return ( <> - - - {selectedConversation ? - : ( - - conversation.id} - renderItem={({ item }) => ( - setSelectedConversation(item)} /> - )} - ItemSeparatorComponent={() => } - /> - - )} + {selectedConversation ? ( + + ) : ( + + conversation.id} + renderItem={({item}) => ( + setSelectedConversation(item)} + /> + )} + ItemSeparatorComponent={() => } + /> + + )} {/* { ItemSeparatorComponent={() => } /> */} - ); -}; \ No newline at end of file +}; diff --git a/apps/mobile/src/modules/DirectMessages/styles.ts b/apps/mobile/src/modules/DirectMessages/styles.ts index 5535fb41..992c9a4d 100644 --- a/apps/mobile/src/modules/DirectMessages/styles.ts +++ b/apps/mobile/src/modules/DirectMessages/styles.ts @@ -1,12 +1,12 @@ import {ThemedStyleSheet} from '../../styles'; export default ThemedStyleSheet((theme) => ({ - container: { - flex: 1, - backgroundColor: theme.colors.background, - }, - separator: { - height: 1, - backgroundColor: theme.colors.divider, - }, + container: { + flex: 1, + backgroundColor: theme.colors.background, + }, + separator: { + height: 1, + backgroundColor: theme.colors.divider, + }, })); diff --git a/apps/mobile/src/modules/Group/all/AllGroup.tsx b/apps/mobile/src/modules/Group/all/AllGroup.tsx index 07e4b242..1ce8c9ee 100644 --- a/apps/mobile/src/modules/Group/all/AllGroup.tsx +++ b/apps/mobile/src/modules/Group/all/AllGroup.tsx @@ -34,7 +34,7 @@ export default function AllGroupListComponent() { return ( - My Groups + All Groups {isPending ? ( diff --git a/apps/mobile/src/modules/Lightning/index.tsx b/apps/mobile/src/modules/Lightning/index.tsx index b862df22..b625929d 100644 --- a/apps/mobile/src/modules/Lightning/index.tsx +++ b/apps/mobile/src/modules/Lightning/index.tsx @@ -1,29 +1,33 @@ import '../../../applyGlobalPolyfills'; -import { init, launchModal } from '@getalby/bitcoin-connect-react'; -import { LightningAddress } from '@getalby/lightning-tools'; -import { webln } from '@getalby/sdk'; -import React from 'react'; -import { Platform, SafeAreaView, Text, TextInput, View } from 'react-native'; -import WebView from 'react-native-webview'; +import {init, launchModal, requestProvider} from '@getalby/bitcoin-connect-react'; +import {LightningAddress} from '@getalby/lightning-tools'; +import {webln} from '@getalby/sdk'; +import React, {useRef} from 'react'; +import {Platform, ScrollView, Text, TextInput, View} from 'react-native'; +import WebView, {WebViewMessageEvent} from 'react-native-webview'; import PolyfillCrypto from 'react-native-webview-crypto'; -import { Button, Input } from '../../components'; -import { useStyles } from '../../hooks'; +import {Button, Input} from '../../components'; +import {useStyles} from '../../hooks'; import stylesheet from './styles'; export const LightningNetworkWalletView: React.FC = () => { const styles = useStyles(stylesheet); return ( - + // + + - + + + // ); }; function LightningNetworkWallet() { const styles = useStyles(stylesheet); - const [amountSats, setAmountSats] = React.useState("1") + const [amountSats, setAmountSats] = React.useState('1'); const [nwcUrl, setNwcUrl] = React.useState(''); const [pendingNwcUrl, setPendingNwcUrl] = React.useState(''); @@ -33,6 +37,30 @@ function LightningNetworkWallet() { const [nostrWebLN, setNostrWebLN] = React.useState( undefined, ); + const webviewRef = useRef(null); + + const onMessage = (event: WebViewMessageEvent) => { + const {data} = event.nativeEvent; + console.log('Received message from WebView:', data); + + // Handle messages sent from the WebView, e.g., invoice payment status + }; + + const injectJavaScript = ` + (async function() { + if (window.webln) { + try { + await window.webln.enable(); + const invoice = await window.webln.makeInvoice({ amount: 1000, memo: "React Native Zap" }); + window.ReactNativeWebView.postMessage(JSON.stringify({ type: "invoice", data: invoice })); + } catch (error) { + window.ReactNativeWebView.postMessage(JSON.stringify({ type: "error", message: error.message })); + } + } else { + window.ReactNativeWebView.postMessage(JSON.stringify({ type: "error", message: "WebLN not available" })); + } + })(); +`; const [balance, setBalance] = React.useState(); React.useEffect(() => { @@ -96,6 +124,7 @@ function LightningNetworkWallet() { async function connectWithAlby() { const nwc = webln.NostrWebLNProvider.withNewSecret({ //authorizationUrl: "http://192.168.1.102:8080", + // authorizationUrl:nwcAuthUrl }); console.log('nwc', nwc); @@ -137,23 +166,44 @@ function LightningNetworkWallet() { // } const handleRequest = async () => { - let modal = launchModal(); - // const provider = await requestProvider(); + const modal = launchModal(); + const provider = await requestProvider(); // let send_payment = await provider.sendPayment('lnbc...'); return; }; + return ( - + + {/* + { + Platform.OS == "web" ? + + : + + } + */} - { - Platform.OS == 'web' ? ( - + + Paste NWC URL setNwcUrl(text)} @@ -187,11 +238,11 @@ function LightningNetworkWallet() { - + + ); } diff --git a/apps/mobile/src/modules/PixelPeace/index.tsx b/apps/mobile/src/modules/PixelPeace/index.tsx index 343c1f0e..aa4d4e1a 100644 --- a/apps/mobile/src/modules/PixelPeace/index.tsx +++ b/apps/mobile/src/modules/PixelPeace/index.tsx @@ -1,41 +1,32 @@ -import React, { useEffect, useState } from 'react'; -import { useStyles } from '../../hooks'; -import stylesheet from './styles'; -import { Chat } from '../../components/PrivateMessages/Chat'; +import React from 'react'; +import {Platform, View} from 'react-native'; // import { App, AppRender } from "pixel_ui" import WebView from 'react-native-webview'; -import { Platform, View } from 'react-native'; -import { useIsDesktop } from '../../hooks/useIsDesktop'; -export const PixelPeace: React.FC = () => { +import {useStyles} from '../../hooks'; +import {useIsDesktop} from '../../hooks/useIsDesktop'; +import stylesheet from './styles'; +export const PixelPeace: React.FC = () => { const styles = useStyles(stylesheet); - const isDesktop = useIsDesktop() - + const isDesktop = useIsDesktop(); return ( - - - {Platform.OS == "web" && process.env.EXPO_PUBLIC_PIXEL_URL && + + {Platform.OS == 'web' && process.env.EXPO_PUBLIC_PIXEL_URL && ( <> - - - } + )} - {Platform.OS != "web" && process.env.EXPO_PUBLIC_PIXEL_URL && - - - } + {Platform.OS != 'web' && process.env.EXPO_PUBLIC_PIXEL_URL && ( + + )} - ); -}; \ No newline at end of file +}; diff --git a/apps/mobile/src/modules/PixelPeace/styles.ts b/apps/mobile/src/modules/PixelPeace/styles.ts index 5535fb41..992c9a4d 100644 --- a/apps/mobile/src/modules/PixelPeace/styles.ts +++ b/apps/mobile/src/modules/PixelPeace/styles.ts @@ -1,12 +1,12 @@ import {ThemedStyleSheet} from '../../styles'; export default ThemedStyleSheet((theme) => ({ - container: { - flex: 1, - backgroundColor: theme.colors.background, - }, - separator: { - height: 1, - backgroundColor: theme.colors.divider, - }, + container: { + flex: 1, + backgroundColor: theme.colors.background, + }, + separator: { + height: 1, + backgroundColor: theme.colors.divider, + }, })); diff --git a/apps/mobile/src/modules/Post/index.tsx b/apps/mobile/src/modules/Post/index.tsx index 6bffbc81..9b203836 100644 --- a/apps/mobile/src/modules/Post/index.tsx +++ b/apps/mobile/src/modules/Post/index.tsx @@ -1,10 +1,17 @@ import {NDKEvent, NDKKind} from '@nostr-dev-kit/ndk'; import {useNavigation} from '@react-navigation/native'; import {useQueryClient} from '@tanstack/react-query'; -import {useProfile, useReact, useReactions, useReplyNotes, useRepost, useBookmark} from 'afk_nostr_sdk'; +import { + useBookmark, + useProfile, + useReact, + useReactions, + useReplyNotes, + useRepost, +} from 'afk_nostr_sdk'; // import { useAuth } from '../../store/auth'; import {useAuth} from 'afk_nostr_sdk'; -import {useEffect, useMemo, useState} from 'react'; +import {useMemo, useState} from 'react'; import {ActivityIndicator, Image, Pressable, View} from 'react-native'; import Animated, { Easing, @@ -27,13 +34,19 @@ import stylesheet from './styles'; export type PostProps = { asComment?: boolean; event?: NDKEvent; - repostedEventProps?:string; - isRepost?:boolean; - isBookmarked?:boolean; + repostedEventProps?: string; + isRepost?: boolean; + isBookmarked?: boolean; }; -export const Post: React.FC = ({asComment, event, repostedEventProps, isRepost, isBookmarked = false}) => { - const repostedEvent = repostedEventProps ?? undefined; +export const Post: React.FC = ({ + asComment, + event, + repostedEventProps, + isRepost, + isBookmarked = false, +}) => { + const repostedEvent = repostedEventProps ?? undefined; const {theme} = useTheme(); const styles = useStyles(stylesheet); @@ -50,8 +63,8 @@ export const Post: React.FC = ({asComment, event, repostedEventProps, const comments = useReplyNotes({noteId: event?.id}); const react = useReact(); const queryClient = useQueryClient(); - const repostMutation = useRepost({ event }); - const { bookmarkNote, removeBookmark } = useBookmark(publicKey); + const repostMutation = useRepost({event}); + const {bookmarkNote, removeBookmark} = useBookmark(publicKey); const [menuOpen, setMenuOpen] = useState(false); @@ -139,15 +152,15 @@ export const Post: React.FC = ({asComment, event, repostedEventProps, if (!event) return; try { if (isBookmarked) { - await removeBookmark({ eventId: event.id }); - showToast({ title: 'Post removed from bookmarks', type: 'success' }); + await removeBookmark({eventId: event.id}); + showToast({title: 'Post removed from bookmarks', type: 'success'}); } else { - await bookmarkNote({ event }); - showToast({ title: 'Post bookmarked successfully', type: 'success' }); + await bookmarkNote({event}); + showToast({title: 'Post bookmarked successfully', type: 'success'}); } } catch (error) { console.error('Bookmark error:', error); - showToast({ title: 'Failed to bookmark', type: 'error' }); + showToast({title: 'Failed to bookmark', type: 'error'}); } }; @@ -156,12 +169,14 @@ export const Post: React.FC = ({asComment, event, repostedEventProps, return ( - {repostedEvent || event?.kind == NDKKind.Repost || isRepost && ( - - - Reposted - - )} + {repostedEvent || + event?.kind == NDKKind.Repost || + (isRepost && ( + + + Reposted + + ))} @@ -298,14 +313,12 @@ export const Post: React.FC = ({asComment, event, repostedEventProps, {repostMutation.isPending && } - + + title={isBookmarked ? 'Bookmarked' : 'Bookmark'} + /> diff --git a/apps/mobile/src/modules/PostCard/index.tsx b/apps/mobile/src/modules/PostCard/index.tsx index 225f8f06..9a6950cc 100644 --- a/apps/mobile/src/modules/PostCard/index.tsx +++ b/apps/mobile/src/modules/PostCard/index.tsx @@ -1,28 +1,36 @@ -import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk'; -import { View } from 'react-native'; -import { useStyles } from '../../hooks'; -import { Post } from '../Post'; +import {NDKEvent, NDKKind} from '@nostr-dev-kit/ndk'; +import {useState} from 'react'; +import {View} from 'react-native'; + +import {useStyles} from '../../hooks'; +import {Post} from '../Post'; import stylesheet from './styles'; -import { useState } from 'react'; export type PostCardProps = { event?: NDKEvent; - isRepostProps?:boolean; - isBookmarked?:boolean; + isRepostProps?: boolean; + isBookmarked?: boolean; }; -export const PostCard: React.FC = ({ event, isRepostProps, isBookmarked }) => { +export const PostCard: React.FC = ({event, isRepostProps, isBookmarked}) => { const styles = useStyles(stylesheet); let repostedEvent = undefined; - const [isRepost, setIsRepost] = useState(isRepostProps ?? event?.kind == NDKKind.Repost ? true : false) + const [isRepost, setIsRepost] = useState( + isRepostProps ?? event?.kind == NDKKind.Repost ? true : false, + ); if (event?.kind == NDKKind.Repost) { - repostedEvent = JSON.stringify(event?.content) + repostedEvent = JSON.stringify(event?.content); } return ( - + ); }; diff --git a/apps/mobile/src/screens/Auth/Login.tsx b/apps/mobile/src/screens/Auth/Login.tsx index ddf60e1f..c36d4a63 100644 --- a/apps/mobile/src/screens/Auth/Login.tsx +++ b/apps/mobile/src/screens/Auth/Login.tsx @@ -169,12 +169,14 @@ export const Login: React.FC = ({navigation}) => { Create Account Import Account Nostr extension diff --git a/apps/mobile/src/screens/ChannelDetail/index.tsx b/apps/mobile/src/screens/ChannelDetail/index.tsx index 684bff19..c25f99da 100644 --- a/apps/mobile/src/screens/ChannelDetail/index.tsx +++ b/apps/mobile/src/screens/ChannelDetail/index.tsx @@ -1,10 +1,10 @@ import {View} from 'react-native'; +import {Header, IconButton} from '../../components'; import {useStyles} from '../../hooks'; import {ChannelDetailComponent} from '../../modules/ChannelDetailPage'; import {ChannelDetailScreenProps} from '../../types'; import stylesheet from './styles'; -import { Header, IconButton } from '../../components'; export const ChannelDetail: React.FC = ({navigation, route}) => { const {postId, post} = route.params; @@ -15,10 +15,9 @@ export const ChannelDetail: React.FC = ({navigation, r
} + left={} // right={} - + title="ChannelDetail" /> diff --git a/apps/mobile/src/screens/Feed/index.tsx b/apps/mobile/src/screens/Feed/index.tsx index 5daa572c..4ce98011 100644 --- a/apps/mobile/src/screens/Feed/index.tsx +++ b/apps/mobile/src/screens/Feed/index.tsx @@ -1,22 +1,22 @@ -import { NDKKind } from '@nostr-dev-kit/ndk'; -import { useAllProfiles, useContacts, useSearch, useSearchNotes } from 'afk_nostr_sdk'; -import { useState } from 'react'; -import { ActivityIndicator, FlatList, Image, Pressable, RefreshControl, View } from 'react-native'; +import {NDKKind} from '@nostr-dev-kit/ndk'; +import {useAllProfiles, useSearch} from 'afk_nostr_sdk'; +import {useState} from 'react'; +import {ActivityIndicator, FlatList, Image, Pressable, RefreshControl, View} from 'react-native'; -import { AddPostIcon } from '../../assets/icons'; -import { BubbleUser } from '../../components/BubbleUser'; +import {AddPostIcon} from '../../assets/icons'; +import {BubbleUser} from '../../components/BubbleUser'; import SearchComponent from '../../components/search'; -import { useStyles, useTheme } from '../../hooks'; -import { ChannelComponent } from '../../modules/ChannelCard'; -import { PostCard } from '../../modules/PostCard'; -import { FeedScreenProps } from '../../types'; +import {useStyles, useTheme} from '../../hooks'; +import {ChannelComponent} from '../../modules/ChannelCard'; +import {PostCard} from '../../modules/PostCard'; +import {FeedScreenProps} from '../../types'; import stylesheet from './styles'; -export const Feed: React.FC = ({ navigation }) => { - const { theme } = useTheme(); +export const Feed: React.FC = ({navigation}) => { + const {theme} = useTheme(); const styles = useStyles(stylesheet); - const profiles = useAllProfiles(); - const [activeSortBy, setSortBy] = useState() + const profiles = useAllProfiles({limit: 10}); + const [activeSortBy, setSortBy] = useState(); const [search, setSearch] = useState(undefined); const [kinds, setKinds] = useState([ NDKKind.Text, @@ -26,27 +26,28 @@ export const Feed: React.FC = ({ navigation }) => { NDKKind.Metadata, ]); - const contacts = useContacts() + // const contacts = useContacts() // console.log("contacts", contacts) const notes = useSearch({ // search: search, kinds, + limit: 10, // authors: activeSortBy && contacts?.data?.?? [], // sortBy: activeSortBy, }); - // Filter profiles based on the search query const profilesSearch = - profiles?.data?.pages - ?.flat() + profiles?.data?.pages?.flat() ?? // .filter((item) => (search && search?.length > 0 ? item?.content?.includes(search) : true)) ?? - ?? []; + []; // Filter notes based on the search query - const filteredNotes = notes.data?.pages - .flat() - .filter((item) => (search && search?.length > 0 ? item?.content?.includes(search) : true)) ?? []; + const filteredNotes = + notes.data?.pages + .flat() + .filter((item) => (search && search?.length > 0 ? item?.content?.includes(search) : true)) ?? + []; return ( @@ -70,30 +71,34 @@ export const Feed: React.FC = ({ navigation }) => { {notes?.data?.pages?.length == 0 && } - profiles.fetchNextPage()} - refreshControl={ - profiles.refetch()} /> - } - ItemSeparatorComponent={() => } - renderItem={({ item }) => } - />} + ListHeaderComponent={ + <> + profiles.fetchNextPage()} + refreshControl={ + profiles.refetch()} + /> + } + ItemSeparatorComponent={() => } + renderItem={({item}) => } + /> + + } contentContainerStyle={styles.flatListContent} data={filteredNotes} keyExtractor={(item) => item?.id} - renderItem={({ item }) => { + renderItem={({item}) => { if (item.kind === NDKKind.ChannelCreation || item.kind === NDKKind.ChannelMetadata) { return ; - } - else if (item.kind === NDKKind.ChannelMessage) { + } else if (item.kind === NDKKind.ChannelMessage) { return ; - } - else if (item.kind === NDKKind.Text) { + } else if (item.kind === NDKKind.Text) { return ; } return <>; @@ -106,7 +111,7 @@ export const Feed: React.FC = ({ navigation }) => { navigation.navigate('MainStack', { screen: 'CreateForm' })} + onPress={() => navigation.navigate('MainStack', {screen: 'CreateForm'})} > diff --git a/apps/mobile/src/screens/Games/index.tsx b/apps/mobile/src/screens/Games/index.tsx index 79deae53..9c721b5e 100644 --- a/apps/mobile/src/screens/Games/index.tsx +++ b/apps/mobile/src/screens/Games/index.tsx @@ -5,13 +5,13 @@ import {SafeAreaView} from 'react-native-safe-area-context'; import {TextButton} from '../../components'; import TabSelector from '../../components/TabSelector'; import {useStyles, useTheme} from '../../hooks'; +import {PixelPeace} from '../../modules/PixelPeace'; import {GameSreenProps} from '../../types'; import {SelectedTab, TABS_MENU} from '../../types/tab'; import {AllKeysComponent} from '../KeysMarketplace/AllKeysComponent'; import {LaunchpadComponent} from '../Launchpad/LaunchpadComponent'; import {SlinksMap} from '../Slink/SlinksMap'; import stylesheet from './styles'; -import { PixelPeace } from '../../modules/PixelPeace'; export const Games: React.FC = ({navigation}) => { const theme = useTheme(); @@ -41,8 +41,7 @@ export const Games: React.FC = ({navigation}) => { > - - {selectedTab == SelectedTab.PIXEL_PEACE && ( + {selectedTab == SelectedTab.PIXEL_PEACE && ( <> diff --git a/apps/mobile/src/screens/Lightning/index.tsx b/apps/mobile/src/screens/Lightning/index.tsx index b1110bb2..1d10db09 100644 --- a/apps/mobile/src/screens/Lightning/index.tsx +++ b/apps/mobile/src/screens/Lightning/index.tsx @@ -1,13 +1,12 @@ import React from 'react'; -import {View} from 'react-native'; +import {ScrollView} from 'react-native'; import {LightningNetworkWalletView} from '../../modules/Lightning'; import {LightningNetworkScreenProps} from '../../types'; - export const LightningNetworkScreen: React.FC = () => { return ( - + - + ); }; diff --git a/apps/mobile/src/screens/Profile/index.tsx b/apps/mobile/src/screens/Profile/index.tsx index 5ca38e6d..beeb61d1 100644 --- a/apps/mobile/src/screens/Profile/index.tsx +++ b/apps/mobile/src/screens/Profile/index.tsx @@ -1,36 +1,43 @@ -import { useBookmark, useReposts, useRootNotes, useSearch } from 'afk_nostr_sdk'; -import { ActivityIndicator, FlatList, Pressable, RefreshControl, ScrollView, View } from 'react-native'; +import {NDKKind} from '@nostr-dev-kit/ndk'; +import {useBookmark, useSearch} from 'afk_nostr_sdk'; +import {useMemo, useState} from 'react'; +import { + ActivityIndicator, + FlatList, + Pressable, + RefreshControl, + ScrollView, + View, +} from 'react-native'; -import { useStyles } from '../../hooks'; -import { PostCard } from '../../modules/PostCard'; -import { ProfileScreenProps } from '../../types'; -import { ProfileInfo } from './Info'; +import {Text} from '../../components'; +import {useStyles} from '../../hooks'; +import {PostCard} from '../../modules/PostCard'; +import {ProfileScreenProps} from '../../types'; +import {ProfileInfo} from './Info'; import stylesheet from './styles'; -import { useMemo, useState } from 'react'; -import { NDKKind } from '@nostr-dev-kit/ndk'; -import { Text } from '../../components'; -export const Profile: React.FC = ({ route }) => { - const { publicKey } = route.params ?? {}; +export const Profile: React.FC = ({route}) => { + const {publicKey} = route.params ?? {}; const styles = useStyles(stylesheet); const [ndkKinds, setNdkKind] = useState([NDKKind.Text]); const kindFilter = useMemo(() => { - return ndkKinds - }, [ndkKinds]) + return ndkKinds; + }, [ndkKinds]); - const notesSearch = useRootNotes({ authors: [publicKey] }); - const search = useSearch({ authors: [publicKey], kinds: kindFilter }); - const reposts = useReposts({ authors: [publicKey] }); - const { bookmarksWithNotes } = useBookmark(publicKey); + // const notesSearch = useRootNotes({ authors: [publicKey] }); + const search = useSearch({authors: [publicKey], kinds: kindFilter}); + // const reposts = useReposts({ authors: [publicKey] }); + const {bookmarksWithNotes} = useBookmark(publicKey); // Extract all bookmarked note IDs const bookmarkedNoteIds = useMemo(() => { if (!bookmarksWithNotes) return new Set(); const ids = new Set(); - bookmarksWithNotes.forEach(bookmark => { - bookmark.notes.forEach(note => { + bookmarksWithNotes.forEach((bookmark) => { + bookmark.notes.forEach((note) => { ids.add(note?.id || ''); }); }); @@ -40,13 +47,18 @@ export const Profile: React.FC = ({ route }) => { // Function to check if a note is bookmarked const isBookmarked = (noteId: string) => bookmarkedNoteIds.has(noteId); - const getData = ndkKinds.includes(NDKKind.BookmarkList) || ndkKinds.includes(NDKKind.BookmarkSet) - ? bookmarksWithNotes?.map(bookmark => bookmark.notes).flat() || [] - : search.data?.pages.flat(); + // const getData = ndkKinds.includes(NDKKind.BookmarkList) || ndkKinds.includes(NDKKind.BookmarkSet) + // ? bookmarksWithNotes?.map(bookmark => bookmark.notes).flat() || [] + // : search.data?.pages.flat(); + + // console.log("getData", getData) + + const getData = search.data?.pages.flat(); + + console.log('getData', getData); return ( - @@ -80,18 +92,21 @@ export const Profile: React.FC = ({ route }) => { } data={getData} keyExtractor={(item) => item.id} - renderItem={({ item }) => { + renderItem={({item}) => { + if (!item) return <>; if (ndkKinds.includes(NDKKind.Repost)) { const itemReposted = JSON.parse(item?.content); - return + return ; } - return + return ; }} refreshControl={ search.refetch()} /> } /> + {search?.isPending && } + {search?.isLoading && } ); diff --git a/apps/mobile/src/screens/Profile/styles.ts b/apps/mobile/src/screens/Profile/styles.ts index 085f902c..fa78209c 100644 --- a/apps/mobile/src/screens/Profile/styles.ts +++ b/apps/mobile/src/screens/Profile/styles.ts @@ -7,19 +7,19 @@ export default ThemedStyleSheet((theme) => ({ }, optionsContentContainer: { paddingVertical: 5, - paddingHorizontal:5, + paddingHorizontal: 5, flexDirection: 'row', rowGap: 3, gap: 3, columnGap: 15, }, optionsContainer: { - paddingHorizontal:5, + paddingHorizontal: 5, paddingVertical: 5, flexDirection: 'row', rowGap: 3, gap: 3, - columnGap: 3 + columnGap: 3, }, option: { paddingVertical: 10, @@ -32,6 +32,6 @@ export default ThemedStyleSheet((theme) => ({ }, selected: { backgroundColor: theme.colors.primary, - color: theme.colors.text - } + color: theme.colors.text, + }, })); diff --git a/apps/mobile/src/screens/Whatever/index.tsx b/apps/mobile/src/screens/Whatever/index.tsx index a87f2ef9..5d66c3e2 100644 --- a/apps/mobile/src/screens/Whatever/index.tsx +++ b/apps/mobile/src/screens/Whatever/index.tsx @@ -1,6 +1,7 @@ import {NDKEvent, NDKKind} from '@nostr-dev-kit/ndk'; import {useNavigation} from '@react-navigation/native'; import {useAccount, useProvider} from '@starknet-react/core'; +import {useNostrContext} from 'afk_nostr_sdk'; import {useState} from 'react'; import {View} from 'react-native'; import {byteArray, cairo, CallData, getChecksumAddress, uint256} from 'starknet'; @@ -17,7 +18,6 @@ import {ChannelComponent} from '../../modules/ChannelCard'; import {MainStackNavigationProps} from '../../types'; import {TipsComponent} from '../Tips/TipsComponent'; import stylesheet from './styles'; -import { useNostrContext } from 'afk_nostr_sdk'; enum SelectedTab { TIPS, diff --git a/apps/mobile/src/types/messages.ts b/apps/mobile/src/types/messages.ts index 48fa0540..250d76d2 100644 --- a/apps/mobile/src/types/messages.ts +++ b/apps/mobile/src/types/messages.ts @@ -9,7 +9,7 @@ export type Message = { message: string; isUser: boolean; // Indicates if the message is from the current user or the other party timestamp: string; -} +}; export type ConversationType = { id: string; diff --git a/apps/mobile/src/types/nostr.ts b/apps/mobile/src/types/nostr.ts index 00fb5eb2..b23ef7ff 100644 --- a/apps/mobile/src/types/nostr.ts +++ b/apps/mobile/src/types/nostr.ts @@ -1,6 +1,5 @@ export enum SORT_OPTION_EVENT_NOSTR { - TIME, - TRENDING, - FOR_YOU - -} \ No newline at end of file + TIME, + TRENDING, + FOR_YOU, +} diff --git a/apps/mobile/src/types/tab.ts b/apps/mobile/src/types/tab.ts index 7b70af1a..2adcbe45 100644 --- a/apps/mobile/src/types/tab.ts +++ b/apps/mobile/src/types/tab.ts @@ -23,7 +23,6 @@ export enum SelectedTab { ALL_GROUP, GROUP_MESSAGE, PIXEL_PEACE, - } export const TABS_TIP_LIST: {screen?: string; title: string; tab: SelectedTab}[] = [ @@ -150,7 +149,7 @@ export const TABS_MENU: {screen?: string; title: string; tab: SelectedTab}[] = [ screen: 'Slink', tab: SelectedTab.SLINK, }, - + { title: '?', screen: '?', diff --git a/apps/mobile/src/utils/dummyData.ts b/apps/mobile/src/utils/dummyData.ts index d730a28e..ae067493 100644 --- a/apps/mobile/src/utils/dummyData.ts +++ b/apps/mobile/src/utils/dummyData.ts @@ -1,225 +1,225 @@ -import { Conversation } from "../types/messages"; +import {Conversation} from '../types/messages'; export const conversationsData: Conversation[] = [ - { - id: '1', - user: { - id: '1', - name: 'John Doe', - handle: '@johndoe', - avatar: '', - }, - messages: [ - { - message: 'Doing well, thanks!', - isUser: true, - timestamp: new Date().toString(), - }, - { - message: 'How are you?', - isUser: false, - timestamp: new Date().toString(), - }, - { - message: 'Hello', - isUser: false, - timestamp: new Date().toString(), - }, - { - message: 'Hi!', - isUser: true, - timestamp: new Date().toString(), - }, - ] - }, - { - id: '2', - user: { - id: '2', - name: 'Jane Doe', - handle: '@janedoe', - avatar: '', - }, - messages: [] - }, - { - id: '3', - user: { - id: '3', - name: 'Alice', - handle: '@alice', - avatar: '', - }, - messages: [] - }, - { - id: '4', - user: { - id: '4', - name: 'Bob', - handle: '@bob', - avatar: '', - }, - messages: [] - }, - { - id: '5', - user: { - id: '5', - name: 'Charlie', - handle: '@charlie', - avatar: '', - }, - messages: [] - }, - { - id: '6', - user: { - id: '6', - name: 'David', - handle: '@david', - avatar: '', - }, - messages: [] - }, - { - id: '7', - user: { - id: '7', - name: 'Eve', - handle: '@eve', - avatar: '', - }, - messages: [] - }, - { - id: '8', - user: { - id: '8', - name: 'Frank', - handle: '@frank', - avatar: '', - }, - messages: [] - }, - { - id: '9', - user: { - id: '9', - name: 'Grace', - handle: '@grace', - avatar: '', - }, - messages: [] - }, - { - id: '10', - user: { - id: '10', - name: 'Harry', - handle: '@harry', - avatar: '', - }, - messages: [] - }, - { - id: '11', - user: { - id: '11', - name: 'Ivy', - handle: '@ivy', - avatar: '', - }, - messages: [] - }, - { - id: '12', - user: { - id: '12', - name: 'Jack', - handle: '@jack', - avatar: '', - }, - messages: [] - }, - { - id: '13', - user: { - id: '13', - name: 'Kate', - handle: '@kate', - avatar: '', - }, - messages: [] - }, - { - id: '14', - user: { - id: '14', - name: 'Liam', - handle: '@liam', - avatar: '', - }, - messages: [] - }, - { - id: '15', - user: { - id: '15', - name: 'Mia', - handle: '@mia', - avatar: '', - }, - messages: [] - }, - { - id: '16', - user: { - id: '16', - name: 'Noah', - handle: '@noah', - avatar: '', - }, - messages: [] - }, - { - id: '17', - user: { - id: '17', - name: 'Olivia', - handle: '@olivia', - avatar: '', - }, - messages: [] - }, - { - id: '18', - user: { - id: '18', - name: 'Peter', - handle: '@peter', - avatar: '', - }, - messages: [] - }, - { - id: '19', - user: { - id: '19', - name: 'Quinn', - handle: '@quinn', - avatar: '', - }, - messages: [] - }, - { - id: '20', - user: { - id: '20', - name: 'Rose', - handle: '@rose', - avatar: '', - }, - messages: [] - } + { + id: '1', + user: { + id: '1', + name: 'John Doe', + handle: '@johndoe', + avatar: '', + }, + messages: [ + { + message: 'Doing well, thanks!', + isUser: true, + timestamp: new Date().toString(), + }, + { + message: 'How are you?', + isUser: false, + timestamp: new Date().toString(), + }, + { + message: 'Hello', + isUser: false, + timestamp: new Date().toString(), + }, + { + message: 'Hi!', + isUser: true, + timestamp: new Date().toString(), + }, + ], + }, + { + id: '2', + user: { + id: '2', + name: 'Jane Doe', + handle: '@janedoe', + avatar: '', + }, + messages: [], + }, + { + id: '3', + user: { + id: '3', + name: 'Alice', + handle: '@alice', + avatar: '', + }, + messages: [], + }, + { + id: '4', + user: { + id: '4', + name: 'Bob', + handle: '@bob', + avatar: '', + }, + messages: [], + }, + { + id: '5', + user: { + id: '5', + name: 'Charlie', + handle: '@charlie', + avatar: '', + }, + messages: [], + }, + { + id: '6', + user: { + id: '6', + name: 'David', + handle: '@david', + avatar: '', + }, + messages: [], + }, + { + id: '7', + user: { + id: '7', + name: 'Eve', + handle: '@eve', + avatar: '', + }, + messages: [], + }, + { + id: '8', + user: { + id: '8', + name: 'Frank', + handle: '@frank', + avatar: '', + }, + messages: [], + }, + { + id: '9', + user: { + id: '9', + name: 'Grace', + handle: '@grace', + avatar: '', + }, + messages: [], + }, + { + id: '10', + user: { + id: '10', + name: 'Harry', + handle: '@harry', + avatar: '', + }, + messages: [], + }, + { + id: '11', + user: { + id: '11', + name: 'Ivy', + handle: '@ivy', + avatar: '', + }, + messages: [], + }, + { + id: '12', + user: { + id: '12', + name: 'Jack', + handle: '@jack', + avatar: '', + }, + messages: [], + }, + { + id: '13', + user: { + id: '13', + name: 'Kate', + handle: '@kate', + avatar: '', + }, + messages: [], + }, + { + id: '14', + user: { + id: '14', + name: 'Liam', + handle: '@liam', + avatar: '', + }, + messages: [], + }, + { + id: '15', + user: { + id: '15', + name: 'Mia', + handle: '@mia', + avatar: '', + }, + messages: [], + }, + { + id: '16', + user: { + id: '16', + name: 'Noah', + handle: '@noah', + avatar: '', + }, + messages: [], + }, + { + id: '17', + user: { + id: '17', + name: 'Olivia', + handle: '@olivia', + avatar: '', + }, + messages: [], + }, + { + id: '18', + user: { + id: '18', + name: 'Peter', + handle: '@peter', + avatar: '', + }, + messages: [], + }, + { + id: '19', + user: { + id: '19', + name: 'Quinn', + handle: '@quinn', + avatar: '', + }, + messages: [], + }, + { + id: '20', + user: { + id: '20', + name: 'Rose', + handle: '@rose', + avatar: '', + }, + messages: [], + }, ]; diff --git a/apps/website/src/app/components/NavbarPixel.tsx b/apps/website/src/app/components/NavbarPixel.tsx index 385f5271..5d54e083 100644 --- a/apps/website/src/app/components/NavbarPixel.tsx +++ b/apps/website/src/app/components/NavbarPixel.tsx @@ -5,7 +5,6 @@ import React, {useState} from 'react'; import {createPortal} from 'react-dom'; import {MobileNavBar} from './MobileNavBar'; -import {NavigationLinks} from './NavigationLinks'; export function NavbarPixel() { const [toggleNav, setToggleNav] = useState(false); diff --git a/apps/website/src/app/pixel/page.tsx b/apps/website/src/app/pixel/page.tsx index 56c8d2f7..a17ff72a 100644 --- a/apps/website/src/app/pixel/page.tsx +++ b/apps/website/src/app/pixel/page.tsx @@ -1,11 +1,12 @@ 'use client'; import {AppRender} from 'pixel_ui'; -import { NavbarPixel } from '../components/NavbarPixel'; + +import {NavbarPixel} from '../components/NavbarPixel'; export default function Pixel() { return (
- + {/* */} {typeof window !== 'undefined' && } diff --git a/onchain/cairo/.snfoundry_cache/.prev_tests_failed b/onchain/cairo/.snfoundry_cache/.prev_tests_failed index e69de29b..a15dd69e 100644 --- a/onchain/cairo/.snfoundry_cache/.prev_tests_failed +++ b/onchain/cairo/.snfoundry_cache/.prev_tests_failed @@ -0,0 +1,5 @@ +afk::social::deposit::tests::deposit_claim +afk::social::deposit::tests::claim_incorrect_gas_amount +afk::social::deposit::tests::deposit_claim_gas_fee +afk::tests::launchpad_tests::launchpad_tests::launchpad_integration +afk::tests::vault_tests::vault_test::test_mint_by_token diff --git a/onchain/cairo/src/launchpad/launchpad.cairo b/onchain/cairo/src/launchpad/launchpad.cairo index 9b1b0aed..3343eaf0 100644 --- a/onchain/cairo/src/launchpad/launchpad.cairo +++ b/onchain/cairo/src/launchpad/launchpad.cairo @@ -107,8 +107,8 @@ mod LaunchpadMarketplace { use super::{ StoredName, BuyToken, SellToken, CreateToken, LaunchUpdated, SharesTokenUser, MINTER_ROLE, ADMIN_ROLE, BondingType, Token, TokenLaunch, TokenQuoteBuyCoin, CreateLaunch, - SetJediwapNFTRouterV2, SetJediwapV2Factory, SupportedExchanges, MintParams, LiquidityCreated, - LiquidityCanBeAdded + SetJediwapNFTRouterV2, SetJediwapV2Factory, SupportedExchanges, MintParams, + LiquidityCreated, LiquidityCanBeAdded }; const MAX_SUPPLY: u256 = 100_000_000; @@ -201,7 +201,7 @@ mod LaunchpadMarketplace { SetJediwapV2Factory: SetJediwapV2Factory, SetJediwapNFTRouterV2: SetJediwapNFTRouterV2, LiquidityCreated: LiquidityCreated, - LiquidityCanBeAdded:LiquidityCanBeAdded, + LiquidityCanBeAdded: LiquidityCanBeAdded, #[flat] AccessControlEvent: AccessControlComponent::Event, #[flat] @@ -397,7 +397,6 @@ mod LaunchpadMarketplace { } - // Buy coin by quote amount // Get amount of coin receive based on token IN fn buy_coin_by_quote_amount( @@ -574,30 +573,28 @@ mod LaunchpadMarketplace { // TODO finish test and fix if pool_coin.liquidity_raised >= threshold { - self - .emit( - LiquidityCanBeAdded { - pool:pool_coin.token_address.clone(), - asset:pool_coin.token_address.clone(), - quote_token_address:pool_coin.token_quote.token_address.clone(), - - } - ); - // self._add_liquidity(coin_address, SupportedExchanges::Jediswap); + .emit( + LiquidityCanBeAdded { + pool: pool_coin.token_address.clone(), + asset: pool_coin.token_address.clone(), + quote_token_address: pool_coin.token_quote.token_address.clone(), + } + ); + // self._add_liquidity(coin_address, SupportedExchanges::Jediswap); } if mc >= threshold_mc { // println!("mc >= threshold_mc"); self - .emit( - LiquidityCanBeAdded { - pool:pool_coin.token_address.clone(), - asset:pool_coin.token_address.clone(), - quote_token_address:pool_coin.token_quote.token_address.clone(), - } - ); - // self._add_liquidity(coin_address, SupportedExchanges::Jediswap); + .emit( + LiquidityCanBeAdded { + pool: pool_coin.token_address.clone(), + asset: pool_coin.token_address.clone(), + quote_token_address: pool_coin.token_quote.token_address.clone(), + } + ); + // self._add_liquidity(coin_address, SupportedExchanges::Jediswap); } // TODO check reetrancy guard @@ -657,7 +654,10 @@ mod LaunchpadMarketplace { // assert!(old_share.amount_owned >= amount, "share to sell > supply"); // println!("amount{:?}", amount); // assert!(total_supply >= quote_amount, "share to sell > supply"); - assert!( old_pool.liquidity_raised >= quote_amount, "pool_update.liquidity_raised <= quote_amount"); + assert!( + old_pool.liquidity_raised >= quote_amount, + "pool_update.liquidity_raised <= quote_amount" + ); // assert!( old_pool.liquidity_raised >= quote_amount, "pool_update.liquidity_raised <= quote_amount"); let old_price = old_pool.price.clone(); @@ -670,7 +670,10 @@ mod LaunchpadMarketplace { // let remain_liquidity = total_price - amount_creator_fee - amount_protocol_fee; let remain_liquidity = total_price - amount_protocol_fee; // let remain_liquidity = total_price ; - assert!( old_pool.liquidity_raised >= remain_liquidity, "pool_update.liquidity_raised <= remain_liquidity"); + assert!( + old_pool.liquidity_raised >= remain_liquidity, + "pool_update.liquidity_raised <= remain_liquidity" + ); // TODO fix amount owned and sellable. // Update share user coin @@ -719,17 +722,15 @@ mod LaunchpadMarketplace { } - // TODO finish check + // TODO finish check // Launch liquidity if threshold ok - fn launch_liquidity(ref self: ContractState, coin_address: ContractAddress) { - + fn launch_liquidity(ref self: ContractState, coin_address: ContractAddress) { let pool = self.launched_coins.read(coin_address); assert!(pool.liquidity_raised >= pool.threshold_liquidity, "no threshold raised"); assert!(pool.is_liquidity_launch == false, "liquidity already launch"); self._add_liquidity(coin_address, SupportedExchanges::Jediswap); - } // TODO Finish this function @@ -1131,7 +1132,7 @@ mod LaunchpadMarketplace { let k_max = total_supply * threshold_liquidity; - if is_decreased == true { + if is_decreased == true { let pool_coin = self.launched_coins.read(coin_address); let qa = pool_coin.liquidity_raised; let qb_init_supply = pool_coin.total_supply / LIQUIDITY_RATIO; @@ -1140,17 +1141,16 @@ mod LaunchpadMarketplace { // let k = pool_qty * INITIAL_SUPPLY; let k = pool_qty * qb_init_supply; let qb = pool_coin.token_holded.clone(); - + let q_out = qa + pool_qty / LIQUIDITY_RATIO - k / (qb + quote_amount); return q_out; + // let k = current_supply * pool_coin.liquidity_raised; + // let liquidity_ratio = total_supply / LIQUIDITY_RATIO; + // let q_out = (total_supply - liquidity_ratio) + (k / (quote_amount)); + // return q_out; + // let q_in = (k / (total_supply - quote_amount)) - (k_max / total_supply); + // return q_in; - // let k = current_supply * pool_coin.liquidity_raised; - // let liquidity_ratio = total_supply / LIQUIDITY_RATIO; - // let q_out = (total_supply - liquidity_ratio) + (k / (quote_amount)); - // return q_out; - // let q_in = (k / (total_supply - quote_amount)) - (k_max / total_supply); - // return q_in; - } // let mut current_price = self // ._get_linear_price(pool_coin.initial_key_price, pool_coin.slope, current_supply); diff --git a/onchain/cairo/src/lib.cairo b/onchain/cairo/src/lib.cairo index 2cce3149..083af35a 100644 --- a/onchain/cairo/src/lib.cairo +++ b/onchain/cairo/src/lib.cairo @@ -7,6 +7,24 @@ pub mod social; pub mod utils; pub mod quests { pub mod tap; +// TODO upgrade to correct OZ version +// pub use interfaces::{ +// IQuest, IAuthorityQuest, IPixelQuest, IRainbowQuest, IUnruggableQuest, IQuestDispatcher, +// IQuestDispatcherTrait, IUnruggableMemecoin, IUnruggableMemecoinDispatcher, +// IUnruggableMemecoinDispatcherTrait +// }; +// pub mod authority_quest; +// pub mod interfaces; +// pub mod pixel_quest; +// pub mod username_quest; +// pub mod rainbow_quest; +// pub mod template_quest; +// pub mod unruggable_quest; +// pub mod nft_quest; +// pub mod hodl_quest; +// pub mod faction_quest; +// pub mod chain_faction_quest; +// pub mod vote_quest; } pub mod interfaces { @@ -46,6 +64,21 @@ pub mod tokens { pub mod token; } +// TODO upgrade to correct OZ version +pub mod nfts { // pub mod canvas_nft; +// pub mod component; +// pub mod interfaces; +} + + +// pub mod pixel { +// // pub mod art_peace; +// pub mod interfaces; + +// // use art_peace::ArtPeace; + +// } + #[cfg(test)] pub mod tests { pub mod identity_tests; diff --git a/onchain/cairo/src/nfts.cairo b/onchain/cairo/src/nfts.cairo new file mode 100644 index 00000000..1b48ba08 --- /dev/null +++ b/onchain/cairo/src/nfts.cairo @@ -0,0 +1 @@ +pub mod nfts; diff --git a/onchain/cairo/src/nfts/canvas_nft.cairo b/onchain/cairo/src/nfts/canvas_nft.cairo new file mode 100644 index 00000000..bd015ae8 --- /dev/null +++ b/onchain/cairo/src/nfts/canvas_nft.cairo @@ -0,0 +1,147 @@ +#[starknet::contract] +mod CanvasNFT { + use afk::nfts::component::CanvasNFTStoreComponent::CanvasNFTMinted; + use afk::nfts::component::CanvasNFTStoreComponent; + use afk::nfts::interfaces::ICanvasNFTStore; + use afk::nfts::{ICanvasNFTAdditional, ICanvasNFTLikeAndUnlike, NFTMetadata}; + use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin::token::erc721::ERC721Component; + use openzeppelin::token::erc721::interface::IERC721Metadata; + use starknet::ContractAddress; + + component!(path: ERC721Component, storage: erc721, event: ERC721Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + component!(path: CanvasNFTStoreComponent, storage: nfts, event: NFTEvent); + + #[abi(embed_v0)] + impl ERC721Impl = ERC721Component::ERC721Impl; + #[abi(embed_v0)] + impl ERC721CamelOnly = ERC721Component::ERC721CamelOnlyImpl; + #[abi(embed_v0)] + impl ERC721MetadataCamelOnly = + ERC721Component::ERC721MetadataCamelOnlyImpl; + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + #[abi(embed_v0)] + impl CanvasNFTStoreImpl = + CanvasNFTStoreComponent::CanvasNFTStoreImpl; + + impl InternalImpl = ERC721Component::InternalImpl; + + #[storage] + struct Storage { + art_peace: ContractAddress, + #[substorage(v0)] + erc721: ERC721Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage, + #[substorage(v0)] + nfts: CanvasNFTStoreComponent::Storage, + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721Event: ERC721Component::Event, + #[flat] + SRC5Event: SRC5Component::Event, + #[flat] + NFTEvent: CanvasNFTStoreComponent::Event, + NFTLiked: NFTLiked, + NFTUnliked: NFTUnliked, + } + + #[derive(Drop, starknet::Event)] + struct NFTLiked { + #[key] + token_id: u256, + #[key] + user_address: ContractAddress + } + + #[derive(Drop, starknet::Event)] + struct NFTUnliked { + #[key] + token_id: u256, + #[key] + user_address: ContractAddress + } + + + #[constructor] + fn constructor(ref self: ContractState, name: ByteArray, symbol: ByteArray) { + let base_uri = "https://api.art-peace.net/nft-meta/nft-"; + self.erc721.initializer(name, symbol, base_uri); + } + + #[abi(embed_v0)] + impl ERC721Metadata of IERC721Metadata { + fn name(self: @ContractState) -> ByteArray { + self.erc721.ERC721_name.read() + } + + fn symbol(self: @ContractState) -> ByteArray { + self.erc721.ERC721_symbol.read() + } + + fn token_uri(self: @ContractState, token_id: u256) -> ByteArray { + assert(self.erc721._exists(token_id), 'Token does not exist'); + let base_uri = self.erc721._base_uri(); + if base_uri.len() == 0 { + return ""; + } else { + return format!("{}{}.json", base_uri, token_id); + } + } + } + + #[abi(embed_v0)] + impl CanvasNFTAdditional of ICanvasNFTAdditional { + fn set_canvas_contract(ref self: ContractState, canvas_contract: ContractAddress) { + let zero_address = starknet::contract_address_const::<0>(); + assert(self.art_peace.read() == zero_address, 'ArtPeace contract already set'); + self.art_peace.write(canvas_contract); + } + + fn mint(ref self: ContractState, metadata: NFTMetadata, receiver: ContractAddress) { + assert( + self.art_peace.read() == starknet::get_caller_address(), + 'Only ArtPeace contract can mint' + ); + let token_id = self.nfts.get_nfts_count(); + self.nfts.nfts_data.write(token_id, metadata); + self.erc721._mint(receiver, token_id); + self.nfts.nfts_count.write(token_id + 1); + self.nfts.emit(CanvasNFTMinted { token_id, metadata }); + } + + fn set_base_uri(ref self: ContractState, base_uri: ByteArray) { + assert( + self.art_peace.read() == starknet::get_caller_address(), + 'Only ArtPeace can set base uri' + ); + self.erc721._set_base_uri(base_uri); + } + } + + #[abi(embed_v0)] + impl CanvasNFTLikeAndUnlike of ICanvasNFTLikeAndUnlike { + fn like_nft(ref self: ContractState, token_id: u256) { + assert(token_id < self.get_nfts_count(), 'NFT Does not Exist in the Store'); + + self + .emit( + NFTLiked { user_address: starknet::get_caller_address(), token_id: token_id } + ); + } + + fn unlike_nft(ref self: ContractState, token_id: u256) { + assert(token_id < self.get_nfts_count(), 'NFT Does not Exist in the Store'); + self + .emit( + NFTUnliked { user_address: starknet::get_caller_address(), token_id: token_id } + ); + } + } +} diff --git a/onchain/cairo/src/nfts/component.cairo b/onchain/cairo/src/nfts/component.cairo new file mode 100644 index 00000000..55539beb --- /dev/null +++ b/onchain/cairo/src/nfts/component.cairo @@ -0,0 +1,54 @@ +#[starknet::component] +pub mod CanvasNFTStoreComponent { + use afk::nfts::interfaces::{ICanvasNFTStore, NFTMetadata}; + + #[storage] + struct Storage { + nfts_count: u256, + // Map: nft's token_id -> nft's metadata + nfts_data: LegacyMap::, + } + + #[event] + #[derive(Drop, starknet::Event)] + pub enum Event { + CanvasNFTMinted: CanvasNFTMinted, + } + + #[derive(Drop, starknet::Event)] + pub struct CanvasNFTMinted { + #[key] + pub token_id: u256, + pub metadata: NFTMetadata, + } + + #[embeddable_as(CanvasNFTStoreImpl)] + impl CanvasNFTStore< + TContractState, +HasComponent + > of ICanvasNFTStore> { + fn get_nfts_count(self: @ComponentState) -> u256 { + return self.nfts_count.read(); + } + + fn get_nft_metadata(self: @ComponentState, token_id: u256) -> NFTMetadata { + return self.nfts_data.read(token_id); + } + + fn get_nft_minter( + self: @ComponentState, token_id: u256 + ) -> starknet::ContractAddress { + let metadata: NFTMetadata = self.nfts_data.read(token_id); + return metadata.minter; + } + + fn get_nft_day_index(self: @ComponentState, token_id: u256) -> u32 { + let metadata: NFTMetadata = self.nfts_data.read(token_id); + return metadata.day_index; + } + + fn get_nft_image_hash(self: @ComponentState, token_id: u256) -> felt252 { + let metadata: NFTMetadata = self.nfts_data.read(token_id); + return metadata.image_hash; + } + } +} diff --git a/onchain/cairo/src/nfts/interfaces.cairo b/onchain/cairo/src/nfts/interfaces.cairo new file mode 100644 index 00000000..f0cbc7db --- /dev/null +++ b/onchain/cairo/src/nfts/interfaces.cairo @@ -0,0 +1,58 @@ +#[derive(Drop, Serde)] +pub struct NFTMintParams { + pub position: u128, + pub width: u128, + pub height: u128, + pub name: felt252, +} + +#[derive(Drop, Copy, Serde, PartialEq, starknet::Store)] +pub struct NFTMetadata { + pub position: u128, + pub width: u128, + pub height: u128, + pub name: felt252, + pub image_hash: felt252, + pub block_number: u64, + pub day_index: u32, + pub minter: starknet::ContractAddress, +} + +#[starknet::interface] +pub trait ICanvasNFTStore { + // Returns the on-chain metadata of the NFT. + fn get_nft_metadata(self: @TContractState, token_id: u256) -> NFTMetadata; + fn get_nft_minter(self: @TContractState, token_id: u256) -> starknet::ContractAddress; + fn get_nft_image_hash(self: @TContractState, token_id: u256) -> felt252; + fn get_nft_day_index(self: @TContractState, token_id: u256) -> u32; + + // Returns the number of NFTs stored in the contract state. + fn get_nfts_count(self: @TContractState) -> u256; +} + +#[starknet::interface] +pub trait ICanvasNFTAdditional { + // Sets up the contract addresses + fn set_canvas_contract(ref self: TContractState, canvas_contract: starknet::ContractAddress); + // Mint a new NFT called by the ArtPeaceNFTMinter contract. + fn mint(ref self: TContractState, metadata: NFTMetadata, receiver: starknet::ContractAddress); + // Change the base uri of the NFTs. + fn set_base_uri(ref self: TContractState, base_uri: ByteArray); +} + +#[starknet::interface] +pub trait IArtPeaceNFTMinter { + // Sets up the contract addresses + fn add_nft_contract(ref self: TContractState, nft_contract: starknet::ContractAddress); + // Mints a new NFT from the canvas using init params, and returns the token ID. + fn mint_nft(ref self: TContractState, mint_params: NFTMintParams); + // Change the base uri of the NFTs. + fn set_nft_base_uri(ref self: TContractState, base_uri: ByteArray); +} + +#[starknet::interface] +pub trait ICanvasNFTLikeAndUnlike { + fn like_nft(ref self: TContractState, token_id: u256); + fn unlike_nft(ref self: TContractState, token_id: u256); +} + diff --git a/onchain/cairo/src/nfts/mod.cairo b/onchain/cairo/src/nfts/mod.cairo new file mode 100644 index 00000000..9964374b --- /dev/null +++ b/onchain/cairo/src/nfts/mod.cairo @@ -0,0 +1,15 @@ +pub mod nfts { + mod canvas_nft; + pub mod component; + // pub mod canvas_nft; + // pub mod component; + // pub mod interfaces; + pub mod interfaces; + + use interfaces::{ + NFTMintParams, NFTMetadata, IArtPeaceNFTMinter, ICanvasNFTStoreDispatcher, + ICanvasNFTStoreDispatcherTrait, IArtPeaceNFTMinterDispatcher, + IArtPeaceNFTMinterDispatcherTrait, ICanvasNFTAdditional, ICanvasNFTLikeAndUnlike, + ICanvasNFTAdditionalDispatcher, ICanvasNFTAdditionalDispatcherTrait + }; +} diff --git a/onchain/cairo/src/pixel.cairo b/onchain/cairo/src/pixel.cairo new file mode 100644 index 00000000..0ad4285c --- /dev/null +++ b/onchain/cairo/src/pixel.cairo @@ -0,0 +1 @@ +pub mod pixel; diff --git a/onchain/cairo/src/quests/authority_quest.cairo b/onchain/cairo/src/quests/authority_quest.cairo new file mode 100644 index 00000000..e9613588 --- /dev/null +++ b/onchain/cairo/src/quests/authority_quest.cairo @@ -0,0 +1,81 @@ +#[starknet::contract] +pub mod AuthorityQuest { + use afk::pixel::templates::interfaces::{ + ITemplateStoreDispatcher, ITemplateStoreDispatcherTrait + }; + use afk::quests::{IAuthorityQuest, IQuest}; + + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + art_peace: ContractAddress, + authority: ContractAddress, + reward: u32, + claimable: LegacyMap, + claimed: LegacyMap, + } + + #[derive(Drop, Serde)] + pub struct AuthorityQuestInitParams { + pub art_peace: ContractAddress, + pub authority: ContractAddress, + pub reward: u32, + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: AuthorityQuestInitParams) { + self.art_peace.write(init_params.art_peace); + self.authority.write(init_params.authority); + self.reward.write(init_params.reward); + } + + #[abi(embed_v0)] + impl AuthorityQuestImpl of IAuthorityQuest { + fn is_claimed(self: @ContractState, user: ContractAddress) -> bool { + self.claimed.read(user) + } + + fn mark_claimable(ref self: ContractState, calldata: Span) { + assert(get_caller_address() == self.authority.read(), 'Only authority address allowed'); + let mut i = 0; + while i < calldata + .len() { + self.claimable.write((*calldata[i]).try_into().unwrap(), true); + i += 1; + } + } + } + + #[abi(embed_v0)] + impl AuthorityQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + if self.claimed.read(user) { + return false; + } + + if self.claimable.read(user) { + true + } else { + false + } + } + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests'); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} diff --git a/onchain/cairo/src/quests/chain_faction_quest.cairo b/onchain/cairo/src/quests/chain_faction_quest.cairo new file mode 100644 index 00000000..78a073dc --- /dev/null +++ b/onchain/cairo/src/quests/chain_faction_quest.cairo @@ -0,0 +1,67 @@ +#[starknet::contract] +pub mod ChainFactionQuest { + use afk::pixel::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait}; + use afk::quests::{IQuest}; + + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + art_peace: ContractAddress, + reward: u32, + claimed: LegacyMap, + } + + #[derive(Drop, Serde)] + pub struct ChainFactionQuestInitParams { + pub art_peace: ContractAddress, + pub reward: u32, + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: ChainFactionQuestInitParams) { + self.art_peace.write(init_params.art_peace); + self.reward.write(init_params.reward); + } + + + #[abi(embed_v0)] + impl ChainFactionQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + if self.claimed.read(user) { + return false; + } + + let art_peace_dispatcher = IArtPeaceDispatcher { + contract_address: self.art_peace.read() + }; + + let user_faction = art_peace_dispatcher.get_user_chain_faction(user); + + if user_faction == 0 { + return false; + } + + return true; + } + + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests'); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} + diff --git a/onchain/cairo/src/quests/faction_quest.cairo b/onchain/cairo/src/quests/faction_quest.cairo new file mode 100644 index 00000000..830f5548 --- /dev/null +++ b/onchain/cairo/src/quests/faction_quest.cairo @@ -0,0 +1,67 @@ +#[starknet::contract] +pub mod FactionQuest { + use afk::pixel::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait}; + use afk::quests::{IQuest}; + + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + art_peace: ContractAddress, + reward: u32, + claimed: LegacyMap, + } + + #[derive(Drop, Serde)] + pub struct FactionQuestInitParams { + pub art_peace: ContractAddress, + pub reward: u32, + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: FactionQuestInitParams) { + self.art_peace.write(init_params.art_peace); + self.reward.write(init_params.reward); + } + + + #[abi(embed_v0)] + impl FactionQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + if self.claimed.read(user) { + return false; + } + + let art_peace_dispatcher = IArtPeaceDispatcher { + contract_address: self.art_peace.read() + }; + + let user_faction = art_peace_dispatcher.get_user_faction(user); + + if user_faction == 0 { + return false; + } + + return true; + } + + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests'); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} + diff --git a/onchain/cairo/src/quests/hodl_quest.cairo b/onchain/cairo/src/quests/hodl_quest.cairo new file mode 100644 index 00000000..8db5aefb --- /dev/null +++ b/onchain/cairo/src/quests/hodl_quest.cairo @@ -0,0 +1,68 @@ +#[starknet::contract] +pub mod HodlQuest { + use afk::pixel::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait}; + use afk::quests::{IQuest}; + use core::traits::TryInto; + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + art_peace: ContractAddress, + reward: u32, + extra_pixels_needed: u32, + claimed: LegacyMap, + } + + + #[derive(Drop, Serde)] + pub struct HodlQuestInitParams { + pub art_peace: ContractAddress, + pub reward: u32, + pub extra_pixels_needed: u32 + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: HodlQuestInitParams) { + self.art_peace.write(init_params.art_peace); + self.reward.write(init_params.reward); + self.extra_pixels_needed.write(init_params.extra_pixels_needed); + } + + #[abi(embed_v0)] + impl HodlQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + if self.claimed.read(user) { + return false; + } + + let art_peace_dispatcher = IArtPeaceDispatcher { + contract_address: self.art_peace.read() + }; + + let user_extra_pixels = art_peace_dispatcher.get_user_extra_pixels_count(user.into()); + + if user_extra_pixels >= self.extra_pixels_needed.read() { + return true; + } + + false + } + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests'); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} diff --git a/onchain/cairo/src/quests/interfaces.cairo b/onchain/cairo/src/quests/interfaces.cairo new file mode 100644 index 00000000..4be9f6bc --- /dev/null +++ b/onchain/cairo/src/quests/interfaces.cairo @@ -0,0 +1,51 @@ +use starknet::ContractAddress; + +#[starknet::interface] +pub trait IQuest { + // Return the reward for the quest. + fn get_reward(self: @TContractState) -> u32; + // Return if the user can claim the quest. + fn is_claimable(self: @TContractState, user: ContractAddress, calldata: Span) -> bool; + // Claim the quest. + fn claim(ref self: TContractState, user: ContractAddress, calldata: Span) -> u32; +} + +#[starknet::interface] +pub trait IAuthorityQuest { + fn is_claimed(self: @TContractState, user: ContractAddress) -> bool; + fn mark_claimable(ref self: TContractState, calldata: Span); +} + +#[starknet::interface] +pub trait IPixelQuest { + fn is_claimed(self: @TContractState, user: starknet::ContractAddress) -> bool; + fn get_pixels_needed(self: @TContractState) -> u32; + fn is_daily(self: @TContractState) -> bool; + fn claim_day(self: @TContractState) -> u32; + fn is_color(self: @TContractState) -> bool; + fn color(self: @TContractState) -> u8; +} + +#[starknet::interface] +pub trait IRainbowQuest { + fn is_claimed(self: @TContractState, user: starknet::ContractAddress) -> bool; +} + + +#[starknet::interface] +pub trait IFactionQuest { + fn is_claimed(self: @TContractState, user: starknet::ContractAddress) -> bool; +} + +#[starknet::interface] +pub trait IUnruggableQuest { + fn is_claimed(self: @TContractState, user: starknet::ContractAddress) -> bool; +} + +#[starknet::interface] +pub trait IUnruggableMemecoin { + // Returns the owner of the unruggable memecoin + fn owner(self: @TState) -> ContractAddress; + // Checks whether token has launched + fn is_launched(self: @TState) -> bool; +} diff --git a/onchain/cairo/src/quests/mod.cairo b/onchain/cairo/src/quests/mod.cairo index 5b1463d6..08aab01b 100644 --- a/onchain/cairo/src/quests/mod.cairo +++ b/onchain/cairo/src/quests/mod.cairo @@ -1,3 +1,46 @@ +pub use interfaces::{ + IQuest, IAuthorityQuest, IPixelQuest, IRainbowQuest, IUnruggableQuest, IQuestDispatcher, + IQuestDispatcherTrait, IUnruggableMemecoin, IUnruggableMemecoinDispatcher, + IUnruggableMemecoinDispatcherTrait +}; + pub mod quests { + pub mod authority_quest; + pub mod chain_faction_quest; + pub mod faction_quest; + pub mod hodl_quest; + pub mod interfaces; + pub mod nft_quest; + pub mod pixel_quest; + pub mod rainbow_quest; pub mod tap; + pub mod template_quest; + pub mod unruggable_quest; + pub mod username_quest; + pub mod vote_quest; + + pub use interfaces::{ + IQuest, IAuthorityQuest, IPixelQuest, IRainbowQuest, IUnruggableQuest, IQuestDispatcher, + IQuestDispatcherTrait, IUnruggableMemecoin, IUnruggableMemecoinDispatcher, + IUnruggableMemecoinDispatcherTrait + }; +// #[cfg(test)] +// mod tests { +// pub(crate) mod art_peace; +// pub(crate) mod username_store; +// pub(crate) mod authority_quest; +// pub(crate) mod username_quest; +// pub(crate) mod color_voting; +// pub(crate) mod nft_quest; +// pub(crate) mod hodl_quest; +// pub(crate) mod pixel_quest; +// pub(crate) mod faction_quest; +// pub(crate) mod chain_faction_quest; +// pub(crate) mod rainbow_quest; +// pub(crate) mod template_quest; +// pub(crate) mod unruggable_quest; +// pub(crate) mod vote_quest; +// pub(crate) mod utils; +// } + } diff --git a/onchain/cairo/src/quests/nft_quest.cairo b/onchain/cairo/src/quests/nft_quest.cairo new file mode 100644 index 00000000..f39d810a --- /dev/null +++ b/onchain/cairo/src/quests/nft_quest.cairo @@ -0,0 +1,80 @@ +#[starknet::contract] +pub mod NFTMintQuest { + use afk::pixel::nfts::interfaces::{ICanvasNFTStoreDispatcher, ICanvasNFTStoreDispatcherTrait}; + use afk::quests::IQuest; + + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + canvas_nft: ContractAddress, + art_peace: ContractAddress, + reward: u32, + is_daily: bool, + day_index: u32, + claimed: LegacyMap, + } + + #[derive(Drop, Serde)] + pub struct NFTMintQuestInitParams { + pub canvas_nft: ContractAddress, + pub art_peace: ContractAddress, + pub reward: u32, + pub is_daily: bool, + pub day_index: u32, + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: NFTMintQuestInitParams) { + self.canvas_nft.write(init_params.canvas_nft); + self.art_peace.write(init_params.art_peace); + self.reward.write(init_params.reward); + self.is_daily.write(init_params.is_daily); + self.day_index.write(init_params.day_index); + } + + #[abi(embed_v0)] + impl NFTMintQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + if self.claimed.read(user) { + return false; + } + + let token_id_felt = *calldata.at(0); + let token_id: u256 = token_id_felt.into(); + + let nft_store = ICanvasNFTStoreDispatcher { contract_address: self.canvas_nft.read() }; + let token_minter = nft_store.get_nft_minter(token_id); + + if token_minter != user { + return false; + } + + if self.is_daily.read() { + let day_index = nft_store.get_nft_day_index(token_id); + if day_index != self.day_index.read() { + return false; + } + } + + return true; + } + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests'); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} diff --git a/onchain/cairo/src/quests/pixel_quest.cairo b/onchain/cairo/src/quests/pixel_quest.cairo new file mode 100644 index 00000000..68ecedbf --- /dev/null +++ b/onchain/cairo/src/quests/pixel_quest.cairo @@ -0,0 +1,127 @@ +#[starknet::contract] +pub mod PixelQuest { + use afk::pixel::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait}; + use afk::quests::{IQuest, IPixelQuest}; + + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + art_peace: IArtPeaceDispatcher, + reward: u32, + claimed: LegacyMap, + pixels_needed: u32, + // Quest types + is_daily: bool, // If the quest is a daily quest + // The day idx the quest can be claimed ( if daily ) + claim_day: u32, + is_color: bool, // If the quest is for a specific color + color: u8, + } + + #[derive(Drop, Serde)] + pub struct PixelQuestInitParams { + pub art_peace: ContractAddress, + pub reward: u32, + pub pixels_needed: u32, + pub is_daily: bool, + pub claim_day: u32, + pub is_color: bool, + pub color: u8, + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: PixelQuestInitParams) { + self.art_peace.write(IArtPeaceDispatcher { contract_address: init_params.art_peace }); + self.reward.write(init_params.reward); + self.pixels_needed.write(init_params.pixels_needed); + self.is_daily.write(init_params.is_daily); + self.claim_day.write(init_params.claim_day); + self.is_color.write(init_params.is_color); + self.color.write(init_params.color); + } + + #[abi(embed_v0)] + impl PixelQuestImpl of IPixelQuest { + fn is_claimed(self: @ContractState, user: ContractAddress) -> bool { + self.claimed.read(user) + } + + fn get_pixels_needed(self: @ContractState) -> u32 { + self.pixels_needed.read() + } + + fn is_daily(self: @ContractState) -> bool { + self.is_daily.read() + } + + fn claim_day(self: @ContractState) -> u32 { + self.claim_day.read() + } + + fn is_color(self: @ContractState) -> bool { + return self.is_color.read(); + } + + fn color(self: @ContractState) -> u8 { + return self.color.read(); + } + } + + #[abi(embed_v0)] + impl PixelQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + let art_peace = self.art_peace.read(); + if self.claimed.read(user) { + return false; + } + + // Daily Pixel Quest + if self.is_daily.read() { + let day = art_peace.get_day(); + if day != self.claim_day.read() { + return false; + } + + if self.is_color.read() { + let placement_count = art_peace + .get_user_pixels_placed_day_color(user, day, self.color.read()); + return placement_count >= self.pixels_needed.read(); + } else { // Daily Pixel Quest + let placement_count = art_peace.get_user_pixels_placed_day(user, day); + return placement_count >= self.pixels_needed.read(); + } + } // Main Pixel Quest + else { + if self.is_color.read() { + let placement_count = art_peace + .get_user_pixels_placed_color(user, self.color.read()); + return placement_count >= self.pixels_needed.read(); + } else { + let placement_count = art_peace.get_user_pixels_placed(user); + return placement_count >= self.pixels_needed.read(); + } + } + } + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert( + get_caller_address() == self.art_peace.read().contract_address, + 'Only ArtPeace can claim quests' + ); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} diff --git a/onchain/cairo/src/quests/rainbow_quest.cairo b/onchain/cairo/src/quests/rainbow_quest.cairo new file mode 100644 index 00000000..62d2de38 --- /dev/null +++ b/onchain/cairo/src/quests/rainbow_quest.cairo @@ -0,0 +1,76 @@ +#[starknet::contract] +pub mod RainbowQuest { + use afk::pixel::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait}; + use afk::quests::{IQuest, IRainbowQuest}; + + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + art_peace: ContractAddress, + reward: u32, + claimed: LegacyMap, + } + + #[derive(Drop, Serde)] + pub struct RainbowQuestInitParams { + pub art_peace: ContractAddress, + pub reward: u32, + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: RainbowQuestInitParams) { + self.art_peace.write(init_params.art_peace); + self.reward.write(init_params.reward); + } + + #[abi(embed_v0)] + impl RainbowQuestImpl of IRainbowQuest { + fn is_claimed(self: @ContractState, user: ContractAddress) -> bool { + self.claimed.read(user) + } + } + + #[abi(embed_v0)] + impl RainbowQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + if self.claimed.read(user) { + return false; + } + + let art_piece = IArtPeaceDispatcher { contract_address: self.art_peace.read() }; + + let mut result = true; + let mut i = 0; + while i < art_piece + .get_color_count() { + if (art_piece.get_user_pixels_placed_color(user, i) == 0) { + result = false; + break; + } + + i += 1; + }; + + result + } + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests'); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} + diff --git a/onchain/cairo/src/quests/template_quest.cairo b/onchain/cairo/src/quests/template_quest.cairo new file mode 100644 index 00000000..918166d1 --- /dev/null +++ b/onchain/cairo/src/quests/template_quest.cairo @@ -0,0 +1,68 @@ +#[starknet::contract] +pub mod TemplateQuest { + use afk::pixel::templates::interfaces::{ + ITemplateStoreDispatcher, ITemplateStoreDispatcherTrait + }; + use afk::quests::IQuest; + + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + art_peace: ContractAddress, + reward: u32, + claimed: LegacyMap, + } + + #[derive(Drop, Serde)] + pub struct TemplateQuestInitParams { + pub art_peace: ContractAddress, + pub reward: u32, + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: TemplateQuestInitParams) { + self.art_peace.write(init_params.art_peace); + self.reward.write(init_params.reward); + } + + #[abi(embed_v0)] + impl TemplateQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + if self.claimed.read(user) { + return false; + } + + let template_id_felt = *calldata.at(0); + let template_id: u32 = template_id_felt.try_into().unwrap(); + + let template_store = ITemplateStoreDispatcher { + contract_address: self.art_peace.read() + }; + let template = template_store.get_template(template_id); + + if template.creator != user { + return false; + } + + return true; + } + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests'); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} diff --git a/onchain/cairo/src/quests/unruggable_quest.cairo b/onchain/cairo/src/quests/unruggable_quest.cairo new file mode 100644 index 00000000..200c0f42 --- /dev/null +++ b/onchain/cairo/src/quests/unruggable_quest.cairo @@ -0,0 +1,73 @@ +#[starknet::contract] +pub mod UnruggableQuest { + use afk::pixel::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait}; + use afk::quests::{ + IQuest, IUnruggableQuest, IUnruggableMemecoinDispatcher, IUnruggableMemecoinDispatcherTrait + }; + + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + art_peace: ContractAddress, + reward: u32, + claimed: LegacyMap, + } + + #[derive(Drop, Serde)] + pub struct UnruggableQuestInitParams { + pub art_peace: ContractAddress, + pub reward: u32, + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: UnruggableQuestInitParams) { + self.art_peace.write(init_params.art_peace); + self.reward.write(init_params.reward); + } + + #[abi(embed_v0)] + impl UnruggableQuestImpl of IUnruggableQuest { + fn is_claimed(self: @ContractState, user: ContractAddress) -> bool { + self.claimed.read(user) + } + } + + #[abi(embed_v0)] + impl UnruggableQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + if self.claimed.read(user) { + return false; + } + + let coin_address_as_felt252: felt252 = *calldata.at(0); + let coin = IUnruggableMemecoinDispatcher { + contract_address: coin_address_as_felt252.try_into().unwrap() + }; + + if coin.is_launched() != true { + return false; + } + + true + } + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests'); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} + diff --git a/onchain/cairo/src/quests/username_quest.cairo b/onchain/cairo/src/quests/username_quest.cairo new file mode 100644 index 00000000..5ad56c2e --- /dev/null +++ b/onchain/cairo/src/quests/username_quest.cairo @@ -0,0 +1,66 @@ +#[starknet::contract] +pub mod UsernameQuest { + use afk::pixel::username_store::interfaces::{ + IUsernameStoreDispatcher, IUsernameStoreDispatcherTrait, + }; + use afk::quests::{IQuest}; + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + art_peace: ContractAddress, + reward: u32, + username_store: IUsernameStoreDispatcher, + claimed: LegacyMap, + } + + + #[derive(Drop, Serde)] + pub struct UsernameQuestInitParams { + pub art_peace: ContractAddress, + pub reward: u32, + pub username_store: ContractAddress, + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: UsernameQuestInitParams) { + self.art_peace.write(init_params.art_peace); + self.reward.write(init_params.reward); + self + .username_store + .write(IUsernameStoreDispatcher { contract_address: init_params.username_store }); + } + + #[abi(embed_v0)] + impl UsernameQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + if self.claimed.read(user) { + return false; + } + + let username = self.username_store.read().get_username(user); + if username == 0 { + return false; + } + + return true; + } + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests'); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} diff --git a/onchain/cairo/src/quests/vote_quest.cairo b/onchain/cairo/src/quests/vote_quest.cairo new file mode 100644 index 00000000..f7d4e865 --- /dev/null +++ b/onchain/cairo/src/quests/vote_quest.cairo @@ -0,0 +1,67 @@ +#[starknet::contract] +pub mod VoteQuest { + use afk::pixel::{quests::IQuest}; + use afk::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait}; + use starknet::{ContractAddress, get_caller_address}; + + #[storage] + struct Storage { + art_peace: ContractAddress, + reward: u32, + day_index: u32, + claimed: LegacyMap, + } + + #[derive(Drop, Serde)] + pub struct VoteQuestInitParams { + pub art_peace: ContractAddress, + pub reward: u32, + pub day_index: u32 + } + + #[constructor] + fn constructor(ref self: ContractState, init_params: VoteQuestInitParams) { + self.art_peace.write(init_params.art_peace); + self.reward.write(init_params.reward); + self.day_index.write(init_params.day_index); + } + + #[abi(embed_v0)] + impl VoteQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + if self.claimed.read(user) { + return false; + } + + let day_index = self.day_index.read(); + let art_peace_dispatcher = IArtPeaceDispatcher { + contract_address: self.art_peace.read() + }; + + // 0, if user has not voted for any color + let user_vote: u8 = art_peace_dispatcher.get_user_vote(user, day_index); + if user_vote == 0 { + return false; + } else { + return true; + } + } + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests'); + + assert(self.is_claimable(user, calldata), 'Quest not claimable'); + + self.claimed.write(user, true); + let reward = self.reward.read(); + + reward + } + } +} diff --git a/onchain/cairo/src/social/account.cairo b/onchain/cairo/src/social/account.cairo index 3009bf69..03ef96e2 100644 --- a/onchain/cairo/src/social/account.cairo +++ b/onchain/cairo/src/social/account.cairo @@ -152,7 +152,6 @@ pub mod SocialAccount { } } } - // #[cfg(test)] // mod tests { // use afk::tokens::erc20::{ERC20, IERC20Dispatcher, IERC20DispatcherTrait}; @@ -440,3 +439,5 @@ pub mod SocialAccount { // stop_cheat_signature_global(); // } // } + + diff --git a/onchain/cairo/src/tests/launchpad_tests.cairo b/onchain/cairo/src/tests/launchpad_tests.cairo index e4700a8e..f8d10008 100644 --- a/onchain/cairo/src/tests/launchpad_tests.cairo +++ b/onchain/cairo/src/tests/launchpad_tests.cairo @@ -320,26 +320,18 @@ mod launchpad_tests { println!("test token_address {:?}", token_address); let memecoin = IERC20Dispatcher { contract_address: token_address }; - // All buy - let mut first_buy=10_u256; - run_buy_by_amount( - launchpad, erc20, memecoin, first_buy, token_address, sender_address, - ); + let mut first_buy = 10_u256; + run_buy_by_amount(launchpad, erc20, memecoin, first_buy, token_address, sender_address,); - run_buy_by_amount( - launchpad, erc20, memecoin, first_buy, token_address, sender_address, - ); + run_buy_by_amount(launchpad, erc20, memecoin, first_buy, token_address, sender_address,); run_buy_by_amount( launchpad, erc20, memecoin, THRESHOLD_LIQUIDITY / 10, token_address, sender_address, ); - - } - #[test] fn launchpad_buy_all() { println!("launchpad_buy_all"); @@ -405,19 +397,16 @@ mod launchpad_tests { ); // let mut total_amount_buy = amount_first_buy; - let new_amount=THRESHOLD_LIQUIDITY - amount_first_buy; + let new_amount = THRESHOLD_LIQUIDITY - amount_first_buy; // // First sell with 10 quote token run_sell_by_amount( launchpad, erc20, memecoin, amount_first_buy, token_address, sender_address, ); + // // Threshold buy - 1 + // run_buy_by_amount( + // launchpad, erc20, memecoin, new_amount, token_address, sender_address, + // ); - // // Threshold buy - 1 - // run_buy_by_amount( - // launchpad, erc20, memecoin, new_amount, token_address, sender_address, - // ); - - - } @@ -518,7 +507,6 @@ mod launchpad_tests { run_buy_by_amount( launchpad, erc20, memecoin, amount_second, token_address, sender_address, ); - } @@ -625,7 +613,6 @@ mod launchpad_tests { launchpad, amount_to_buy, token_address, sender_address, true, true ); println!("amount_coin_sell {:?}", amount_coin_sell); - assert!(amount_coin_get==amount_coin_sell, "amount incorrect"); - + assert!(amount_coin_get == amount_coin_sell, "amount incorrect"); } } diff --git a/packages/afk_nostr_sdk/src/hooks/useAllProfiles.ts b/packages/afk_nostr_sdk/src/hooks/useAllProfiles.ts index 835af5d4..82b49fc0 100644 --- a/packages/afk_nostr_sdk/src/hooks/useAllProfiles.ts +++ b/packages/afk_nostr_sdk/src/hooks/useAllProfiles.ts @@ -6,6 +6,7 @@ import {useNostrContext} from '../context/NostrContext'; export type UseRootProfilesOptions = { authors?: string[]; search?: string; + limit?:number; }; export const useAllProfiles = (options?: UseRootProfilesOptions) => { @@ -28,7 +29,7 @@ export const useAllProfiles = (options?: UseRootProfilesOptions) => { authors: options?.authors, search: options?.search, until: pageParam || Math.round(Date.now() / 1000), - limit: 20, + limit: options?.limit ?? 20, }); return [...notes].filter((note) => note.tags.every((tag) => tag[0] !== 'e')); diff --git a/packages/afk_nostr_sdk/src/hooks/useBookmark.ts b/packages/afk_nostr_sdk/src/hooks/useBookmark.ts index 4e4263ad..9f541109 100644 --- a/packages/afk_nostr_sdk/src/hooks/useBookmark.ts +++ b/packages/afk_nostr_sdk/src/hooks/useBookmark.ts @@ -164,10 +164,13 @@ export const useBookmark = (userPublicKey: string) => { // Remove the specific event bookmarkEvent.tags = bookmarkEvent.tags.filter(tag => !(tag[0] === 'e' && tag[1] === eventId)); - if (bookmarkEvent.tags.length > 0) { - await bookmarkEvent.sign(); - await bookmarkEvent.publish(); - } + + await bookmarkEvent.sign(); + await bookmarkEvent.publish(); + // if (bookmarkEvent.tags.length > 0) { + // await bookmarkEvent.sign(); + // await bookmarkEvent.publish(); + // } }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['bookmarks', userPublicKey] });