diff --git a/.all-contributorsrc b/.all-contributorsrc index 36f47f30..d9607ec5 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -81,6 +81,33 @@ "contributions": [ "code" ] + }, + { + "login": "manlikeHB", + "name": "Yusuf Habib", + "avatar_url": "https://avatars.githubusercontent.com/u/109147010?v=4", + "profile": "https://github.com/manlikeHB", + "contributions": [ + "code" + ] + }, + { + "login": "Dprof-in-tech", + "name": "Isaac Onyemaechi Ugwu", + "avatar_url": "https://avatars.githubusercontent.com/u/116242877?v=4", + "profile": "https://isaaconyemaechi.tech/", + "contributions": [ + "code" + ] + }, + { + "login": "EjembiEmmanuel", + "name": "Oche", + "avatar_url": "https://avatars.githubusercontent.com/u/83036156?v=4", + "profile": "https://github.com/EjembiEmmanuel", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/.gitmodules b/.gitmodules index 3fe95c27..13973c8a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,9 @@ -[submodule "solidity/solidity_contracts/lib/kakarot-lib"] - path = solidity/solidity_contracts/lib/kakarot-lib - url = https://github.com/kkrt-labs/kakarot-lib -[submodule "solidity/solidity_contracts/lib/forge-std"] - path = solidity/solidity_contracts/lib/forge-std +[submodule "onchain/lib/kakarot-rpc"] + path = onchain/lib/kakarot-rpc + url = https://github.com/kkrt-labs/kakarot-rpc +[submodule "onchain/solidity_contracts/lib/forge-std"] + path = onchain/solidity_contracts/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "onchain/solidity_contracts/lib/kakarot-lib"] + path = onchain/solidity_contracts/lib/kakarot-lib + url = https://github.com/kkrt-labs/kakarot-lib diff --git a/README.md b/README.md index b7dfb67d..35b8d931 100644 --- a/README.md +++ b/README.md @@ -236,6 +236,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Bhavya Gosai
Bhavya Gosai

💻 + Yusuf Habib
Yusuf Habib

💻 + Isaac Onyemaechi Ugwu
Isaac Onyemaechi Ugwu

💻 + Oche
Oche

💻 diff --git a/apps/indexer/src/constants.js b/apps/indexer/src/constants.js index 2bd1a0a1..c5ec894b 100644 --- a/apps/indexer/src/constants.js +++ b/apps/indexer/src/constants.js @@ -2,5 +2,6 @@ export const FACTORY_ADDRESS = '0x01a46467a9246f45c8c340f1f155266a26a71c07bd55d3 export const STARTING_BLOCK = 100_000 export const LAUNCHPAD_ADDRESS = { // SEPOLIA:"0x74acb6752abb734a7b3388567429217988e02409d9bf43c5586dc2c4f8baf40", - SEPOLIA:"0x29a532e6933a6d6f9939e59469d96b52b7c38561745331302e1a29f035e4dd0" + // SEPOLIA:"0x29a532e6933a6d6f9939e59469d96b52b7c38561745331302e1a29f035e4dd0", + SEPOLIA:"0x3798921000573bfc442d8153fc088db97bd3794f5ed19ea8c0846db5378f4af" } diff --git a/apps/indexer/src/deploy-token.js b/apps/indexer/src/deploy-token.js index 40877873..b2e88bb0 100644 --- a/apps/indexer/src/deploy-token.js +++ b/apps/indexer/src/deploy-token.js @@ -34,11 +34,14 @@ export default function DecodeTokenDeploy({ header, events }) { if (!event.data || !event.keys) return; const transactionHash = transaction.meta.hash; - const [caller, token_address, name, symbol] = event.keys; + const [caller, token_address, + // name, symbol + ] = event.keys; const [ - initial_supply_low, initial_supply_high, + initial_supply_low, initial_supply_high, total_supply_low, total_supply_high, + symbol, name ] = event.data; const initial_supply = uint256.uint256ToBN({ low: initial_supply_low, high: initial_supply_high }).toString(); diff --git a/apps/indexer/src/token-launch.js b/apps/indexer/src/token-launch.js index a3fea4a4..559db270 100644 --- a/apps/indexer/src/token-launch.js +++ b/apps/indexer/src/token-launch.js @@ -49,7 +49,7 @@ export default function DecodeTokenLaunchDeploy({ header, events }) { const name_decoded = shortString.decodeShortString(name.replace(/0x0+/, '0x')) const symbol_decoded = shortString.decodeShortString(symbol.replace(/0x0+/, '0x')) - const quote_token_decoded = quote_token ? shortString.decodeShortString(quote_token.replace(/0x0+/, '0x')) : ''; + const quote_token_decoded = token_address ? shortString.decodeShortString(token_address.replace(/0x0+/, '0x')) : ''; const exchange_name_decoded = exchange_name ? shortString.decodeShortString(exchange_name.replace(/0x0+/, '0x')) : ''; const price_decoded = price ? shortString.decodeShortString(price.replace(/0x0+/, '0x')) : ''; const liquidity_raised_decoded = liquidity_raised ? uint256.uint256ToBN({ low: liquidity_raised, high: 0 }).toString() : '0'; diff --git a/apps/mobile/src/components/Filter/index.tsx b/apps/mobile/src/components/Filter/index.tsx index 491c5168..b517e409 100644 --- a/apps/mobile/src/components/Filter/index.tsx +++ b/apps/mobile/src/components/Filter/index.tsx @@ -12,6 +12,7 @@ import { import {useStyles} from '../../hooks'; import stylesheet from './styles'; +import { SORT_OPTION_EVENT_NOSTR } from '../../types/nostr'; interface IFilterMenuProps { visible: boolean; @@ -30,10 +31,17 @@ const NDK_KIND_OPTIONS = [ {label: 'Metadata', value: NDKKind.Metadata}, ]; + +// const SORT_OPTIONS = [ +// {label: 'Time', value: 'time'}, +// {label: 'For You', value: 'forYou'}, +// {label: 'Trending', value: 'trending'}, +// ]; + const SORT_OPTIONS = [ - {label: 'Time', value: 'time'}, - {label: 'For You', value: 'forYou'}, - {label: 'Trending', value: 'trending'}, + {label: 'Time', value: SORT_OPTION_EVENT_NOSTR.TIME}, + {label: 'For You', value: SORT_OPTION_EVENT_NOSTR.FOR_YOU}, + {label: 'Trending', value: SORT_OPTION_EVENT_NOSTR.TRENDING}, ]; const FilterMenu: React.FC = ({ @@ -70,8 +78,8 @@ const FilterMenu: React.FC = ({ {SORT_OPTIONS.map((option) => ( onSortChange(option.value)} + style={[styles.button, activeSortBy === option.value.toString() && styles.activeButton]} + onPress={() => onSortChange(option.value.toString())} > {option.label} diff --git a/apps/mobile/src/components/Filter/styles.ts b/apps/mobile/src/components/Filter/styles.ts index 3537ac69..2faf35e7 100644 --- a/apps/mobile/src/components/Filter/styles.ts +++ b/apps/mobile/src/components/Filter/styles.ts @@ -46,7 +46,7 @@ export default ThemedStyleSheet((theme) => ({ closeButton: { paddingVertical: Spacing.small, paddingHorizontal: Spacing.large, - backgroundColor: theme.colors.primary, + // backgroundColor: theme.colors.primary, borderRadius: 8, marginTop: Spacing.small, }, diff --git a/apps/mobile/src/components/search/index.tsx b/apps/mobile/src/components/search/index.tsx index b4ee7600..b3917127 100644 --- a/apps/mobile/src/components/search/index.tsx +++ b/apps/mobile/src/components/search/index.tsx @@ -13,7 +13,10 @@ interface ISearchComponent { setSearchQuery: (search: string) => void; kinds?: NDKKind[]; setKinds?: (kinds: NDKKind[]) => void; - contactList: string[]; + contactList?: string[]; + setSortBy?: (sort:string) => void; + sortBy?:string; + } const SearchComponent: React.FC = ({ @@ -22,14 +25,17 @@ const SearchComponent: React.FC = ({ kinds = [], setKinds = () => {}, contactList, + sortBy, + setSortBy }) => { const styles = useStyles(stylesheet); const [debouncedQuery, setDebouncedQuery] = useState(searchQuery); const [isOpenFilter, setIsOpenFilter] = useState(false); - const [activeSortBy, setActiveSortBy] = useState(''); + const [activeSortBy, setActiveSortBy] = useState(sortBy ?? "trending"); const handleSortChange = (sortBy: string) => { setActiveSortBy(sortBy); + setSortBy }; useEffect(() => { @@ -46,12 +52,12 @@ const SearchComponent: React.FC = ({ setDebouncedQuery(text); }; - const {data, isLoading, isError} = useSearch({ - search: searchQuery, - kinds, - authors: contactList, - sortBy: activeSortBy, - }); + // const {data, isLoading, isError} = useSearch({ + // search: searchQuery, + // kinds, + // authors: contactList, + // sortBy: activeSortBy, + // }); return ( diff --git a/apps/mobile/src/hooks/launchpad/useSellCoin.ts b/apps/mobile/src/hooks/launchpad/useSellCoin.ts index 52085a12..994d6575 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} from 'starknet'; +import {AccountInterface, CallData, constants, RpcProvider, uint256} from 'starknet'; import {TokenQuoteBuyKeys} from '../../types/keys'; import {formatFloatToUint256} from '../../utils/format'; @@ -20,7 +20,7 @@ export const useSellCoin = () => { contractAddress?: string, ) => { if (!account) return; - const addressContract = 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 +28,7 @@ export const useSellCoin = () => { // account // ); - const amountUint256 = formatFloatToUint256(amount); + let amountUint256 = formatFloatToUint256(amount); // amountUint256 = uint256.bnToUint256(BigInt('0x' + amount)); const sellKeysParams = { @@ -40,7 +40,7 @@ export const useSellCoin = () => { const call = { contractAddress: addressContract, - entrypoint: 'sell_keys', + entrypoint: 'sell_coin', calldata: CallData.compile({ user_address: sellKeysParams.user_address, amount: sellKeysParams.amount, diff --git a/apps/mobile/src/screens/Feed/index.tsx b/apps/mobile/src/screens/Feed/index.tsx index befd2f75..9f24d652 100644 --- a/apps/mobile/src/screens/Feed/index.tsx +++ b/apps/mobile/src/screens/Feed/index.tsx @@ -1,21 +1,22 @@ -import {NDKKind} from '@nostr-dev-kit/ndk'; -import {useAllProfiles, useSearchNotes} from 'afk_nostr_sdk'; -import {useState} from 'react'; -import {FlatList, Image, Pressable, RefreshControl, View} from 'react-native'; +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 {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 [search, setSearch] = useState(undefined); const [kinds, setKinds] = useState([ NDKKind.Text, @@ -25,21 +26,27 @@ export const Feed: React.FC = ({navigation}) => { NDKKind.Metadata, ]); - const notes = useSearchNotes({ + const contacts = useContacts() + console.log("contacts", contacts) + const notes = useSearch({ + // search: search, kinds, + // authors: activeSortBy && contacts?.data?.?? [], + // sortBy: activeSortBy, }); + // Filter profiles based on the search query const profilesSearch = profiles?.data?.pages ?.flat() - .filter((item) => (search && search?.length > 0 ? item?.content?.includes(search) : true)) ?? - []; + // .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)); + .filter((item) => (search && search?.length > 0 ? item?.content?.includes(search) : true)) ?? []; return ( @@ -54,30 +61,38 @@ export const Feed: React.FC = ({navigation}) => { searchQuery={search ?? ''} kinds={kinds} setKinds={setKinds} - contactList={profilesSearch.map((item) => item?.id)} + setSortBy={setSortBy} + sortBy={activeSortBy} + contactList={contacts?.data?.map((item) => item)} /> - profiles.fetchNextPage()} - refreshControl={ - profiles.refetch()} /> - } - ItemSeparatorComponent={() => } - renderItem={({item}) => } - /> + {notes?.isLoading && } + 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.Text) { + } + else if (item.kind === NDKKind.ChannelMessage) { + return ; + } + else if (item.kind === NDKKind.Text) { return ; } return <>; @@ -90,7 +105,7 @@ export const Feed: React.FC = ({navigation}) => { navigation.navigate('MainStack', {screen: 'CreateForm'})} + onPress={() => navigation.navigate('MainStack', { screen: 'CreateForm' })} > diff --git a/apps/mobile/src/types/nostr.ts b/apps/mobile/src/types/nostr.ts new file mode 100644 index 00000000..00fb5eb2 --- /dev/null +++ b/apps/mobile/src/types/nostr.ts @@ -0,0 +1,6 @@ +export enum SORT_OPTION_EVENT_NOSTR { + TIME, + TRENDING, + FOR_YOU + +} \ No newline at end of file diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 00000000..4c49bd78 --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1 @@ +.env diff --git a/backend/postgres/awards.sql b/backend/postgres/awards.sql new file mode 100644 index 00000000..3b0ad688 --- /dev/null +++ b/backend/postgres/awards.sql @@ -0,0 +1,8 @@ +-- TODO: Allow marking claimed +CREATE TABLE AwardWinners ( + address char(64) NOT NULL, + amount int NOT NULL, + type text NOT NULL +); +CREATE INDEX address ON AwardWinners (address); +CREATE INDEX type ON AwardWinners (type); diff --git a/backend/postgres/init.sql b/backend/postgres/init.sql new file mode 100644 index 00000000..4d93d6b5 --- /dev/null +++ b/backend/postgres/init.sql @@ -0,0 +1,301 @@ +-- TODO: unique, ... constraints + +CREATE TABLE Pixels ( + address char(64) NOT NULL, + position integer NOT NULL, + day integer NOT NULL, + color integer NOT NULL, + time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP +); +CREATE INDEX pixels_address_index ON Pixels (address); +CREATE INDEX pixels_position_index ON Pixels (position); +CREATE INDEX pixels_day_index ON Pixels (day); +CREATE INDEX pixels_color_index ON Pixels (color); +CREATE INDEX pixels_time_index ON Pixels (time); + +CREATE TABLE LastPlacedTime ( + address char(64) NOT NULL, + time timestamp NOT NULL, + UNIQUE (address) +); +CREATE INDEX lastPlacedTime_address_index ON LastPlacedTime (address); +CREATE INDEX lastPlacedTime_time_index ON LastPlacedTime (time); + +CREATE TABLE ExtraPixels ( + address char(64) NOT NULL UNIQUE, + available integer NOT NULL, + used integer NOT NULL +); +CREATE INDEX extraPixels_address_index ON ExtraPixels (address); + +CREATE TABLE Users ( + address char(64) NOT NULL, + name text NOT NULL +); +CREATE INDEX user_address_index ON Users (address); + +CREATE TABLE Days ( + -- Postgres auto-incrementing primary key + key integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + day_index integer NOT NULL, + day_start timestamp NOT NULL +); +CREATE INDEX days_day_index_index ON Days (day_index); + +CREATE TABLE DailyQuests ( + day_index integer NOT NULL, + quest_id integer NOT NULL, + name text NOT NULL, + description text NOT NULL, + reward integer NOT NULL, + quest_type text NOT NULL, + PRIMARY KEY (day_index, quest_id) +); +CREATE INDEX dailyQuests_day_index_index ON DailyQuests (day_index); +CREATE INDEX dailyQuests_quest_id_index ON DailyQuests (quest_id); + +CREATE TABLE DailyQuestsInput ( + day_index integer NOT NULL, + quest_id integer NOT NULL, + input_key integer NOT NULL, + input_value integer NOT NULL, + PRIMARY KEY (day_index, quest_id, input_key) +); +CREATE INDEX dailyQuestsInput_day_index_index ON DailyQuestsInput (day_index); +CREATE INDEX dailyQuestsInput_quest_id_index ON DailyQuestsInput (quest_id); +CREATE INDEX dailyQuestsInput_input_key_index ON DailyQuestsInput (input_key); + +CREATE TABLE DailyQuestsClaimParams ( + day_index integer NOT NULL, + quest_id integer NOT NULL, + claim_key integer NOT NULL, + claim_type text NOT NULL, + name text NOT NULL, + example text, + input boolean NOT NULL, + PRIMARY KEY (day_index, quest_id, claim_key) +); +CREATE INDEX dailyQuestsClaimParams_day_index_index ON DailyQuestsClaimParams (day_index); +CREATE INDEX dailyQuestsClaimParams_quest_id_index ON DailyQuestsClaimParams (quest_id); +CREATE INDEX dailyQuestsClaimParams_claim_key_index ON DailyQuestsClaimParams (claim_key); + +-- Table for storing the daily quests that the user has completed +CREATE TABLE UserDailyQuests ( + -- Postgres auto-incrementing primary key + key integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + user_address char(64) NOT NULL, + day_index integer NOT NULL, + quest_id integer NOT NULL, + completed boolean NOT NULL, + completed_at timestamp DEFAULT CURRENT_TIMESTAMP, + UNIQUE (user_address, day_index, quest_id) +); +CREATE INDEX userDailyQuests_user_address_index ON UserDailyQuests (user_address); +CREATE INDEX userDailyQuests_quest_id_index ON UserDailyQuests (quest_id); + +CREATE TABLE MainQuests ( + -- Postgres auto-incrementing primary key + key integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + name text NOT NULL, + description text NOT NULL, + reward integer NOT NULL, + quest_type text NOT NULL +); + +CREATE TABLE MainQuestsInput ( + quest_id integer NOT NULL, + input_key integer NOT NULL, + input_value integer NOT NULL, + PRIMARY KEY (quest_id, input_key) +); +CREATE INDEX mainQuestsInput_quest_id_index ON MainQuestsInput (quest_id); +CREATE INDEX mainQuestsInput_input_key_index ON MainQuestsInput (input_key); + +CREATE TABLE MainQuestsClaimParams ( + quest_id integer NOT NULL, + claim_key integer NOT NULL, + claim_type text NOT NULL, + name text NOT NULL, + example text, + input boolean NOT NULL, + PRIMARY KEY (quest_id, claim_key) +); +CREATE INDEX mainQuestsClaimParams_quest_id_index ON MainQuestsClaimParams (quest_id); +CREATE INDEX mainQuestsClaimParams_claim_key_index ON MainQuestsClaimParams (claim_key); + +-- Table for storing the main quests that the user has completed +CREATE TABLE UserMainQuests ( + -- Postgres auto-incrementing primary key + key integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + user_address char(64) NOT NULL, + quest_id integer NOT NULL, + completed boolean NOT NULL, + completed_at timestamp +); +CREATE INDEX userMainQuests_user_address_index ON UserMainQuests (user_address); +CREATE INDEX userMainQuests_quest_id_index ON UserMainQuests (quest_id); + +-- TODO: key to color_idx +CREATE TABLE Colors ( + -- Postgres auto-incrementing primary key + key int PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + color_key integer NOT NULL, + hex text NOT NULL +); +CREATE INDEX colors_color_key_index ON Colors (color_key); + +-- TODO: Add day_index +CREATE TABLE VotableColors ( + -- Postgres auto-incrementing primary key + key int PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + day_index integer NOT NULL, + color_key integer NOT NULL, + hex text NOT NULL, + UNIQUE (day_index, color_key) +); +CREATE INDEX votableColors_day_index_index ON VotableColors (day_index); +CREATE INDEX votableColors_color_key_index ON VotableColors (color_key); + +CREATE TABLE ColorVotes ( + -- Postgres auto-incrementing primary key + key int PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + user_address char(64) NOT NULL, + day_index integer NOT NULL, + color_key integer NOT NULL, + UNIQUE (user_address, day_index) +); +CREATE INDEX colorVotes_user_address_index ON ColorVotes (user_address); +CREATE INDEX colorVotes_day_index ON ColorVotes (day_index); +CREATE INDEX colorVotes_color_key_index ON ColorVotes (color_key); + +CREATE TABLE TemplateData ( + key int PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + hash text NOT NULL, + data bytea NOT NULL +); + +-- TODO: key -> template_id? +CREATE TABLE Templates ( + key integer NOT NULL PRIMARY KEY, + name text NOT NULL, + hash text NOT NULL, + width integer NOT NULL, + height integer NOT NULL, + position integer NOT NULL, + reward integer NOT NULL, + reward_token char(64) NOT NULL +); + +CREATE TABLE NFTs ( + token_id integer NOT NULL PRIMARY KEY, + position integer NOT NULL, + width integer NOT NULL, + height integer NOT NULL, + name text NOT NULL, + image_hash text NOT NULL, + block_number integer NOT NULL, + day_index integer NOT NULL, + minter char(64) NOT NULL, + owner char(64) NOT NULL +); + +CREATE TABLE NFTLikes ( + key int PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + nftKey integer NOT NULL, + liker char(64) NOT NULL, + UNIQUE (nftKey, liker) +); +CREATE INDEX nftLikes_nft_key_index ON NFTLikes (nftKey); +CREATE INDEX nftLikes_liker_index ON NFTLikes (liker); + +CREATE TABLE Factions ( + faction_id integer NOT NULL PRIMARY KEY, + name text NOT NULL, + leader char(64) NOT NULL, + joinable boolean NOT NULL, + allocation integer NOT NULL +); +CREATE INDEX factions_leader_index ON Factions (leader); +CREATE INDEX factions_joinable_index ON Factions (joinable); + +CREATE TABLE ChainFactions ( + faction_id integer NOT NULL PRIMARY KEY, + name text NOT NULL +); + +CREATE TABLE FactionLinks ( + faction_id integer NOT NULL, + icon text NOT NULL, + telegram text, + twitter text, + github text, + site text, + PRIMARY KEY (faction_id) +); +CREATE INDEX factionLinks_faction_id_index ON FactionLinks (faction_id); + +CREATE TABLE ChainFactionLinks ( + faction_id integer NOT NULL, + icon text NOT NULL, + telegram text, + twitter text, + github text, + site text, + PRIMARY KEY (faction_id) +); +CREATE INDEX chainFactionLinks_faction_id_index ON ChainFactionLinks (faction_id); + +CREATE TABLE FactionMembersInfo ( + faction_id integer NOT NULL, + user_address char(64) NOT NULL, + last_placed_time timestamp NOT NULL, + member_pixels integer NOT NULL, + UNIQUE (faction_id, user_address) +); +CREATE INDEX factionMembersInfo_faction_id_index ON FactionMembersInfo (faction_id); +CREATE INDEX factionMembersInfo_user_address_index ON FactionMembersInfo (user_address); + +CREATE TABLE ChainFactionMembersInfo ( + faction_id integer NOT NULL, + user_address char(64) NOT NULL, + last_placed_time timestamp NOT NULL, + member_pixels integer NOT NULL, + UNIQUE (faction_id, user_address) +); +CREATE INDEX chainFactionMembersInfo_faction_id_index ON ChainFactionMembersInfo (faction_id); +CREATE INDEX chainFactionMembersInfo_user_address_index ON ChainFactionMembersInfo (user_address); + +CREATE TABLE FactionTemplates ( + template_id integer NOT NULL, + faction_id integer NOT NULL, + hash text NOT NULL, + position integer NOT NULL, + width integer NOT NULL, + height integer NOT NULL, + stale boolean NOT NULL +); +CREATE INDEX factionTemplates_template_id_index ON FactionTemplates (template_id); +CREATE INDEX factionTemplates_faction_id_index ON FactionTemplates (faction_id); +CREATE INDEX factionTemplates_stale_index ON FactionTemplates (stale); + +CREATE TABLE ChainFactionTemplates ( + template_id integer NOT NULL, + faction_id integer NOT NULL, + hash text NOT NULL, + position integer NOT NULL, + width integer NOT NULL, + height integer NOT NULL, + stale boolean NOT NULL +); +CREATE INDEX chainFactionTemplates_template_id_index ON ChainFactionTemplates (template_id); +CREATE INDEX chainFactionTemplates_faction_id_index ON ChainFactionTemplates (faction_id); +CREATE INDEX chainFactionTemplates_stale_index ON ChainFactionTemplates (stale); + +-- TODO: allow marking claimed +CREATE TABLE AwardWinners ( + address char(64) NOT NULL, + amount int NOT NULL, + type text NOT NULL +); +CREATE INDEX address ON AwardWinners (address); +CREATE INDEX type ON AwardWinners (type); diff --git a/onchain/Makefile b/onchain/Makefile index fd676b82..ac1e2d0c 100644 --- a/onchain/Makefile +++ b/onchain/Makefile @@ -1,5 +1,5 @@ RPC_PATH := lib/kakarot-rpc -CAIRO_CONTRACTS_PATH := cairo_contracts +CAIRO_CONTRACTS_PATH := cairo SOL_CONTRACTS_PATH := solidity_contracts LOCAL_ENV_PATH := .env MAKE := make @@ -12,7 +12,7 @@ start: $(MAKE) -C $(RPC_PATH) local-rpc-up deploy-l1: copy-env - yarn hardhat run scripts/deploy.ts --network l1Rpc + pnpm hardhat run scripts/deploy.ts --network l1Rpc copy-env: @echo "Updating .env file with keys from Kakarot RPC container..." @@ -68,4 +68,4 @@ whitelist-contract: copy-env test: copy-env build @echo "Running tests..." - yarn hardhat test + pnpm hardhat test diff --git a/onchain/README.md b/onchain/README.md index af159b54..3a52559d 100644 --- a/onchain/README.md +++ b/onchain/README.md @@ -84,10 +84,10 @@ As Kakarot is an EVM-L2 using the Starknet Stack, you can natively interact with ### Deploying a Cairo Contract -Once scarb is installed in version `2.5.4`, `cd` into the `cairo_contracts` directory and build the `Counter` cairo contract: +Once scarb is installed in version `2.6.5`, `cd` into the `cairo` directory and build the `Counter` cairo contract: ``` -cd cairo_contracts && scarb build && ../ +cd cairo && scarb build && ../ ``` Once built, you can deploy the contract using the `starkli`. First, set an account up (using the default Katana private key, no password): @@ -96,7 +96,7 @@ Once built, you can deploy the contract using the `starkli`. First, set an accou export STARKNET_KEYSTORE="katana.key.json" export STARKNET_ACCOUNT="katana.account.json" export STARKNET_RPC="http://127.0.0.1:5050" -starkli declare cairo_contracts/target/dev/cairo_contracts_Counter.contract_class.json +starkli declare cairo/target/dev/afk_Counter.contract_class.json ``` This will output the contract's class hash. You can use this hash to deploy the contract: @@ -150,7 +150,7 @@ The `DualVMToken` contract demonstrates how one can deploy a token that is able Let's deploy the `DualVMToken` Cairo contract: ```sh -starkli declare cairo_contracts/target/dev/cairo_contracts_DualVMToken.contract_class.json +starkli declare cairo/target/dev/afk_DualVMToken.contract_class.json starkli deploy 0x007cadcf5c04b02dae809a2700b85ff87aca8a3117e67e9aec24c5513730b1c1 100 0 0xb3ff441a68610b30fd5e2abbf3a1548eb6ba6f3559f2862bf2dc757e5828ca --salt 1 ``` diff --git a/onchain/cairo/.snfoundry_cache/.prev_tests_failed b/onchain/cairo/.snfoundry_cache/.prev_tests_failed index 77ce435e..70563d04 100644 --- a/onchain/cairo/.snfoundry_cache/.prev_tests_failed +++ b/onchain/cairo/.snfoundry_cache/.prev_tests_failed @@ -1,4 +1 @@ afk::tests::launchpad_tests::launchpad_tests::launchpad_integration -afk::tests::launchpad_tests::launchpad_tests::launchpad_buy_and_sell -afk::tests::launchpad_tests::launchpad_tests::launchpad_buy_more_then_liquidity_threshold -afk::tests::launchpad_tests::launchpad_tests::launchpad_buy_all_few_steps diff --git a/onchain/cairo/Scarb.toml b/onchain/cairo/Scarb.toml index 6bf8f5f6..a1f03a62 100644 --- a/onchain/cairo/Scarb.toml +++ b/onchain/cairo/Scarb.toml @@ -6,7 +6,7 @@ edition = "2023_11" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html [dependencies] -starknet = ">=2.6.3" +starknet = ">=2.6.4" openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag="v0.13.0" } [dev-dependencies] diff --git a/onchain/cairo/src/launchpad/launchpad.cairo b/onchain/cairo/src/launchpad/launchpad.cairo index 2f2f06ff..abb43d82 100644 --- a/onchain/cairo/src/launchpad/launchpad.cairo +++ b/onchain/cairo/src/launchpad/launchpad.cairo @@ -1,8 +1,9 @@ use afk::types::jediswap_types::{MintParams}; use afk::types::launchpad_types::{ MINTER_ROLE, ADMIN_ROLE, StoredName, BuyToken, SellToken, CreateToken, LaunchUpdated, - TokenQuoteBuyKeys, TokenLaunch, SharesKeys, BondingType, Token, CreateLaunch, - SetJediwapNFTRouterV2, SetJediwapV2Factory, SupportedExchanges, LiquidityCreated + TokenQuoteBuyCoin, TokenLaunch, SharesTokenUser, BondingType, Token, CreateLaunch, + SetJediwapNFTRouterV2, SetJediwapV2Factory, SupportedExchanges, LiquidityCreated, + LiquidityCanBeAdded }; use starknet::ClassHash; use starknet::ContractAddress; @@ -27,6 +28,7 @@ pub trait ILaunchpadMarketplace { contract_address_salt: felt252, ) -> ContractAddress; fn launch_token(ref self: TContractState, coin_address: ContractAddress); + fn launch_liquidity(ref self: TContractState, coin_address: ContractAddress); // fn buy_coin(ref self: TContractState, coin_address: ContractAddress, amount: u256); fn buy_coin_by_quote_amount( ref self: TContractState, coin_address: ContractAddress, quote_amount: u256 @@ -37,7 +39,7 @@ pub trait ILaunchpadMarketplace { // Views fn get_threshold_liquidity(self: @TContractState) -> u256; - fn get_default_token(self: @TContractState,) -> TokenQuoteBuyKeys; + fn get_default_token(self: @TContractState,) -> TokenQuoteBuyCoin; // Main function to calculate amount fn get_amount_by_type_of_coin_or_quote( @@ -58,13 +60,13 @@ pub trait ILaunchpadMarketplace { fn get_coin_launch(self: @TContractState, key_user: ContractAddress,) -> TokenLaunch; fn get_share_key_of_user( self: @TContractState, owner: ContractAddress, key_user: ContractAddress, - ) -> SharesKeys; + ) -> SharesTokenUser; fn get_all_launch(self: @TContractState) -> Span; fn get_all_coins(self: @TContractState) -> Span; // Admins - fn set_token(ref self: TContractState, token_quote: TokenQuoteBuyKeys); + fn set_token(ref self: TContractState, token_quote: TokenQuoteBuyCoin); fn set_protocol_fee_percent(ref self: TContractState, protocol_fee_percent: u256); fn set_creator_fee_percent(ref self: TContractState, creator_fee_percent: u256); fn set_dollar_paid_coin_creation(ref self: TContractState, dollar_price: u256); @@ -103,9 +105,10 @@ mod LaunchpadMarketplace { contract_address_const, get_block_timestamp, get_contract_address, ClassHash }; use super::{ - StoredName, BuyToken, SellToken, CreateToken, LaunchUpdated, SharesKeys, MINTER_ROLE, - ADMIN_ROLE, BondingType, Token, TokenLaunch, TokenQuoteBuyKeys, CreateLaunch, - SetJediwapNFTRouterV2, SetJediwapV2Factory, SupportedExchanges, MintParams, LiquidityCreated + StoredName, BuyToken, SellToken, CreateToken, LaunchUpdated, SharesTokenUser, MINTER_ROLE, + ADMIN_ROLE, BondingType, Token, TokenLaunch, TokenQuoteBuyCoin, CreateLaunch, + SetJediwapNFTRouterV2, SetJediwapV2Factory, SupportedExchanges, MintParams, LiquidityCreated, + LiquidityCanBeAdded }; const MAX_SUPPLY: u256 = 100_000_000; @@ -153,15 +156,15 @@ mod LaunchpadMarketplace { token_created: LegacyMap::, launched_coins: LegacyMap::, pumped_coins: LegacyMap::, - shares_by_users: LegacyMap::<(ContractAddress, ContractAddress), SharesKeys>, + shares_by_users: LegacyMap::<(ContractAddress, ContractAddress), SharesTokenUser>, bonding_type: LegacyMap::, array_launched_coins: LegacyMap::, array_coins: LegacyMap::, tokens_created: LegacyMap::, launch_created: LegacyMap::, // Parameters - is_tokens_buy_enable: LegacyMap::, - default_token: TokenQuoteBuyKeys, + is_tokens_buy_enable: LegacyMap::, + default_token: TokenQuoteBuyCoin, dollar_price_launch_pool: u256, dollar_price_create_token: u256, dollar_price_percentage: u256, @@ -198,6 +201,7 @@ mod LaunchpadMarketplace { SetJediwapV2Factory: SetJediwapV2Factory, SetJediwapNFTRouterV2: SetJediwapNFTRouterV2, LiquidityCreated: LiquidityCreated, + LiquidityCanBeAdded:LiquidityCanBeAdded, #[flat] AccessControlEvent: AccessControlComponent::Event, #[flat] @@ -221,7 +225,7 @@ mod LaunchpadMarketplace { self.accesscontrol._grant_role(MINTER_ROLE, admin); self.accesscontrol._grant_role(ADMIN_ROLE, admin); - let init_token = TokenQuoteBuyKeys { + let init_token = TokenQuoteBuyCoin { token_address: token_address, initial_key_price, price: initial_key_price, @@ -249,7 +253,7 @@ mod LaunchpadMarketplace { impl LaunchpadMarketplace of super::ILaunchpadMarketplace { // ADMIN - fn set_token(ref self: ContractState, token_quote: TokenQuoteBuyKeys) { + fn set_token(ref self: ContractState, token_quote: TokenQuoteBuyCoin) { self.accesscontrol.assert_only_role(ADMIN_ROLE); self.is_tokens_buy_enable.write(token_quote.token_address, token_quote); } @@ -392,6 +396,19 @@ mod LaunchpadMarketplace { self._launch_token(coin_address, caller); } + // Launch liquidity if threshold ok + 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); + + } + + // Buy coin by quote amount // Get amount of coin receive based on token IN fn buy_coin_by_quote_amount( @@ -429,14 +446,20 @@ mod LaunchpadMarketplace { // Pay with quote token // Transfer quote & coin // TOdo fix issue price + + // In case the user want to buy more than the threshold + // Give the available supply if total_price + old_launch.liquidity_raised.clone() > threshold_liquidity { total_price = threshold_liquidity - old_launch.liquidity_raised.clone(); - // println!("total price {:?}", total_price); - // println!("total_price {:?}", total_price); + // amount = total_price; + // amount = total_price; + // amount = self + // ._get_amount_by_type_of_coin_or_quote(coin_address, total_price, false, true); amount = pool_coin.available_supply; amount_protocol_fee = total_price * protocol_fee_percent / BPS; - remain_liquidity = total_price - amount_protocol_fee; + // remain_liquidity = total_price - amount_protocol_fee; + remain_liquidity = total_price; erc20 .transfer_from( get_caller_address(), @@ -465,10 +488,19 @@ mod LaunchpadMarketplace { // let mut amount = self // ._get_amount_by_type_of_coin_or_quote(coin_address, total_price, false, true); - if total_price != 0 { - amount = self - ._get_amount_by_type_of_coin_or_quote(coin_address, total_price, false, true); - } + // if total_price != 0 { + // amount = self + // ._get_amount_by_type_of_coin_or_quote(coin_address, total_price, false, true); + // } + + // if amount == 0 { + // amount = self + // ._get_amount_by_type_of_coin_or_quote(coin_address, total_price, false, true); + // } + + // if amount > pool_coin.available_supply { + // amount = pool_coin.available_supply; + // } // let mut amount = self // ._get_coin_amount_by_quote_amount(coin_address, total_price, false); // println!("quote_amount {:?}", quote_amount); @@ -482,9 +514,9 @@ mod LaunchpadMarketplace { let mut share_user = old_share.clone(); if old_share.owner.is_zero() { share_user = - SharesKeys { + SharesTokenUser { owner: get_caller_address(), - key_address: coin_address, + token_address: coin_address, amount_owned: amount, amount_buy: amount, amount_sell: 0, @@ -542,14 +574,33 @@ mod LaunchpadMarketplace { // TOTAL_SUPPLY / 5 // 20% go the liquidity // 80% bought by others + + // TODO finish test and fix if pool_coin.liquidity_raised >= threshold { - // println!("mc threshold reached"); - self._add_liquidity(coin_address, SupportedExchanges::Jediswap); + + 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); } if mc >= threshold_mc { // println!("mc >= threshold_mc"); - self._add_liquidity(coin_address, SupportedExchanges::Jediswap); + 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); } // TODO check reetrancy guard @@ -677,7 +728,7 @@ mod LaunchpadMarketplace { fn claim_coin_buy(ref self: ContractState, coin_address: ContractAddress, amount: u256) {} - fn get_default_token(self: @ContractState) -> TokenQuoteBuyKeys { + fn get_default_token(self: @ContractState) -> TokenQuoteBuyCoin { self.default_token.read() } @@ -692,7 +743,7 @@ mod LaunchpadMarketplace { fn get_share_key_of_user( self: @ContractState, owner: ContractAddress, key_user: ContractAddress, - ) -> SharesKeys { + ) -> SharesTokenUser { self.shares_by_users.read((owner, key_user)) } @@ -845,7 +896,7 @@ mod LaunchpadMarketplace { let liquidity_supply = total_supply / LIQUIDITY_RATIO; let supply_distribution = total_supply - liquidity_supply; - let (slope, _) = self._calculate_pricing(total_supply - liquidity_supply); + let (slope, init_price) = self._calculate_pricing(total_supply - liquidity_supply); // let (slope, ini_price) = self._calculate_pricing(total_supply - liquidity_supply); // println!("slope key price {:?}",slope); // println!("ini_price key price {:?}",ini_price); @@ -868,13 +919,14 @@ mod LaunchpadMarketplace { token_quote: token_to_use.clone(), initial_key_price: initial_key_price.clone(), // initial_key_price: token_to_use.initial_key_price, - price: 0, - liquidity_raised: 0, - token_holded: 0, + price: 0_u256, + // price:init_price, + liquidity_raised: 0_u256, + token_holded: 0_u256, is_liquidity_launch: false, slope: slope, - threshold_liquidity: threshold - // token_holded:1 + threshold_liquidity: threshold, + initial_pool_supply: liquidity_supply, }; // Send supply need to launch your coin let amount_needed = total_supply.clone(); @@ -1070,10 +1122,22 @@ mod LaunchpadMarketplace { let k_max = total_supply * threshold_liquidity; if is_decreased == true { - 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)); + 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; + // let pool_qty = self.threshold_liquidity.read().clone(); + let pool_qty = pool_coin.threshold_liquidity.clone(); + // 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; diff --git a/onchain/cairo/src/social/account.cairo b/onchain/cairo/src/social/account.cairo index e68e6e55..3009bf69 100644 --- a/onchain/cairo/src/social/account.cairo +++ b/onchain/cairo/src/social/account.cairo @@ -153,290 +153,290 @@ pub mod SocialAccount { } } -#[cfg(test)] -mod tests { - use afk::tokens::erc20::{ERC20, IERC20Dispatcher, IERC20DispatcherTrait}; - use core::array::SpanTrait; - use core::traits::Into; - use snforge_std::{ - declare, ContractClass, ContractClassTrait, spy_events, SpyOn, EventSpy, EventFetcher, - Event, EventAssertions, cheat_transaction_hash_global, cheat_signature_global, - stop_cheat_transaction_hash_global, stop_cheat_signature_global - }; - use starknet::{ - ContractAddress, get_caller_address, get_contract_address, contract_address_const - }; - use super::super::profile::NostrProfile; - - use super::super::request::{SocialRequest, Signature, Encode}; - use super::super::transfer::Transfer; - use super::{ - ISocialAccountDispatcher, ISocialAccountDispatcherTrait, ISocialAccountSafeDispatcher, - ISocialAccountSafeDispatcherTrait - }; - - use super::{ISRC6Dispatcher, ISRC6DispatcherTrait}; - - fn declare_account() -> ContractClass { - declare("SocialAccount").unwrap() - } - - fn declare_erc20() -> ContractClass { - declare("ERC20").unwrap() - } - - fn deploy_account(class: ContractClass, public_key: u256) -> ISocialAccountDispatcher { - let mut calldata = array![]; - public_key.serialize(ref calldata); - - let address = class.precalculate_address(@calldata); - - let mut spy = spy_events(SpyOn::One(address)); - - let (contract_address, _) = class.deploy(@calldata).unwrap(); - - spy.fetch_events(); - - assert(spy.events.len() == 1, 'there should be one event'); - - // TODO: deserialize event instead of manual decoding - let (_, event) = spy.events.at(0); - assert(event.keys.at(0) == @selector!("AccountCreated"), 'wrong event name'); - - let event_key = u256 { - low: (*event.keys.at(1)).try_into().unwrap(), - high: (*event.keys.at(2)).try_into().unwrap() - }; - - assert(event_key == public_key, 'wrong public key'); - - ISocialAccountDispatcher { contract_address } - } - - fn deploy_erc20( - class: ContractClass, - name: felt252, - symbol: felt252, - initial_supply: u256, - recipient: ContractAddress - ) -> IERC20Dispatcher { - let mut calldata = array![]; - - name.serialize(ref calldata); - symbol.serialize(ref calldata); - (2 * initial_supply).serialize(ref calldata); - recipient.serialize(ref calldata); - 18_u8.serialize(ref calldata); - - let (contract_address, _) = class.deploy(@calldata).unwrap(); - - IERC20Dispatcher { contract_address } - } - - fn request_fixture_custom_classes( - erc20_class: ContractClass, account_class: ContractClass - ) -> ( - SocialRequest, - ISocialAccountDispatcher, - ISocialAccountDispatcher, - IERC20Dispatcher - ) { - // sender private key: 70aca2a9ab722bd56a9a1aadae7f39bc747c7d6735a04d677e0bc5dbefa71d47 - // just for testing, do not use for anything else - let sender_public_key = - 0xd6f1cf53f9f52d876505164103b1e25811ec4226a17c7449576ea48b00578171_u256; - - let sender = deploy_account(account_class, sender_public_key); - - // recipient private key: 59a772c0e643e4e2be5b8bac31b2ab5c5582b03a84444c81d6e2eec34a5e6c35 - // just for testing, do not use for anything else - let recipient_public_key = - 0x5b2b830f2778075ab3befb5a48c9d8138aef017fab2b26b5c31a2742a901afcc_u256; - let recipient = deploy_account(account_class, recipient_public_key); - - let joyboy_public_key = 0x84603b4e300840036ca8cc812befcc8e240c09b73812639d5cdd8ece7d6eba40; - - let erc20 = deploy_erc20(erc20_class, 'USDC token', 'USDC', 100, sender.contract_address); - - let transfer = Transfer { - amount: 1, - token: erc20.symbol(), - token_address: erc20.contract_address, - joyboy: NostrProfile { - public_key: joyboy_public_key, relays: array!["wss://relay.joyboy.community.com"] - }, - recipient: NostrProfile { public_key: recipient_public_key, relays: array![] }, - recipient_address: recipient.contract_address - }; - - // for test data see: https://replit.com/@maciejka/WanIndolentKilobyte-2 - - let request = SocialRequest { - public_key: sender_public_key, - created_at: 1716285235_u64, - kind: 1_u16, - tags: "[]", - content: transfer, - sig: Signature { - r: 0x3570a9a0c92c180bd4ac826c887e63844b043e3b65da71a857d2aa29e7cd3a4e_u256, - s: 0x1c0c0a8b7a8330b6b8915985c9cd498a407587213c2e7608e7479b4ef966605f_u256, - } - }; - - (request, sender, recipient, erc20) - } - - fn request_fixture() -> ( - SocialRequest, - ISocialAccountDispatcher, - ISocialAccountDispatcher, - IERC20Dispatcher - ) { - let erc20_class = declare_erc20(); - let account_class = declare_account(); - request_fixture_custom_classes(erc20_class, account_class) - } +// #[cfg(test)] +// mod tests { +// use afk::tokens::erc20::{ERC20, IERC20Dispatcher, IERC20DispatcherTrait}; +// use core::array::SpanTrait; +// use core::traits::Into; +// use snforge_std::{ +// declare, ContractClass, ContractClassTrait, spy_events, SpyOn, EventSpy, EventFetcher, +// Event, EventAssertions, cheat_transaction_hash_global, cheat_signature_global, +// stop_cheat_transaction_hash_global, stop_cheat_signature_global +// }; +// use starknet::{ +// ContractAddress, get_caller_address, get_contract_address, contract_address_const +// }; +// use super::super::profile::NostrProfile; + +// use super::super::request::{SocialRequest, Signature, Encode}; +// use super::super::transfer::Transfer; +// use super::{ +// ISocialAccountDispatcher, ISocialAccountDispatcherTrait, ISocialAccountSafeDispatcher, +// ISocialAccountSafeDispatcherTrait +// }; + +// use super::{ISRC6Dispatcher, ISRC6DispatcherTrait}; + +// fn declare_account() -> ContractClass { +// declare("SocialAccount").unwrap() +// } + +// fn declare_erc20() -> ContractClass { +// declare("ERC20").unwrap() +// } + +// fn deploy_account(class: ContractClass, public_key: u256) -> ISocialAccountDispatcher { +// let mut calldata = array![]; +// public_key.serialize(ref calldata); + +// let address = class.precalculate_address(@calldata); + +// let mut spy = spy_events(SpyOn::One(address)); + +// let (contract_address, _) = class.deploy(@calldata).unwrap(); + +// spy.fetch_events(); + +// assert(spy.events.len() == 1, 'there should be one event'); + +// // TODO: deserialize event instead of manual decoding +// let (_, event) = spy.events.at(0); +// assert(event.keys.at(0) == @selector!("AccountCreated"), 'wrong event name'); + +// let event_key = u256 { +// low: (*event.keys.at(1)).try_into().unwrap(), +// high: (*event.keys.at(2)).try_into().unwrap() +// }; + +// assert(event_key == public_key, 'wrong public key'); + +// ISocialAccountDispatcher { contract_address } +// } + +// fn deploy_erc20( +// class: ContractClass, +// name: felt252, +// symbol: felt252, +// initial_supply: u256, +// recipient: ContractAddress +// ) -> IERC20Dispatcher { +// let mut calldata = array![]; + +// name.serialize(ref calldata); +// symbol.serialize(ref calldata); +// (2 * initial_supply).serialize(ref calldata); +// recipient.serialize(ref calldata); +// 18_u8.serialize(ref calldata); + +// let (contract_address, _) = class.deploy(@calldata).unwrap(); + +// IERC20Dispatcher { contract_address } +// } + +// fn request_fixture_custom_classes( +// erc20_class: ContractClass, account_class: ContractClass +// ) -> ( +// SocialRequest, +// ISocialAccountDispatcher, +// ISocialAccountDispatcher, +// IERC20Dispatcher +// ) { +// // sender private key: 70aca2a9ab722bd56a9a1aadae7f39bc747c7d6735a04d677e0bc5dbefa71d47 +// // just for testing, do not use for anything else +// let sender_public_key = +// 0xd6f1cf53f9f52d876505164103b1e25811ec4226a17c7449576ea48b00578171_u256; + +// let sender = deploy_account(account_class, sender_public_key); + +// // recipient private key: 59a772c0e643e4e2be5b8bac31b2ab5c5582b03a84444c81d6e2eec34a5e6c35 +// // just for testing, do not use for anything else +// let recipient_public_key = +// 0x5b2b830f2778075ab3befb5a48c9d8138aef017fab2b26b5c31a2742a901afcc_u256; +// let recipient = deploy_account(account_class, recipient_public_key); + +// let joyboy_public_key = 0x84603b4e300840036ca8cc812befcc8e240c09b73812639d5cdd8ece7d6eba40; + +// let erc20 = deploy_erc20(erc20_class, 'USDC token', 'USDC', 100, sender.contract_address); + +// let transfer = Transfer { +// amount: 1, +// token: erc20.symbol(), +// token_address: erc20.contract_address, +// joyboy: NostrProfile { +// public_key: joyboy_public_key, relays: array!["wss://relay.joyboy.community.com"] +// }, +// recipient: NostrProfile { public_key: recipient_public_key, relays: array![] }, +// recipient_address: recipient.contract_address +// }; + +// // for test data see: https://replit.com/@maciejka/WanIndolentKilobyte-2 + +// let request = SocialRequest { +// public_key: sender_public_key, +// created_at: 1716285235_u64, +// kind: 1_u16, +// tags: "[]", +// content: transfer, +// sig: Signature { +// r: 0x3570a9a0c92c180bd4ac826c887e63844b043e3b65da71a857d2aa29e7cd3a4e_u256, +// s: 0x1c0c0a8b7a8330b6b8915985c9cd498a407587213c2e7608e7479b4ef966605f_u256, +// } +// }; + +// (request, sender, recipient, erc20) +// } + +// fn request_fixture() -> ( +// SocialRequest, +// ISocialAccountDispatcher, +// ISocialAccountDispatcher, +// IERC20Dispatcher +// ) { +// let erc20_class = declare_erc20(); +// let account_class = declare_account(); +// request_fixture_custom_classes(erc20_class, account_class) +// } + +// #[test] +// fn get_public_key() { +// let public_key: u256 = 45; +// let account = deploy_account(declare_account(), public_key); +// assert!(account.get_public_key() == public_key, "wrong public_key"); +// } + +// #[test] +// fn successful_transfer() { +// let (request, sender, _, _) = request_fixture(); +// sender.handle_transfer(request); +// } + +// #[test] +// #[should_panic(expected: "can't verify signature")] +// fn incorrect_signature() { +// let (request, sender, _, _) = request_fixture(); + +// let request = SocialRequest { +// sig: Signature { +// r: 0x2570a9a0c92c180bd4ac826c887e63844b043e3b65da71a857d2aa29e7cd3a4e_u256, +// s: 0x1c0c0a8b7a8330b6b8915985c9cd498a407587213c2e7608e7479b4ef966605f_u256, +// }, +// ..request, +// }; + +// sender.handle_transfer(request); +// } + +// #[test] +// #[should_panic(expected: "wrong sender")] +// fn wrong_sender() { +// let (request, sender, _, _) = request_fixture(); + +// let request = SocialRequest { public_key: 123_u256, ..request, }; + +// sender.handle_transfer(request); +// } + +// #[test] +// #[should_panic(expected: "wrong recipient")] +// fn wrong_recipient() { +// let (request, sender, _, _) = request_fixture(); + +// // let content = request.content.clone(); + +// let request = SocialRequest { +// content: Transfer { +// recipient_address: sender.contract_address, ..request.content.clone() +// }, +// ..request, +// }; + +// sender.handle_transfer(request); +// } + +// #[test] +// #[should_panic(expected: "wrong token")] +// fn wrong_token() { +// let erc20_class = declare_erc20(); +// let account_class = declare_account(); + +// let dai = deploy_erc20(erc20_class, 'DAI token', 'DAI', 100, 21.try_into().unwrap()); + +// let (request, sender, _, _) = request_fixture_custom_classes(erc20_class, account_class); + +// let request = SocialRequest { +// content: Transfer { token_address: dai.contract_address, ..request.content.clone() }, +// ..request, +// }; - #[test] - fn get_public_key() { - let public_key: u256 = 45; - let account = deploy_account(declare_account(), public_key); - assert!(account.get_public_key() == public_key, "wrong public_key"); - } +// sender.handle_transfer(request); +// } - #[test] - fn successful_transfer() { - let (request, sender, _, _) = request_fixture(); - sender.handle_transfer(request); - } +// #[test] +// #[should_panic(expected: "double spend")] +// fn double_transfer() { +// let erc20_class = declare_erc20(); +// let account_class = declare_account(); +// let (request, sender, _, _) = request_fixture_custom_classes(erc20_class, account_class); +// let (request2, _, _, _) = request_fixture_custom_classes(erc20_class, account_class); - #[test] - #[should_panic(expected: "can't verify signature")] - fn incorrect_signature() { - let (request, sender, _, _) = request_fixture(); +// sender.handle_transfer(request); +// sender.handle_transfer(request2); +// } - let request = SocialRequest { - sig: Signature { - r: 0x2570a9a0c92c180bd4ac826c887e63844b043e3b65da71a857d2aa29e7cd3a4e_u256, - s: 0x1c0c0a8b7a8330b6b8915985c9cd498a407587213c2e7608e7479b4ef966605f_u256, - }, - ..request, - }; +// #[test] +// fn is_valid_signature() { +// let public_key = 0xdff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659; - sender.handle_transfer(request); - } +// let account_class = declare_account(); +// let account = deploy_account(account_class, public_key); - #[test] - #[should_panic(expected: "wrong sender")] - fn wrong_sender() { - let (request, sender, _, _) = request_fixture(); +// let account = ISRC6Dispatcher { contract_address: account.contract_address }; - let request = SocialRequest { public_key: 123_u256, ..request, }; +// let hash = 0x6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89; - sender.handle_transfer(request); - } +// let r: u256 = 0x49ae3fa614e2877877a90987726f1b48387bef1f66de78e5075659040cbbf612; +// let s: u256 = 0x11259ae25e0743ac7490df3fef875ea291c7b99cf2295e44aabd677107b9c53a; - #[test] - #[should_panic(expected: "wrong recipient")] - fn wrong_recipient() { - let (request, sender, _, _) = request_fixture(); +// let mut signature = Default::default(); +// r.serialize(ref signature); +// s.serialize(ref signature); - // let content = request.content.clone(); +// assert!(account.is_valid_signature(hash, signature.clone()) == starknet::VALIDATED); - let request = SocialRequest { - content: Transfer { - recipient_address: sender.contract_address, ..request.content.clone() - }, - ..request, - }; +// let invalid_hash = 0x5a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89; - sender.handle_transfer(request); - } +// assert!(account.is_valid_signature(invalid_hash, signature) != starknet::VALIDATED); +// } - #[test] - #[should_panic(expected: "wrong token")] - fn wrong_token() { - let erc20_class = declare_erc20(); - let account_class = declare_account(); +// #[test] +// fn validate_transaction() { +// let public_key = 0xdff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659; - let dai = deploy_erc20(erc20_class, 'DAI token', 'DAI', 100, 21.try_into().unwrap()); - - let (request, sender, _, _) = request_fixture_custom_classes(erc20_class, account_class); - - let request = SocialRequest { - content: Transfer { token_address: dai.contract_address, ..request.content.clone() }, - ..request, - }; - - sender.handle_transfer(request); - } - - #[test] - #[should_panic(expected: "double spend")] - fn double_transfer() { - let erc20_class = declare_erc20(); - let account_class = declare_account(); - let (request, sender, _, _) = request_fixture_custom_classes(erc20_class, account_class); - let (request2, _, _, _) = request_fixture_custom_classes(erc20_class, account_class); - - sender.handle_transfer(request); - sender.handle_transfer(request2); - } +// let account_class = declare_account(); +// let account = deploy_account(account_class, public_key); - #[test] - fn is_valid_signature() { - let public_key = 0xdff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659; +// let account = ISRC6Dispatcher { contract_address: account.contract_address }; - let account_class = declare_account(); - let account = deploy_account(account_class, public_key); +// let hash = 0x6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89; - let account = ISRC6Dispatcher { contract_address: account.contract_address }; +// let r: u256 = 0x49ae3fa614e2877877a90987726f1b48387bef1f66de78e5075659040cbbf612; +// let s: u256 = 0x11259ae25e0743ac7490df3fef875ea291c7b99cf2295e44aabd677107b9c53a; - let hash = 0x6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89; +// let mut signature = Default::default(); +// r.serialize(ref signature); +// s.serialize(ref signature); - let r: u256 = 0x49ae3fa614e2877877a90987726f1b48387bef1f66de78e5075659040cbbf612; - let s: u256 = 0x11259ae25e0743ac7490df3fef875ea291c7b99cf2295e44aabd677107b9c53a; +// cheat_transaction_hash_global(hash); +// cheat_signature_global(signature.span()); - let mut signature = Default::default(); - r.serialize(ref signature); - s.serialize(ref signature); +// assert!(account.__validate__(Default::default()) == starknet::VALIDATED); - assert!(account.is_valid_signature(hash, signature.clone()) == starknet::VALIDATED); +// let invalid_hash = 0x5a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89; +// cheat_transaction_hash_global(invalid_hash); - let invalid_hash = 0x5a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89; +// assert!(account.__validate__(Default::default()) != starknet::VALIDATED); - assert!(account.is_valid_signature(invalid_hash, signature) != starknet::VALIDATED); - } - - #[test] - fn validate_transaction() { - let public_key = 0xdff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659; - - let account_class = declare_account(); - let account = deploy_account(account_class, public_key); - - let account = ISRC6Dispatcher { contract_address: account.contract_address }; - - let hash = 0x6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89; - - let r: u256 = 0x49ae3fa614e2877877a90987726f1b48387bef1f66de78e5075659040cbbf612; - let s: u256 = 0x11259ae25e0743ac7490df3fef875ea291c7b99cf2295e44aabd677107b9c53a; - - let mut signature = Default::default(); - r.serialize(ref signature); - s.serialize(ref signature); - - cheat_transaction_hash_global(hash); - cheat_signature_global(signature.span()); - - assert!(account.__validate__(Default::default()) == starknet::VALIDATED); - - let invalid_hash = 0x5a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89; - cheat_transaction_hash_global(invalid_hash); - - assert!(account.__validate__(Default::default()) != starknet::VALIDATED); - - stop_cheat_transaction_hash_global(); - stop_cheat_signature_global(); - } -} +// stop_cheat_transaction_hash_global(); +// stop_cheat_signature_global(); +// } +// } diff --git a/onchain/cairo/src/social/mod.cairo b/onchain/cairo/src/social/mod.cairo index d2f27b5f..54fdd741 100644 --- a/onchain/cairo/src/social/mod.cairo +++ b/onchain/cairo/src/social/mod.cairo @@ -1,4 +1,5 @@ -pub mod account; +// pub mod account;// uncommented test etc when used pub mod bech32; +pub mod deposit; pub mod namespace; pub mod request; diff --git a/onchain/cairo/src/social/namespace.cairo b/onchain/cairo/src/social/namespace.cairo index 8ba84058..19af9787 100644 --- a/onchain/cairo/src/social/namespace.cairo +++ b/onchain/cairo/src/social/namespace.cairo @@ -44,11 +44,11 @@ pub enum LinkedResult { #[starknet::interface] pub trait INamespace { // Getters - fn get_nostr_to_sn_default( + fn get_nostr_by_sn_default( self: @TContractState, nostr_public_key: NostrPublicKey ) -> ContractAddress; - fn get_sn_to_nostr_default( + fn get_sn_by_nostr_default( self: @TContractState, starknet_address: ContractAddress ) -> NostrPublicKey; // Admin @@ -179,14 +179,14 @@ pub mod Namespace { } // Getters - fn get_nostr_to_sn_default( + fn get_nostr_by_sn_default( self: @ContractState, nostr_public_key: NostrPublicKey ) -> ContractAddress { self.nostr_to_sn.read(nostr_public_key) } - fn get_sn_to_nostr_default( + fn get_sn_by_nostr_default( self: @ContractState, starknet_address: ContractAddress ) -> NostrPublicKey { self.sn_to_nostr.read(starknet_address) @@ -360,7 +360,7 @@ mod tests { start_cheat_caller_address(namespace.contract_address, sender_address); namespace.linked_nostr_default_account(request); - let nostr_linked = namespace.get_nostr_to_sn_default(recipient_nostr_key); + let nostr_linked = namespace.get_nostr_by_sn_default(recipient_nostr_key); assert!(nostr_linked == sender_address, "nostr not linked"); } diff --git a/onchain/cairo/src/tests/launchpad_tests.cairo b/onchain/cairo/src/tests/launchpad_tests.cairo index ac530878..e4700a8e 100644 --- a/onchain/cairo/src/tests/launchpad_tests.cairo +++ b/onchain/cairo/src/tests/launchpad_tests.cairo @@ -4,7 +4,7 @@ mod launchpad_tests { ILaunchpadMarketplaceDispatcher, ILaunchpadMarketplaceDispatcherTrait }; use afk::tokens::erc20::{ERC20, IERC20, IERC20Dispatcher, IERC20DispatcherTrait}; - use afk::types::launchpad_types::{MINTER_ROLE, ADMIN_ROLE, TokenQuoteBuyKeys, BondingType}; + use afk::types::launchpad_types::{MINTER_ROLE, ADMIN_ROLE, TokenQuoteBuyCoin, BondingType}; use core::array::SpanTrait; use core::num::traits::Zero; use core::traits::Into; @@ -204,7 +204,7 @@ mod launchpad_tests { start_cheat_caller_address(erc20.contract_address, sender_address); erc20.approve(launchpad.contract_address, amount_quote); let allowance = erc20.allowance(sender_address, launchpad.contract_address); - println!("test allowance erc20 {}", allowance); + // println!("test allowance erc20 {}", allowance); stop_cheat_caller_address(erc20.contract_address); start_cheat_caller_address(launchpad.contract_address, sender_address); @@ -331,10 +331,11 @@ mod launchpad_tests { launchpad, erc20, memecoin, first_buy, token_address, sender_address, ); - // All buy run_buy_by_amount( - launchpad, erc20, memecoin, THRESHOLD_LIQUIDITY -30, token_address, sender_address, + launchpad, erc20, memecoin, THRESHOLD_LIQUIDITY / 10, token_address, sender_address, ); + + } @@ -410,10 +411,10 @@ mod launchpad_tests { 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, + // ); diff --git a/onchain/cairo/src/types/launchpad_types.cairo b/onchain/cairo/src/types/launchpad_types.cairo index 19f43ba1..c8be848a 100644 --- a/onchain/cairo/src/types/launchpad_types.cairo +++ b/onchain/cairo/src/types/launchpad_types.cairo @@ -30,7 +30,7 @@ pub enum BondingType { // Storage #[derive(Drop, Serde, Copy, starknet::Store)] -pub struct TokenQuoteBuyKeys { +pub struct TokenQuoteBuyCoin { pub token_address: ContractAddress, pub initial_key_price: u256, pub price: u256, @@ -66,10 +66,11 @@ pub struct TokenLaunch { pub initial_key_price: u256, pub price: u256, pub available_supply: u256, + pub initial_pool_supply: u256, pub total_supply: u256, pub bonding_curve_type: Option, pub created_at: u64, - pub token_quote: TokenQuoteBuyKeys, + pub token_quote: TokenQuoteBuyCoin, pub liquidity_raised: u256, pub token_holded: u256, pub is_liquidity_launch: bool, @@ -87,14 +88,14 @@ pub struct TokenLaunchFair { pub total_supply: u256, pub bonding_curve_type: Option, pub created_at: u64, - pub token_quote: TokenQuoteBuyKeys, + pub token_quote: TokenQuoteBuyCoin, pub final_time: u64, } #[derive(Drop, Serde, Clone, starknet::Store)] -pub struct SharesKeys { +pub struct SharesTokenUser { pub owner: ContractAddress, - pub key_address: ContractAddress, + pub token_address: ContractAddress, pub amount_owned: u256, pub amount_buy: u256, pub amount_sell: u256, @@ -185,6 +186,17 @@ pub struct SetJediwapNFTRouterV2 { pub address_jediswap_nft_router_v2: ContractAddress, } + +#[derive(Drop, starknet::Event)] +pub struct LiquidityCanBeAdded { + #[key] + pub pool: ContractAddress, + #[key] + pub asset: ContractAddress, + #[key] + pub quote_token_address: ContractAddress, +} + #[derive(Drop, starknet::Event)] pub struct LiquidityCreated { #[key] diff --git a/onchain/foundry.toml b/onchain/foundry.toml index 18434eee..637d9d56 100644 --- a/onchain/foundry.toml +++ b/onchain/foundry.toml @@ -2,7 +2,7 @@ src = "solidity_contracts/src" test = "solidity_contracts/test" out = "out" -libs = ["solidity_contracts/lib"] +libs = ["solidity_contracts/lib", "lib/kakarot-rpc"] # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/onchain/lib/kakarot-rpc b/onchain/lib/kakarot-rpc new file mode 160000 index 00000000..f97902f1 --- /dev/null +++ b/onchain/lib/kakarot-rpc @@ -0,0 +1 @@ +Subproject commit f97902f15b488f4fb9db51738e23f287154033f4 diff --git a/onchain/package.json b/onchain/package.json index 2c05b710..c69dffe8 100644 --- a/onchain/package.json +++ b/onchain/package.json @@ -24,6 +24,7 @@ }, "dependencies": { "dotenv": "^16.4.5", + "onchain": "link:", "solidity": "link:", "starknet": "^6.11.0" } diff --git a/onchain/scripts/config.ts b/onchain/scripts/config.ts index 345e3491..172676f6 100644 --- a/onchain/scripts/config.ts +++ b/onchain/scripts/config.ts @@ -12,7 +12,7 @@ export const readContractSierraCasm = (name: string): CompiledSierraCasm => .readFileSync( path.resolve( __dirname, - `../cairo_contracts/target/dev/cairo_contracts_${name}.compiled_contract_class.json`, + `../cairo/target/dev/afk_${name}.compiled_contract_class.json`, ), ) .toString("ascii"), @@ -24,7 +24,7 @@ export const readContractSierra = (name: string): CompiledSierra => .readFileSync( path.resolve( __dirname, - `../cairo_contracts/target/dev/cairo_contracts_${name}.contract_class.json`, + `../cairo/target/dev/afk_${name}.contract_class.json`, ), ) .toString("ascii"), diff --git a/onchain/solidity_contracts/lib/forge-std b/onchain/solidity_contracts/lib/forge-std new file mode 160000 index 00000000..58d30519 --- /dev/null +++ b/onchain/solidity_contracts/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 58d30519826c313ce47345abedfdc07679e944d1 diff --git a/onchain/solidity_contracts/lib/kakarot-lib b/onchain/solidity_contracts/lib/kakarot-lib new file mode 160000 index 00000000..a137c35a --- /dev/null +++ b/onchain/solidity_contracts/lib/kakarot-lib @@ -0,0 +1 @@ +Subproject commit a137c35a79467ec4dedcbd65867a9bff16b39104 diff --git a/onchain/solidity_contracts/src/launchpad/LaunchpadPumpDualVM.sol b/onchain/solidity_contracts/src/launchpad/LaunchpadPumpDualVM.sol index 506f0b30..27750c74 100644 --- a/onchain/solidity_contracts/src/launchpad/LaunchpadPumpDualVM.sol +++ b/onchain/solidity_contracts/src/launchpad/LaunchpadPumpDualVM.sol @@ -2,16 +2,79 @@ pragma solidity >=0.8.0; contract LaunchpadPumpDualVM { - + /// @dev The address of the cairo contract to call uint256 immutable starknetLaunchpad; + /// @dev The cairo function selector to call - `create_token` + uint256 constant FUNCTION_SELECTOR_CREATE_TOKEN = uint256(keccak256("create_token")) % 2 ** 250; + + /// @dev The cairo function selector to call - `create_and_launch_token` + uint256 constant FUNCTION_SELECTOR_CREATE_TOKEN_AND_LAUNCH= uint256(keccak256("create_and_launch_token")) % 2 ** 250; + + + /// @dev The cairo function selector to call - `launch_token` + uint256 constant FUNCTION_SELECTOR_LAUNCH_TOKEN = uint256(keccak256("launch_token")) % 2 ** 250; + + + /// @dev The cairo function selector to call - `get_coin_launch` + uint256 constant FUNCTION_SELECTOR_GET_LAUNCH = uint256(keccak256("get_coin_launch")) % 2 ** 250; + + /// @dev The cairo function selector to call - `buy_coin_by_quote_amount` + uint256 constant FUNCTION_SELECTOR_BUY_COIN = uint256(keccak256("buy_coin_by_quote_amount")) % 2 ** 250; + + /// @dev The cairo function selector to call - `sell_coin` + uint256 constant FUNCTION_SELECTOR_SELL_COIN = uint256(keccak256("sell_coin")) % 2 ** 250; + + struct SharesTokenUser { + address owner; + address token_address; + uint256 price; + uint256 amount_owned; + uint256 amount_buy; + uint256 amount_sell; + uint256 total_paid; + uint64 created_at; + } + + struct TokenLaunch { + address owner; + address token_address; + uint256 price; + uint256 available_supply; + uint256 total_supply; + uint256 initial_key_price; + uint256 liquidity_raised; + uint256 token_holded; + bool is_liquidity_launch; + uint256 slop; + uint64 created_at; + } + + struct Token { + address owner; + address token_address; + bytes symbol; + bytes name; + uint256 total_supply; + uint256 initial_supply; + uint64 created_at; + + } + constructor(uint256 _starknetLaunchpad) { starknetLaunchpad = _starknetLaunchpad; } - function getLaunchPump(uint256 userAddress) public { + function getLaunchPump(uint256 tokenAddress) public { + + uint256[] memory tokenAddressCalldata = new uint256[](1); + tokenAddressCalldata[0] = uint256(uint160(from)); + uint256 tokenStarknetAddress = + abi.decode(kakarot.staticcallCairo("compute_starknet_address", tokenAddressCalldata), (uint256)); + // call launch that sent struct + // todo how do it? } function createToken() public { diff --git a/onchain/solidity_contracts/src/nostr/Namespace.sol b/onchain/solidity_contracts/src/nostr/Namespace.sol index a2a608c3..f856e0c1 100644 --- a/onchain/solidity_contracts/src/nostr/Namespace.sol +++ b/onchain/solidity_contracts/src/nostr/Namespace.sol @@ -3,12 +3,43 @@ pragma solidity >=0.8.0; contract Namespace { - constructor() { - + /// @dev The address of the starknet token to call + uint256 immutable namespaceAddress; + + constructor(uint256 _namespaceAddress) { + namespaceAddress = _namespaceAddress; } + + // Get nostr address by starknet address function getNostrAddressByStarknetAddress(uint256 userAddress) public { + uint256[] memory kakarotCallData = new uint256[](1); + kakarotCallData[0] = uint256(uint160(userAddress)); + + uint256 userStarknetAddress = + abi.decode(kakarot.staticcallCairo("compute_starknet_address", kakarotCallData), (uint256)); + + uint256[] memory addressOfCallData = new uint256[](1); + addressOfCallData[0] = userStarknetAddress; + bytes memory returnData = namespaceAddress.staticcallCairo("get_nostr_by_sn_default", balanceOfCallData); + return abi.decode(returnData, (uint256)); + } + + + // Get Starknet address namespace with + function getStarknetAddressByNostrAddress(uint256 nostrAddress) public { + + uint256[] memory kakarotCallData = new uint256[](1); + kakarotCallData[0] = uint256(uint160(nostrAddress)); + + uint256 userStarknetAddress = + abi.decode(kakarot.staticcallCairo("compute_starknet_address", kakarotCallData), (uint256)); + + uint256[] memory addressOfCallData = new uint256[](1); + addressOfCallData[0] = userStarknetAddress; + bytes memory returnData = namespaceAddress.staticcallCairo("get_sn_by_nostr_default", balanceOfCallData); + return abi.decode(returnData, (uint256)); } function linkNostrAddress() public { diff --git a/packages/common/src/contracts.ts b/packages/common/src/contracts.ts index bb1159a2..c1875287 100644 --- a/packages/common/src/contracts.ts +++ b/packages/common/src/contracts.ts @@ -43,7 +43,9 @@ export const LAUNCHPAD_ADDRESS = { [constants.StarknetChainId.SN_MAIN]: "", // [constants.StarknetChainId.SN_SEPOLIA]:"0x5cf19613d54ae5e7c229c87cc26322f2ff6c473d2183723010676b8337c0af3", // [constants.StarknetChainId.SN_SEPOLIA]:"0x19084523bd7307c2169ee32a336be3f9d9eb6bf24197156cb6fc7a42feb7a5" - [constants.StarknetChainId.SN_SEPOLIA]:"0x29a532e6933a6d6f9939e59469d96b52b7c38561745331302e1a29f035e4dd0" + // [constants.StarknetChainId.SN_SEPOLIA]:"0x29a532e6933a6d6f9939e59469d96b52b7c38561745331302e1a29f035e4dd0", + [constants.StarknetChainId.SN_SEPOLIA]:"0x3798921000573bfc442d8153fc088db97bd3794f5ed19ea8c0846db5378f4af", + } diff --git a/scripts/.env.exemple b/scripts/.env.exemple index e418d786..c4173d87 100644 --- a/scripts/.env.exemple +++ b/scripts/.env.exemple @@ -16,7 +16,7 @@ NODE_ENV=development ESCROW_CLASS_HASH=0x3f70abaaeef59cc900b597d45a2c97c08abb5260c03327cce9e45d4c7a8ad0 # Sepolia KEY_CLASS_HASH=0x788881563d2af51d1eeacc8607b2e95c60110eddab5b43223ec97cac6d7d885 -LAUNCHPAD_CLASS_HASH=0x4a357ece4e9cc78cafe856fdf676f564d4614cc8e09c53e7bc4617515eea511 +LAUNCHPAD_CLASS_HASH=0x75e02f0e02f31ce405ff77551e5b343631451d2e27c8935e5f62cfa86a9d6b # Env test and scripts IS_DEPLOY_CONTRACT=true REDECLARE_ACCOUNT=false # Set to true on devnet