Skip to content

Commit

Permalink
feat: gno social feeds (#642)
Browse files Browse the repository at this point in the history
* wip: handle post for gno

* wip: integrating gno boards

* wip: working on get gno feed

* feat: hanndle actions/comments/pagination for posts

* chore: add missing files

* feat: use network features to handle menu

* chore: update networkjson

* feat: add gno teritori

* feat: add teritori gno network

* chore: fix lint

* chore: add update network

* fix: fix lint

* feat: update contract social_feeds_v3 + fix teritori test network

* chore: remove default val
  • Loading branch information
hthieu1110 authored Aug 6, 2023
1 parent 3f97336 commit e08c001
Show file tree
Hide file tree
Showing 22 changed files with 527 additions and 126 deletions.
12 changes: 8 additions & 4 deletions networks.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"icon": "icons/networks/teritori.svg",
"features": [
"NFTMarketplace",
"Organizations"
"Organizations",
"SocialFeed"
],
"walletUrlForStaking": "https://explorer.teritori.com/teritori/staking",
"currencies": [
Expand Down Expand Up @@ -132,7 +133,8 @@
"icon": "icons/networks/teritori.svg",
"features": [
"NFTMarketplace",
"Organizations"
"Organizations",
"SocialFeed"
],
"currencies": [
{
Expand Down Expand Up @@ -567,7 +569,8 @@
"displayName": "Gno Dev",
"icon": "icons/networks/gno.svg",
"features": [
"Organizations"
"Organizations",
"SocialFeed"
],
"currencies": [
{
Expand Down Expand Up @@ -600,7 +603,8 @@
"displayName": "Gno Teritori",
"icon": "icons/networks/gno.svg",
"features": [
"Organizations"
"Organizations",
"SocialFeed"
],
"currencies": [
{
Expand Down
4 changes: 2 additions & 2 deletions packages/components/TopMenu/TopMenuMyWallets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
useSelectedNetworkInfo,
} from "../../hooks/useSelectedNetwork";
import useSelectedWallet from "../../hooks/useSelectedWallet";
import { getStakingCurrency, NetworkKind } from "../../networks";
import { CurrencyInfo, getStakingCurrency, NetworkKind } from "../../networks";
import { DepositWithdrawModal } from "../../screens/WalletManager/components/DepositWithdrawModal";
import { useAppNavigation } from "../../utils/navigation";
import {
Expand Down Expand Up @@ -189,7 +189,7 @@ export const TopMenuMyWallets: React.FC = () => {

const atomIbcCurrency = useMemo(() => {
return selectedNetworkInfo?.currencies.find(
(currencyInfo) =>
(currencyInfo: CurrencyInfo) =>
currencyInfo.kind === "ibc" && currencyInfo.sourceDenom === "uatom"
);
}, [selectedNetworkInfo]);
Expand Down
89 changes: 64 additions & 25 deletions packages/components/socialFeed/NewsFeed/NewsFeedInput.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { coin } from "@cosmjs/amino";
import { GnoJSONRPCProvider } from "@gnolang/gno-js-client";
import React, { useImperativeHandle, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import {
Expand Down Expand Up @@ -35,12 +36,17 @@ import { useUpdatePostFee } from "../../../hooks/feed/useUpdatePostFee";
import { useBalances } from "../../../hooks/useBalances";
import { useIsMobile } from "../../../hooks/useIsMobile";
import { useMaxResolution } from "../../../hooks/useMaxResolution";
import { useSelectedNetworkId } from "../../../hooks/useSelectedNetwork";
import { useSelectedNetworkInfo } from "../../../hooks/useSelectedNetwork";
import useSelectedWallet from "../../../hooks/useSelectedWallet";
import { getUserId, mustGetCosmosNetwork } from "../../../networks";
import {
NetworkKind,
getUserId,
mustGetCosmosNetwork,
} from "../../../networks";
import { selectNFTStorageAPI } from "../../../store/slices/settings";
import { prettyPrice } from "../../../utils/coins";
import { defaultSocialFeedFee } from "../../../utils/fee";
import { adenaDoContract } from "../../../utils/gno";
import { generateIpfsKey, uploadFilesToPinata } from "../../../utils/ipfs";
import {
AUDIO_MIME_TYPES,
Expand Down Expand Up @@ -89,6 +95,7 @@ import { FileUploader } from "../../fileUploader";
import { SpacerColumn } from "../../spacer";
import { EmojiSelector } from "../EmojiSelector";
import { GIFSelector } from "../GIFSelector";
import { GNO_SOCIAL_FEEDS_PKG_PATH, TERITORI_FEED_ID } from "../const";

interface NewsFeedInputProps {
type: "comment" | "post";
Expand Down Expand Up @@ -142,7 +149,8 @@ export const NewsFeedInput = React.forwardRef<
const inputMinHeight = 20;
const inputHeight = useSharedValue(20);
const wallet = useSelectedWallet();
const selectedNetworkId = useSelectedNetworkId();
const selectedNetwork = useSelectedNetworkInfo();
const selectedNetworkId = selectedNetwork?.id || "teritori";
const selectedWallet = useSelectedWallet();
const userId = getUserId(selectedNetworkId, selectedWallet?.address);
const inputRef = useRef<TextInput>(null);
Expand Down Expand Up @@ -170,10 +178,7 @@ export const NewsFeedInput = React.forwardRef<
onCloseCreateModal && onCloseCreateModal();
};

const balances = useBalances(
process.env.TERITORI_NETWORK_ID,
wallet?.address
);
const balances = useBalances(selectedNetworkId, wallet?.address);

const { setValue, handleSubmit, reset, watch } = useForm<NewPostFormValues>(
{
Expand All @@ -199,8 +204,11 @@ export const NewsFeedInput = React.forwardRef<
);

const processSubmit = async () => {
const toriBalance = balances.find((bal) => bal.denom === "utori");
if (postFee > Number(toriBalance?.amount) && !freePostCount) {
const denom = selectedNetwork?.currencies[0].denom;

const currentBalance = balances.find((bal) => bal.denom === denom);

if (postFee > Number(currentBalance?.amount) && !freePostCount) {
return setNotEnoughFundModal(true);
}

Expand Down Expand Up @@ -254,14 +262,8 @@ export const NewsFeedInput = React.forwardRef<
});
return;
}

const postCategory = getPostCategory(formValues);

const client = await signingSocialFeedClient({
networkId: selectedNetworkId,
walletAddress: wallet?.address || "",
});

const metadata: SocialFeedMetadata = generatePostMetadata({
title: formValues.title || "",
message: finalMessage,
Expand All @@ -282,6 +284,7 @@ export const NewsFeedInput = React.forwardRef<

if (daoId) {
const network = mustGetCosmosNetwork(selectedNetworkId);

if (!network.socialFeedContractAddress) {
throw new Error("Social feed contract address not found");
}
Expand All @@ -306,15 +309,51 @@ export const NewsFeedInput = React.forwardRef<
],
});
} else {
await mutateAsync({
client,
msg,
args: {
fee: defaultSocialFeedFee,
memo: "",
funds: [coin(postFee, "utori")],
},
});
if (selectedNetwork?.kind === NetworkKind.Gno) {
// const provider = new GnoJSONRPCProvider(selectedNetwork.endpoint);

const msg = {
category: postCategory,
identifier,
metadata: JSON.stringify(metadata),
parentPostIdentifier: hasUsername ? replyTo?.parentId : parentId,
};

const vmCall = {
caller: selectedWallet?.address || "",
send: "",
pkg_path: GNO_SOCIAL_FEEDS_PKG_PATH,
func: "CreatePost",
args: [
TERITORI_FEED_ID,
msg.parentPostIdentifier || "0",
msg.category.toString(),
msg.metadata,
],
};

const txHash = await adenaDoContract(selectedNetworkId, [
{ type: "/vm.m_call", value: vmCall },
]);

const provider = new GnoJSONRPCProvider(selectedNetwork.endpoint);
await provider.waitForTransaction(txHash);
onPostCreationSuccess();
} else {
const client = await signingSocialFeedClient({
networkId: selectedNetworkId,
walletAddress: wallet?.address || "",
});
await mutateAsync({
client,
msg,
args: {
fee: defaultSocialFeedFee,
memo: "",
funds: [coin(postFee, "utori")],
},
});
}

if (
postCategory === PostCategory.Question ||
Expand Down Expand Up @@ -552,7 +591,7 @@ export const NewsFeedInput = React.forwardRef<
: `The cost for this ${type} is ${prettyPrice(
selectedNetworkId,
postFee.toString(),
"utori"
selectedNetwork?.currencies?.[0].denom || "utori"
)}`}
</BrandText>
</View>
Expand Down
69 changes: 55 additions & 14 deletions packages/components/socialFeed/NewsFeed/NewsFeedQueries.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { coin } from "@cosmjs/amino";
import { GnoJSONRPCProvider } from "@gnolang/gno-js-client";
import { v4 as uuidv4 } from "uuid";

import {
PostCategory,
NewPostFormValues,
PostCategory,
SocialFeedMetadata,
} from "./NewsFeed.type";
import {
nonSigningSocialFeedClient,
signingSocialFeedClient,
} from "../../../client-creators/socialFeedClient";
import { Wallet } from "../../../context/WalletsProvider";
import { mustGetNetwork, NetworkKind } from "../../../networks";
import { defaultSocialFeedFee } from "../../../utils/fee";
import { adenaDoContract } from "../../../utils/gno";
import { ipfsURLToHTTPURL, uploadFilesToPinata } from "../../../utils/ipfs";
import { RemoteFileData } from "../../../utils/types/files";
import { GNO_SOCIAL_FEEDS_PKG_PATH, TERITORI_FEED_ID } from "../const";

interface GetAvailableFreePostParams {
networkId: string;
wallet?: Wallet;
Expand Down Expand Up @@ -122,11 +127,6 @@ export const createPost = async ({
return;
}

const client = await signingSocialFeedClient({
networkId,
walletAddress: wallet.address,
});

let files: RemoteFileData[] = [];

if (formValues.files?.length && pinataJWTKey) {
Expand Down Expand Up @@ -161,17 +161,58 @@ export const createPost = async ({
mentions: formValues.mentions || [],
});

await client.createPost(
{
const network = mustGetNetwork(networkId);

if (network.kind === NetworkKind.Gno) {
const msg = {
category,
identifier: identifier || uuidv4(),
identifier,
metadata: JSON.stringify(metadata),
parentPostIdentifier: parentId,
},
defaultSocialFeedFee,
"",
freePostCount ? undefined : [coin(fee, "utori")]
);
};

const vmCall = {
caller: wallet.address,
send: "",
pkg_path: GNO_SOCIAL_FEEDS_PKG_PATH,
func: "CreatePost",
args: [
TERITORI_FEED_ID,
msg.parentPostIdentifier || "0",
msg.category.toString(),
msg.metadata,
],
};

const txHash = await adenaDoContract(
networkId,
[{ type: "/vm.m_call", value: vmCall }],
{
gasWanted: 2_000_000,
}
);

const provider = new GnoJSONRPCProvider(network.endpoint);
await provider.waitForTransaction(txHash);
} else {
const client = await signingSocialFeedClient({
networkId,
walletAddress: wallet.address,
});

await client.createPost(
{
category,
identifier: identifier || uuidv4(),
metadata: JSON.stringify(metadata),
parentPostIdentifier: parentId,
},
defaultSocialFeedFee,
"",
freePostCount ? undefined : [coin(fee, "utori")]
);
}

return true;
};

Expand Down
Loading

0 comments on commit e08c001

Please sign in to comment.