From e56ac5bc0c4ba080dfa8dc1aefe4a7b1caaa241f Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Thu, 10 Oct 2024 16:52:48 +0200 Subject: [PATCH 01/27] test: e2e test to create dao creation flow --- cypress/e2e/dao-creation.cy.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 cypress/e2e/dao-creation.cy.ts diff --git a/cypress/e2e/dao-creation.cy.ts b/cypress/e2e/dao-creation.cy.ts new file mode 100644 index 0000000000..bb4db144fb --- /dev/null +++ b/cypress/e2e/dao-creation.cy.ts @@ -0,0 +1,11 @@ +describe("Create a dao flow", () => { + it("works", () => { + cy.request("http://127.0.0.1:8888/reset"); + + cy.visit("http://localhost:8081/orgs?network=gno-dev", { + timeout: 300000, + }); + + cy.contains("Create Dao").click(); + }); +}); From 6860ec0e2209f0d7d84f01ab3d5c3cbb5a4aeee7 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Thu, 10 Oct 2024 18:50:08 +0200 Subject: [PATCH 02/27] wip: e2e test to create dao creation flow --- cypress/e2e/dao-creation.cy.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cypress/e2e/dao-creation.cy.ts b/cypress/e2e/dao-creation.cy.ts index bb4db144fb..b394463462 100644 --- a/cypress/e2e/dao-creation.cy.ts +++ b/cypress/e2e/dao-creation.cy.ts @@ -6,6 +6,16 @@ describe("Create a dao flow", () => { timeout: 300000, }); + const daoName = "Test Dao"; + const handle = "testdao"; + const url = "https://images.unsplash.com/photo-1492571350019-22de08371fd3?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"; + const description = "Test Dao description"; + cy.contains("Create Dao").click(); + + cy.get("input[placeholder='Type organization\\'s name here']").type(daoName); + cy.get("input[placeholder='your_organization']").type(handle); + cy.get("input[placeholder='https://example.com/preview.png']").type(url); + //cy.type("input[placeholder='Type organization\\'s description here']").type(description); WHY IT DOES NOT WORK ?? }); }); From c04bea24d3e46720543de9160298f6456de2331d Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Fri, 11 Oct 2024 00:48:23 +0200 Subject: [PATCH 03/27] wip: e2e test handle filling all steps in dao creation form --- cypress/e2e/dao-creation.cy.ts | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/cypress/e2e/dao-creation.cy.ts b/cypress/e2e/dao-creation.cy.ts index b394463462..7073142ed1 100644 --- a/cypress/e2e/dao-creation.cy.ts +++ b/cypress/e2e/dao-creation.cy.ts @@ -8,14 +8,32 @@ describe("Create a dao flow", () => { const daoName = "Test Dao"; const handle = "testdao"; - const url = "https://images.unsplash.com/photo-1492571350019-22de08371fd3?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"; + const url = + "https://images.unsplash.com/photo-1492571350019-22de08371fd3?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"; const description = "Test Dao description"; + const memberAddress = "g1nyz430dsujj56ygllcaujkzagz54v0l6yusspy"; cy.contains("Create Dao").click(); - cy.get("input[placeholder='Type organization\\'s name here']").type(daoName); + cy.get("input[placeholder='Type organization\\'s name here']").type( + daoName, + ); cy.get("input[placeholder='your_organization']").type(handle); cy.get("input[placeholder='https://example.com/preview.png']").type(url); - //cy.type("input[placeholder='Type organization\\'s description here']").type(description); WHY IT DOES NOT WORK ?? + // because cy.get("input[placeholder='Type organization\\'s description here']").type(description) doesn't work, i use suggested selector from cypress studio + cy.get( + ":nth-child(5) > [style='flex-direction: row; width: 100%;'] > :nth-child(1) > [style='width: 100%;'] > .r-alignItems-1habvwh > .r-alignItems-1awozwy > .css-view-175oi2r > .css-textinput-11aywtz", + ).type(description); + + cy.contains("Next: Configure voting").click(); + cy.contains("Next: Set tokens or members").click(); + + cy.get( + '.r-display-6koalj > :nth-child(1) > .r-WebkitOverflowScrolling-150rngu > .r-padding-1jgu3lx > .r-marginBottom-1ifxtd0 > .r-flex-6wfxan > :nth-child(1) > [style="flex-direction: row; width: 100%;"] > :nth-child(1) > [style="width: 100%;"] > .r-alignItems-1habvwh > .r-flexDirection-18u37iz > [style="flex: 1 1 0%; margin-right: 12px;"] > .css-textinput-11aywtz', + ).type(memberAddress); + + cy.get( + '.r-display-6koalj > :nth-child(1) > .r-alignItems-obd0qt > .r-cursor-1loqt21 > [style="height: 48px; opacity: 1;"] > [style="width: 100%; height: 100%; border-width: 1px; border-color: rgba(0, 0, 0, 0); padding: 0px 20px; align-items: center; justify-content: center;"]', + ).click(); }); }); From 59680d9b7737660593c429911e03aed67a524ab5 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Fri, 11 Oct 2024 16:47:54 +0200 Subject: [PATCH 04/27] wip: e2e test handle filling all steps in dao creation form --- cypress/e2e/dao-creation.cy.ts | 4 +- gno/r/test/gno.mod | 1 + gno/r/test/test.gno | 104 ++++++++++++++++++++++++++++++++ packages/utils/gnodao/deploy.ts | 23 +++---- 4 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 gno/r/test/gno.mod create mode 100644 gno/r/test/test.gno diff --git a/cypress/e2e/dao-creation.cy.ts b/cypress/e2e/dao-creation.cy.ts index 7073142ed1..5f6c264ec0 100644 --- a/cypress/e2e/dao-creation.cy.ts +++ b/cypress/e2e/dao-creation.cy.ts @@ -15,7 +15,7 @@ describe("Create a dao flow", () => { cy.contains("Create Dao").click(); - cy.get("input[placeholder='Type organization\\'s name here']").type( + cy.get("input[plac eholder='Type organization\\'s name here']").type( daoName, ); cy.get("input[placeholder='your_organization']").type(handle); @@ -35,5 +35,7 @@ describe("Create a dao flow", () => { cy.get( '.r-display-6koalj > :nth-child(1) > .r-alignItems-obd0qt > .r-cursor-1loqt21 > [style="height: 48px; opacity: 1;"] > [style="width: 100%; height: 100%; border-width: 1px; border-color: rgba(0, 0, 0, 0); padding: 0px 20px; align-items: center; justify-content: center;"]', ).click(); + + cy.contains("Confirm & Launch the Organization").click(); }); }); diff --git a/gno/r/test/gno.mod b/gno/r/test/gno.mod new file mode 100644 index 0000000000..d207309536 --- /dev/null +++ b/gno/r/test/gno.mod @@ -0,0 +1 @@ +module gno.land/r/teritori/test diff --git a/gno/r/test/test.gno b/gno/r/test/test.gno new file mode 100644 index 0000000000..148773ee73 --- /dev/null +++ b/gno/r/test/test.gno @@ -0,0 +1,104 @@ +package test + +import ( + dao_core "gno.land/p/teritori/dao_core" + dao_interfaces "gno.land/p/teritori/dao_interfaces" + proposal_single "gno.land/p/teritori/dao_proposal_single" + voting_group "gno.land/p/teritori/dao_voting_group" + "gno.land/r/teritori/dao_registry" + "gno.land/r/teritori/groups" +) + +var ( + daoCore dao_interfaces.IDAOCore + mainBoardName = "test" + groupName = mainBoardName + "_voting_group" + groupID groups.GroupID +) + +func init() { + modboards.CreateBoard(mainBoardName) + + votingModuleFactory := func(core dao_interfaces.IDAOCore) dao_interfaces.IVotingModule { + groupID = groups.CreateGroup(groupName) + groups.AddMember(groupID, "g16jv3rpz7mkt0gqulxas56se2js7v5vmc6n6e0r", 1, "") + return voting_group.NewVotingGroup(groupID) + } + + // TODO: consider using factories that return multiple modules and handlers + + proposalModulesFactories := []dao_interfaces.ProposalModuleFactory{ + func(core dao_interfaces.IDAOCore) dao_interfaces.IProposalModule { + tt := proposal_single.PercentageThresholdPercent(1500) // 15% + tq := proposal_single.PercentageThresholdPercent(5000) // 50% + return proposal_single.NewDAOProposalSingle(core, &proposal_single.DAOProposalSingleOpts{ + MaxVotingPeriod: 60 * 86400, + Threshold: &proposal_single.ThresholdThresholdQuorum{ + Threshold: &tt, + Quorum: &tq, + }, + }) + }, + } + + messageHandlersFactories := []dao_interfaces.MessageHandlerFactory{ + func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { + return groups.NewAddMemberHandler() + }, + func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { + return groups.NewDeleteMemberHandler() + }, + func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { + // TODO: add a router to support multiple proposal modules + propMod := core.ProposalModules()[0] + return proposal_single.NewUpdateSettingsHandler(propMod.Module.(*proposal_single.DAOProposalSingle)) + }, + func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { + return modboards.NewCreateBoardHandler() + }, + func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { + return modboards.NewDeletePostHandler() + }, + } + + daoCore = dao_core.NewDAOCore(votingModuleFactory, proposalModulesFactories, messageHandlersFactories) + + dao_registry.Register("Test", "Test Dao description", "https://images.unsplash.com/photo-1492571350019-22de08371fd3?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D") +} + +func Render(path string) string { + return "[[board](/r/demo/modboards:" + mainBoardName + ")]\n\n" + daoCore.Render(path) +} + +func VoteJSON(moduleIndex int, proposalID int, voteJSON string) { + // move check in dao core + module := dao_core.GetProposalModule(daoCore, moduleIndex) + if !module.Enabled { + panic("proposal module is not enabled") + } + module.Module.VoteJSON(proposalID, voteJSON) +} + +func Execute(moduleIndex int, proposalID int) { + // move check in dao core + module := dao_core.GetProposalModule(daoCore, moduleIndex) + if !module.Enabled { + panic("proposal module is not enabled") + } + module.Module.Execute(proposalID) +} + +func ProposeJSON(moduleIndex int, proposalJSON string) { + // move check in dao core + module := dao_core.GetProposalModule(daoCore, moduleIndex) + if !module.Enabled { + panic("proposal module is not enabled") + } + module.Module.ProposeJSON(proposalJSON) +} + +func getProposalsJSON(moduleIndex int, limit int, startAfter string, reverse bool) string { + // move logic in dao core + module := dao_core.GetProposalModule(daoCore, moduleIndex) + return module.Module.ProposalsJSON(limit, startAfter, reverse) +} diff --git a/packages/utils/gnodao/deploy.ts b/packages/utils/gnodao/deploy.ts index eafbd5bb3e..50cddb26d8 100644 --- a/packages/utils/gnodao/deploy.ts +++ b/packages/utils/gnodao/deploy.ts @@ -46,11 +46,11 @@ const generateDAORealmSource = (networkId: string, conf: GnoDAOConfig) => { votingModuleFactory := func(core dao_interfaces.IDAOCore) dao_interfaces.IVotingModule { groupID = groups.CreateGroup(groupName) ${conf.initialMembers - .map( - (member) => - `groups.AddMember(groupID, "${member.address}", ${member.weight}, "");`, - ) - .join("\n\t")} + .map( + (member) => + `groups.AddMember(groupID, "${member.address}", ${member.weight}, "");`, + ) + .join("\n\t")} return voting_group.NewVotingGroup(groupID) } @@ -59,11 +59,11 @@ const generateDAORealmSource = (networkId: string, conf: GnoDAOConfig) => { proposalModulesFactories := []dao_interfaces.ProposalModuleFactory{ func(core dao_interfaces.IDAOCore) dao_interfaces.IProposalModule { tt := proposal_single.PercentageThresholdPercent(${Math.ceil( - conf.thresholdPercent * 100, - )}) // ${Math.ceil(conf.thresholdPercent * 100) / 100}% + conf.thresholdPercent * 100, + )}) // ${Math.ceil(conf.thresholdPercent * 100) / 100}% tq := proposal_single.PercentageThresholdPercent(${Math.ceil( - conf.quorumPercent * 100, - )}) // ${Math.ceil(conf.quorumPercent * 100) / 100}% + conf.quorumPercent * 100, + )}) // ${Math.ceil(conf.quorumPercent * 100) / 100}% return proposal_single.NewDAOProposalSingle(core, &proposal_single.DAOProposalSingleOpts{ MaxVotingPeriod: time.Second * ${conf.maxVotingPeriodSeconds}, Threshold: &proposal_single.ThresholdThresholdQuorum{ @@ -97,8 +97,8 @@ const generateDAORealmSource = (networkId: string, conf: GnoDAOConfig) => { daoCore = dao_core.NewDAOCore(votingModuleFactory, proposalModulesFactories, messageHandlersFactories) dao_registry.Register(${JSON.stringify(conf.displayName)}, ${JSON.stringify( - conf.description, - )}, ${JSON.stringify(conf.imageURI)}) + conf.description, + )}, ${JSON.stringify(conf.imageURI)}) } func Render(path string) string { @@ -146,6 +146,7 @@ export const adenaDeployGnoDAO = async ( conf: GnoDAOConfig, ) => { const source = generateDAORealmSource(networkId, conf); + console.log("Deploying DAO with source:", source); const pkgPath = `gno.land/r/demo/${conf.name}`; await adenaAddPkg( networkId, From 83d31c8889906fd03c0d84ffd4f56525007714ab Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Mon, 14 Oct 2024 11:42:52 +0200 Subject: [PATCH 05/27] wip: e2e test handle filling all steps in dao creation form --- gno/r/test/gno.mod | 1 - gno/r/test/test.gno | 104 --------------------- packages/networks/gno-dev/index.ts | 9 +- packages/networks/gno-portal/index.ts | 6 +- packages/networks/gno-teritori/index.ts | 6 +- packages/networks/types.ts | 4 +- packages/utils/gno.ts | 1 + packages/utils/gnodao/deploy.ts | 117 +++++++++++++----------- 8 files changed, 81 insertions(+), 167 deletions(-) delete mode 100644 gno/r/test/gno.mod delete mode 100644 gno/r/test/test.gno diff --git a/gno/r/test/gno.mod b/gno/r/test/gno.mod deleted file mode 100644 index d207309536..0000000000 --- a/gno/r/test/gno.mod +++ /dev/null @@ -1 +0,0 @@ -module gno.land/r/teritori/test diff --git a/gno/r/test/test.gno b/gno/r/test/test.gno deleted file mode 100644 index 148773ee73..0000000000 --- a/gno/r/test/test.gno +++ /dev/null @@ -1,104 +0,0 @@ -package test - -import ( - dao_core "gno.land/p/teritori/dao_core" - dao_interfaces "gno.land/p/teritori/dao_interfaces" - proposal_single "gno.land/p/teritori/dao_proposal_single" - voting_group "gno.land/p/teritori/dao_voting_group" - "gno.land/r/teritori/dao_registry" - "gno.land/r/teritori/groups" -) - -var ( - daoCore dao_interfaces.IDAOCore - mainBoardName = "test" - groupName = mainBoardName + "_voting_group" - groupID groups.GroupID -) - -func init() { - modboards.CreateBoard(mainBoardName) - - votingModuleFactory := func(core dao_interfaces.IDAOCore) dao_interfaces.IVotingModule { - groupID = groups.CreateGroup(groupName) - groups.AddMember(groupID, "g16jv3rpz7mkt0gqulxas56se2js7v5vmc6n6e0r", 1, "") - return voting_group.NewVotingGroup(groupID) - } - - // TODO: consider using factories that return multiple modules and handlers - - proposalModulesFactories := []dao_interfaces.ProposalModuleFactory{ - func(core dao_interfaces.IDAOCore) dao_interfaces.IProposalModule { - tt := proposal_single.PercentageThresholdPercent(1500) // 15% - tq := proposal_single.PercentageThresholdPercent(5000) // 50% - return proposal_single.NewDAOProposalSingle(core, &proposal_single.DAOProposalSingleOpts{ - MaxVotingPeriod: 60 * 86400, - Threshold: &proposal_single.ThresholdThresholdQuorum{ - Threshold: &tt, - Quorum: &tq, - }, - }) - }, - } - - messageHandlersFactories := []dao_interfaces.MessageHandlerFactory{ - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return groups.NewAddMemberHandler() - }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return groups.NewDeleteMemberHandler() - }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - // TODO: add a router to support multiple proposal modules - propMod := core.ProposalModules()[0] - return proposal_single.NewUpdateSettingsHandler(propMod.Module.(*proposal_single.DAOProposalSingle)) - }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return modboards.NewCreateBoardHandler() - }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return modboards.NewDeletePostHandler() - }, - } - - daoCore = dao_core.NewDAOCore(votingModuleFactory, proposalModulesFactories, messageHandlersFactories) - - dao_registry.Register("Test", "Test Dao description", "https://images.unsplash.com/photo-1492571350019-22de08371fd3?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D") -} - -func Render(path string) string { - return "[[board](/r/demo/modboards:" + mainBoardName + ")]\n\n" + daoCore.Render(path) -} - -func VoteJSON(moduleIndex int, proposalID int, voteJSON string) { - // move check in dao core - module := dao_core.GetProposalModule(daoCore, moduleIndex) - if !module.Enabled { - panic("proposal module is not enabled") - } - module.Module.VoteJSON(proposalID, voteJSON) -} - -func Execute(moduleIndex int, proposalID int) { - // move check in dao core - module := dao_core.GetProposalModule(daoCore, moduleIndex) - if !module.Enabled { - panic("proposal module is not enabled") - } - module.Module.Execute(proposalID) -} - -func ProposeJSON(moduleIndex int, proposalJSON string) { - // move check in dao core - module := dao_core.GetProposalModule(daoCore, moduleIndex) - if !module.Enabled { - panic("proposal module is not enabled") - } - module.Module.ProposeJSON(proposalJSON) -} - -func getProposalsJSON(moduleIndex int, limit int, startAfter string, reverse bool) string { - // move logic in dao core - module := dao_core.GetProposalModule(daoCore, moduleIndex) - return module.Module.ProposalsJSON(limit, startAfter, reverse) -} diff --git a/packages/networks/gno-dev/index.ts b/packages/networks/gno-dev/index.ts index b7349f907f..e1e272d54c 100644 --- a/packages/networks/gno-dev/index.ts +++ b/packages/networks/gno-dev/index.ts @@ -1,5 +1,5 @@ -import { gnoCurrencies } from "./currencies"; import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; +import { gnoCurrencies } from "./currencies"; export const gnoDevNetwork: GnoNetworkInfo = { id: "gno-dev", @@ -42,14 +42,15 @@ export const gnoDevNetwork: GnoNetworkInfo = { socialFeedsPkgPath: "gno.land/r/teritori/social_feeds", socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao", nameServiceContractAddress: "gno.land/r/demo/users", - modboardsPkgPath: "gno.land/r/teritori/modboards", - groupsPkgPath: "gno.land/r/teritori/groups", + // modboardsPkgPath: "gno.land/r/teritori/modboards", + // groupsPkgPath: "gno.land/r/teritori/groups", votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group", daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single", profilePkgPath: "gno.land/r/demo/profile", - daoInterfacesPkgPath: "gno.land/p/teritori/dao_interfaces", daoCorePkgPath: "gno.land/p/teritori/dao_core", + daoUtilsPkgPath: "gno.land/p/teritori/dao_utils", + toriPkgPath: "gno.land/r/teritori/tori", nameServiceDefaultImage: "ipfs://bafkreignptjimiu7wuux6mk6uh4hb4odb6ff62ny4bvdokrhes7g67huse", gnowebURL: "http://127.0.0.1:8888", diff --git a/packages/networks/gno-portal/index.ts b/packages/networks/gno-portal/index.ts index 5409578d13..4955ed1e44 100644 --- a/packages/networks/gno-portal/index.ts +++ b/packages/networks/gno-portal/index.ts @@ -1,5 +1,5 @@ -import { gnoCurrencies } from "./currencies"; import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; +import { gnoCurrencies } from "./currencies"; export const gnoPortalNetwork: GnoNetworkInfo = { id: "gno-portal", @@ -33,11 +33,13 @@ export const gnoPortalNetwork: GnoNetworkInfo = { socialFeedsPkgPath: "gno.land/r/teritori/social_feeds", socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao", // modboardsPkgPath: "gno.land/r/teritori/modboards_v4", - groupsPkgPath: "gno.land/r/teritori/groups", + // groupsPkgPath: "gno.land/r/teritori/groups", votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group", daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single", daoInterfacesPkgPath: "gno.land/p/teritori/dao_interfaces", daoCorePkgPath: "gno.land/p/teritori/dao_core", + daoUtilsPkgPath: "gno.land/r/teritori/dao_utils", + toriPkgPath: "gno.land/r/teritori/tori", profilePkgPath: "gno.land/r/demo/profile", txIndexerURL: "https://indexer.portal-loop.gno.testnet.teritori.com", }; diff --git a/packages/networks/gno-teritori/index.ts b/packages/networks/gno-teritori/index.ts index ff21695a40..6a13ce4539 100644 --- a/packages/networks/gno-teritori/index.ts +++ b/packages/networks/gno-teritori/index.ts @@ -1,5 +1,5 @@ -import { gnoCurrencies } from "./currencies"; import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; +import { gnoCurrencies } from "./currencies"; export const gnoTeritoriNetwork: GnoNetworkInfo = { id: "gno-teritori", @@ -37,12 +37,12 @@ export const gnoTeritoriNetwork: GnoNetworkInfo = { daoRegistryPkgPath: "gno.land/r/teritori/dao_registry_v4", socialFeedsPkgPath: "gno.land/r/teritori/social_feeds_v4", socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao_v2", - modboardsPkgPath: "gno.land/r/teritori/modboards_v4", - groupsPkgPath: "gno.land/r/teritori/groups_v4", votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group_v2", daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single_v4", daoInterfacesPkgPath: "gno.land/p/teritori/dao_interfaces_v5", + daoUtilsPkgPath: "", //TODO: fill with the correct path daoCorePkgPath: "gno.land/p/teritori/dao_core_v4", + toriPkgPath: "", //TODO: fill with the correct path gnowebURL: "https://testnet.gno.teritori.com", faucetURL: "https://testnet.gno.teritori.com:5050/?toaddr=$addr", }; diff --git a/packages/networks/types.ts b/packages/networks/types.ts index a591787572..d442d3596d 100644 --- a/packages/networks/types.ts +++ b/packages/networks/types.ts @@ -109,14 +109,14 @@ export type GnoNetworkInfo = NetworkInfoBase & { nameServiceDefaultImage: string; gnowebURL: string; daoRegistryPkgPath?: string; - modboardsPkgPath?: string; socialFeedsPkgPath?: string; socialFeedsDAOPkgPath?: string; votingGroupPkgPath?: string; daoProposalSinglePkgPath?: string; daoInterfacesPkgPath?: string; daoCorePkgPath?: string; - groupsPkgPath?: string; + daoUtilsPkgPath?: string; + toriPkgPath?: string; profilePkgPath?: string; faucetURL?: string; txIndexerURL?: string; diff --git a/packages/utils/gno.ts b/packages/utils/gno.ts index 42ff6dfdd6..a3d7e0e1e8 100644 --- a/packages/utils/gno.ts +++ b/packages/utils/gno.ts @@ -35,6 +35,7 @@ export const adenaDoContract = async ( gasWanted: opts?.gasWanted === undefined ? 10000000 : opts.gasWanted, memo: opts?.memo, }; + console.log(JSON.stringify(req)); const res = await adena.DoContract(req); if (res.status === "failure") { throw new Error(res.message); diff --git a/packages/utils/gnodao/deploy.ts b/packages/utils/gnodao/deploy.ts index 50cddb26d8..b4adc8e268 100644 --- a/packages/utils/gnodao/deploy.ts +++ b/packages/utils/gnodao/deploy.ts @@ -17,43 +17,50 @@ interface GnoDAOConfig { imageURI: string; } +const generateFakeSource = (networkId: string, conf: GnoDAOConfig) => { + const network = mustGetGnoNetwork(networkId); + return `package ${conf.name} + func Render(path string) string { + return "Hello, World!" +} +`; +} + const generateDAORealmSource = (networkId: string, conf: GnoDAOConfig) => { const network = mustGetGnoNetwork(networkId); return `package ${conf.name} import ( + "std" "time" dao_core "${network.daoCorePkgPath}" dao_interfaces "${network.daoInterfacesPkgPath}" proposal_single "${network.daoProposalSinglePkgPath}" + "${network.daoUtilsPkgPath}" voting_group "${network.votingGroupPkgPath}" - "${network.groupsPkgPath}" - modboards "${network.modboardsPkgPath}" "${network.daoRegistryPkgPath}" + "${network.toriPkgPath}" ) - var ( - daoCore dao_interfaces.IDAOCore - mainBoardName = "${conf.name}" - groupName = mainBoardName + "_voting_group" - groupID groups.GroupID - ) - - func init() { - modboards.CreateBoard(mainBoardName) - - votingModuleFactory := func(core dao_interfaces.IDAOCore) dao_interfaces.IVotingModule { - groupID = groups.CreateGroup(groupName) +var ( + daoCore dao_interfaces.IDAOCore + group *voting_group.VotingGroup + registered bool +) + +func init() { + votingModuleFactory := func(core dao_interfaces.IDAOCore) dao_interfaces.IVotingModule { + group = voting_group.NewVotingGroup() ${conf.initialMembers .map( (member) => - `groups.AddMember(groupID, "${member.address}", ${member.weight}, "");`, + `group.SetMemberPower("${member.address}", ${member.weight});`, ) .join("\n\t")} - return voting_group.NewVotingGroup(groupID) - } - + return group + } + // TODO: consider using factories that return multiple modules and handlers proposalModulesFactories := []dao_interfaces.ProposalModuleFactory{ @@ -65,7 +72,7 @@ const generateDAORealmSource = (networkId: string, conf: GnoDAOConfig) => { conf.quorumPercent * 100, )}) // ${Math.ceil(conf.quorumPercent * 100) / 100}% return proposal_single.NewDAOProposalSingle(core, &proposal_single.DAOProposalSingleOpts{ - MaxVotingPeriod: time.Second * ${conf.maxVotingPeriodSeconds}, + MaxVotingPeriod: dao_utils.DurationTime(time.Second * ${conf.maxVotingPeriodSeconds}), Threshold: &proposal_single.ThresholdThresholdQuorum{ Threshold: &tt, Quorum: &tq, @@ -74,35 +81,33 @@ const generateDAORealmSource = (networkId: string, conf: GnoDAOConfig) => { }, } - messageHandlersFactories := []dao_interfaces.MessageHandlerFactory{ - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return groups.NewAddMemberHandler() - }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return groups.NewDeleteMemberHandler() - }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - // TODO: add a router to support multiple proposal modules - propMod := core.ProposalModules()[0] - return proposal_single.NewUpdateSettingsHandler(propMod.Module.(*proposal_single.DAOProposalSingle)) - }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return modboards.NewCreateBoardHandler() - }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return modboards.NewDeletePostHandler() - }, - } - - daoCore = dao_core.NewDAOCore(votingModuleFactory, proposalModulesFactories, messageHandlersFactories) + messageHandlersFactories := []dao_interfaces.MessageHandlerFactory{ + func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { + return group.UpdateMembersHandler() + }, + func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { + // TODO: add a router to support multiple proposal modules + propMod := core.ProposalModules()[0] + return proposal_single.NewUpdateSettingsHandler(propMod.Module.(*proposal_single.DAOProposalSingle)) + }, + func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { + return tori.NewMintToriHandler() + }, + func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { + return tori.NewBurnToriHandler() + }, + func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { + return tori.NewChangeAdminHandler() + }, + } - dao_registry.Register(${JSON.stringify(conf.displayName)}, ${JSON.stringify( - conf.description, - )}, ${JSON.stringify(conf.imageURI)}) + daoCore = dao_core.NewDAOCore(votingModuleFactory, proposalModulesFactories, messageHandlersFactories) + + dao_registry.Register(func() dao_interfaces.IDAOCore { return daoCore }, "${conf.displayName}", "${conf.description}", "${conf.imageURI}") } func Render(path string) string { - return "[[board](/r/demo/modboards:" + mainBoardName + ")]\\n\\n" + daoCore.Render(path) + return daoCore.Render(path) } func VoteJSON(moduleIndex int, proposalID int, voteJSON string) { @@ -111,32 +116,41 @@ const generateDAORealmSource = (networkId: string, conf: GnoDAOConfig) => { if !module.Enabled { panic("proposal module is not enabled") } + module.Module.VoteJSON(proposalID, voteJSON) } - + func Execute(moduleIndex int, proposalID int) { // move check in dao core module := dao_core.GetProposalModule(daoCore, moduleIndex) if !module.Enabled { panic("proposal module is not enabled") } + module.Module.Execute(proposalID) } - - func ProposeJSON(moduleIndex int, proposalJSON string) { + + func ProposeJSON(moduleIndex int, proposalJSON string) int { // move check in dao core module := dao_core.GetProposalModule(daoCore, moduleIndex) if !module.Enabled { panic("proposal module is not enabled") } - module.Module.ProposeJSON(proposalJSON) + + return module.Module.ProposeJSON(proposalJSON) } - + func getProposalsJSON(moduleIndex int, limit int, startAfter string, reverse bool) string { // move logic in dao core module := dao_core.GetProposalModule(daoCore, moduleIndex) return module.Module.ProposalsJSON(limit, startAfter, reverse) } + + func getProposalJSON(moduleIndex int, proposalIndex int) string { + // move logic in dao core + module := dao_core.GetProposalModule(daoCore, moduleIndex) + return module.Module.ProposalJSON(proposalIndex) + } `; }; @@ -145,9 +159,10 @@ export const adenaDeployGnoDAO = async ( creator: string, conf: GnoDAOConfig, ) => { - const source = generateDAORealmSource(networkId, conf); + const source = generateFakeSource(networkId, conf); console.log("Deploying DAO with source:", source); - const pkgPath = `gno.land/r/demo/${conf.name}`; + const pkgPath = `gno.land/r/teritori/${conf.name}`; + console.log("Deploying DAO with pkgPath:", pkgPath); await adenaAddPkg( networkId, { From f5a55e2ac2993da742d0233619ef172b51f6261d Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Mon, 14 Oct 2024 13:32:48 +0200 Subject: [PATCH 06/27] wip: e2e test handle filling all steps in dao creation form --- packages/utils/gnodao/deploy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/gnodao/deploy.ts b/packages/utils/gnodao/deploy.ts index b4adc8e268..c3871d294d 100644 --- a/packages/utils/gnodao/deploy.ts +++ b/packages/utils/gnodao/deploy.ts @@ -161,7 +161,7 @@ export const adenaDeployGnoDAO = async ( ) => { const source = generateFakeSource(networkId, conf); console.log("Deploying DAO with source:", source); - const pkgPath = `gno.land/r/teritori/${conf.name}`; + const pkgPath = `gno.land/r/${creator}/${conf.name}`; console.log("Deploying DAO with pkgPath:", pkgPath); await adenaAddPkg( networkId, From a0207523aca0475998262bd1b237b34c966c5400 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Tue, 15 Oct 2024 13:52:01 +0200 Subject: [PATCH 07/27] fix: remove unused std from gno dao realm generation --- packages/utils/gno.ts | 10 +++++----- packages/utils/gnodao/deploy.ts | 20 ++++---------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/packages/utils/gno.ts b/packages/utils/gno.ts index a3d7e0e1e8..76dbddd9d2 100644 --- a/packages/utils/gno.ts +++ b/packages/utils/gno.ts @@ -79,14 +79,14 @@ export const adenaVMCall = async ( }; interface Package { - Name: string; - Path: string; - Files: PackageFile[]; + name: string; + path: string; + files: PackageFile[]; } interface PackageFile { - Name: string; - Body: string; + name: string; + body: string; } interface VmAddPackage { diff --git a/packages/utils/gnodao/deploy.ts b/packages/utils/gnodao/deploy.ts index c3871d294d..a786726702 100644 --- a/packages/utils/gnodao/deploy.ts +++ b/packages/utils/gnodao/deploy.ts @@ -17,21 +17,11 @@ interface GnoDAOConfig { imageURI: string; } -const generateFakeSource = (networkId: string, conf: GnoDAOConfig) => { - const network = mustGetGnoNetwork(networkId); - return `package ${conf.name} - func Render(path string) string { - return "Hello, World!" -} -`; -} - const generateDAORealmSource = (networkId: string, conf: GnoDAOConfig) => { const network = mustGetGnoNetwork(networkId); return `package ${conf.name} import ( - "std" "time" dao_core "${network.daoCorePkgPath}" @@ -159,19 +149,17 @@ export const adenaDeployGnoDAO = async ( creator: string, conf: GnoDAOConfig, ) => { - const source = generateFakeSource(networkId, conf); - console.log("Deploying DAO with source:", source); + const source = generateDAORealmSource(networkId, conf); const pkgPath = `gno.land/r/${creator}/${conf.name}`; - console.log("Deploying DAO with pkgPath:", pkgPath); await adenaAddPkg( networkId, { creator, deposit: "1ugnot", package: { - Name: conf.name, - Path: pkgPath, - Files: [{ Name: `${conf.name}.gno`, Body: source }], + name: conf.name, + path: pkgPath, + files: [{ name: `${conf.name}.gno`, body: source }], }, }, { gasWanted: 10000000 }, From 7c600182bc3b58eab7cf0760925b5d0a9f92ebb6 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Tue, 15 Oct 2024 16:25:33 +0200 Subject: [PATCH 08/27] feat: add adena mock deploy pkg function --- cypress/e2e/dao-creation.cy.ts | 25 ++++----- cypress/e2e/projects-contractor.cy.ts | 1 - .../context/WalletsProvider/gnotest/index.tsx | 53 +++++++++++++++---- .../components/CreateDAOSection.tsx | 1 + .../components/MemberSettingsSection.tsx | 1 + 5 files changed, 53 insertions(+), 28 deletions(-) diff --git a/cypress/e2e/dao-creation.cy.ts b/cypress/e2e/dao-creation.cy.ts index 5f6c264ec0..dabf875107 100644 --- a/cypress/e2e/dao-creation.cy.ts +++ b/cypress/e2e/dao-creation.cy.ts @@ -1,41 +1,34 @@ +import { connectWallet, resetChain } from "./lib"; + describe("Create a dao flow", () => { it("works", () => { - cy.request("http://127.0.0.1:8888/reset"); + + resetChain(); cy.visit("http://localhost:8081/orgs?network=gno-dev", { timeout: 300000, }); + connectWallet(); + const daoName = "Test Dao"; const handle = "testdao"; const url = "https://images.unsplash.com/photo-1492571350019-22de08371fd3?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"; const description = "Test Dao description"; - const memberAddress = "g1nyz430dsujj56ygllcaujkzagz54v0l6yusspy"; cy.contains("Create Dao").click(); - cy.get("input[plac eholder='Type organization\\'s name here']").type( + cy.get("input[placeholder='Type organization\\'s name here']").type( daoName, ); cy.get("input[placeholder='your_organization']").type(handle); cy.get("input[placeholder='https://example.com/preview.png']").type(url); - // because cy.get("input[placeholder='Type organization\\'s description here']").type(description) doesn't work, i use suggested selector from cypress studio - cy.get( - ":nth-child(5) > [style='flex-direction: row; width: 100%;'] > :nth-child(1) > [style='width: 100%;'] > .r-alignItems-1habvwh > .r-alignItems-1awozwy > .css-view-175oi2r > .css-textinput-11aywtz", - ).type(description); + cy.get('[data-testid="organization-description"]').type(description); cy.contains("Next: Configure voting").click(); cy.contains("Next: Set tokens or members").click(); - - cy.get( - '.r-display-6koalj > :nth-child(1) > .r-WebkitOverflowScrolling-150rngu > .r-padding-1jgu3lx > .r-marginBottom-1ifxtd0 > .r-flex-6wfxan > :nth-child(1) > [style="flex-direction: row; width: 100%;"] > :nth-child(1) > [style="width: 100%;"] > .r-alignItems-1habvwh > .r-flexDirection-18u37iz > [style="flex: 1 1 0%; margin-right: 12px;"] > .css-textinput-11aywtz', - ).type(memberAddress); - - cy.get( - '.r-display-6koalj > :nth-child(1) > .r-alignItems-obd0qt > .r-cursor-1loqt21 > [style="height: 48px; opacity: 1;"] > [style="width: 100%; height: 100%; border-width: 1px; border-color: rgba(0, 0, 0, 0); padding: 0px 20px; align-items: center; justify-content: center;"]', - ).click(); - + cy.get('[data-testid="member-settings-next"]').click(); cy.contains("Confirm & Launch the Organization").click(); }); }); diff --git a/cypress/e2e/projects-contractor.cy.ts b/cypress/e2e/projects-contractor.cy.ts index 564ac9ccc6..df46429003 100644 --- a/cypress/e2e/projects-contractor.cy.ts +++ b/cypress/e2e/projects-contractor.cy.ts @@ -19,7 +19,6 @@ describe("Contractor proposer full flow", () => { cy.contains("Create a Project").click(); connectWallet(); - changeTestUser("bob"); // first step: basic project info cy.get("input[placeholder='Your Grant name']").type(projectName); diff --git a/packages/context/WalletsProvider/gnotest/index.tsx b/packages/context/WalletsProvider/gnotest/index.tsx index 89eb65347c..065329b52b 100644 --- a/packages/context/WalletsProvider/gnotest/index.tsx +++ b/packages/context/WalletsProvider/gnotest/index.tsx @@ -1,10 +1,12 @@ import { GnoJSONRPCProvider, GnoWallet, + MemFile, + MemPackage, MsgSend, decodeTxMessages, } from "@gnolang/gno-js-client"; -import { TxFee, TransactionEndpoint, Tx } from "@gnolang/tm2-js-client"; +import { TransactionEndpoint, Tx, TxFee } from "@gnolang/tm2-js-client"; import Long from "long"; import React from "react"; import { Pressable } from "react-native"; @@ -16,7 +18,7 @@ import { getUserId } from "@/networks"; import { gnoDevNetwork } from "@/networks/gno-dev"; import { setSelectedWalletId } from "@/store/slices/settings"; import { useAppDispatch } from "@/store/store"; -import { RequestDocontractMessage } from "@/utils/gno"; +import { AdenaDoContractMessage, RequestDocontractMessage } from "@/utils/gno"; import { WalletProvider } from "@/utils/walletProvider"; type UseGnotestResult = [true, boolean, Wallet[]] | [false, boolean, undefined]; @@ -268,7 +270,7 @@ const setupAdenaMock = () => { throw new Error("Wallet not connected"); } const msg = req.messages[0]; - if (msg.type !== "/vm.m_call") { + if (msg.type !== "/vm.m_call" && msg.type !== "/vm.m_addpkg") { throw new Error("Unsupported message type: " + msg.type); } const txFee: TxFee = { @@ -283,14 +285,24 @@ const setupAdenaMock = () => { console.log("docontract sendAmount", sendAmount); sendMap.set("ugnot", +sendAmount); } - const res = await state.wallet.callMethod( - msg.value.pkg_path, - msg.value.func, - msg.value.args, - TransactionEndpoint.BROADCAST_TX_COMMIT, - sendMap, - txFee, - ); + let res; + if (msg.type === "/vm.m_call") { + res = await state.wallet.callMethod( + msg.value.pkg_path, + msg.value.func, + msg.value.args, + TransactionEndpoint.BROADCAST_TX_COMMIT, + sendMap, + txFee, + ); + } else { + res = await deployPackage( + state.wallet, + msg, + sendMap, + txFee, + ); + } return { status: "success", data: { @@ -313,6 +325,25 @@ const setupAdenaMock = () => { }; }; + +const deployPackage = async (wallet: GnoWallet, msg: AdenaDoContractMessage, funds: Map | undefined, txFee: TxFee) => { + const files: MemFile[] = msg.value.package.files + + const pkg: MemPackage = { + name: msg.value.package.name, + path: msg.value.package.path, + files: files + } + + const tx = await wallet.deployPackage( + pkg, + TransactionEndpoint.BROADCAST_TX_COMMIT, + funds, + txFee, + ) + return tx; +} + export const useGnotest: () => UseGnotestResult = () => { const { wallet, address } = useGnotestStore(); const wallets: Wallet[] = []; diff --git a/packages/screens/Organizations/components/CreateDAOSection.tsx b/packages/screens/Organizations/components/CreateDAOSection.tsx index 29ef7ca0ca..1ed41a2c15 100644 --- a/packages/screens/Organizations/components/CreateDAOSection.tsx +++ b/packages/screens/Organizations/components/CreateDAOSection.tsx @@ -131,6 +131,7 @@ export const CreateDAOSection: React.FC = ({ // isAsterickSign multiline numberOfLines={3} + testID="organization-description" /> diff --git a/packages/screens/Organizations/components/MemberSettingsSection.tsx b/packages/screens/Organizations/components/MemberSettingsSection.tsx index 03d724349f..6c44dc3d40 100644 --- a/packages/screens/Organizations/components/MemberSettingsSection.tsx +++ b/packages/screens/Organizations/components/MemberSettingsSection.tsx @@ -112,6 +112,7 @@ export const MemberSettingsSection: React.FC = ({ size="M" text={`Next: ${ORGANIZATION_DEPLOYER_STEPS[3]}`} onPress={handleSubmit(onSubmit)} + testID="member-settings-next" /> From e4f4b20f79234b5fd532f09dedbe0f8b953d70e0 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Tue, 15 Oct 2024 16:35:23 +0200 Subject: [PATCH 09/27] fix: finish e2e test organization creation flow on gno --- .../e2e/{dao-creation.cy.ts => organization-creation.cy.ts} | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename cypress/e2e/{dao-creation.cy.ts => organization-creation.cy.ts} (90%) diff --git a/cypress/e2e/dao-creation.cy.ts b/cypress/e2e/organization-creation.cy.ts similarity index 90% rename from cypress/e2e/dao-creation.cy.ts rename to cypress/e2e/organization-creation.cy.ts index dabf875107..cb351aed80 100644 --- a/cypress/e2e/dao-creation.cy.ts +++ b/cypress/e2e/organization-creation.cy.ts @@ -1,6 +1,6 @@ import { connectWallet, resetChain } from "./lib"; -describe("Create a dao flow", () => { +describe("Create an organization flow", () => { it("works", () => { resetChain(); @@ -30,5 +30,7 @@ describe("Create a dao flow", () => { cy.contains("Next: Set tokens or members").click(); cy.get('[data-testid="member-settings-next"]').click(); cy.contains("Confirm & Launch the Organization").click(); + + cy.contains('Get Started', { timeout: 10000 }).should('exist'); }); }); From 21567e5d1d08a75a1845860598ba23b4ed716066 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Tue, 15 Oct 2024 16:38:54 +0200 Subject: [PATCH 10/27] chore: refactor project structure by moving all e2e test files into gno subfolder --- cypress/e2e/{ => gno}/lib.ts | 0 cypress/e2e/{ => gno}/organization-creation.cy.ts | 0 cypress/e2e/{ => gno}/projects-contractor.cy.ts | 0 cypress/e2e/{ => gno}/projects-funder.cy.ts | 0 cypress/e2e/{ => gno}/upp-form.cy.ts | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename cypress/e2e/{ => gno}/lib.ts (100%) rename cypress/e2e/{ => gno}/organization-creation.cy.ts (100%) rename cypress/e2e/{ => gno}/projects-contractor.cy.ts (100%) rename cypress/e2e/{ => gno}/projects-funder.cy.ts (100%) rename cypress/e2e/{ => gno}/upp-form.cy.ts (100%) diff --git a/cypress/e2e/lib.ts b/cypress/e2e/gno/lib.ts similarity index 100% rename from cypress/e2e/lib.ts rename to cypress/e2e/gno/lib.ts diff --git a/cypress/e2e/organization-creation.cy.ts b/cypress/e2e/gno/organization-creation.cy.ts similarity index 100% rename from cypress/e2e/organization-creation.cy.ts rename to cypress/e2e/gno/organization-creation.cy.ts diff --git a/cypress/e2e/projects-contractor.cy.ts b/cypress/e2e/gno/projects-contractor.cy.ts similarity index 100% rename from cypress/e2e/projects-contractor.cy.ts rename to cypress/e2e/gno/projects-contractor.cy.ts diff --git a/cypress/e2e/projects-funder.cy.ts b/cypress/e2e/gno/projects-funder.cy.ts similarity index 100% rename from cypress/e2e/projects-funder.cy.ts rename to cypress/e2e/gno/projects-funder.cy.ts diff --git a/cypress/e2e/upp-form.cy.ts b/cypress/e2e/gno/upp-form.cy.ts similarity index 100% rename from cypress/e2e/upp-form.cy.ts rename to cypress/e2e/gno/upp-form.cy.ts From 9b8a071e763308bc0405493437ad880b414b5160 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Tue, 15 Oct 2024 16:43:43 +0200 Subject: [PATCH 11/27] style: run eslint --- cypress/e2e/gno/organization-creation.cy.ts | 3 +-- .../context/WalletsProvider/gnotest/index.tsx | 25 +++++++++---------- packages/networks/gno-dev/index.ts | 2 +- packages/networks/gno-portal/index.ts | 2 +- packages/networks/gno-teritori/index.ts | 2 +- packages/utils/gnodao/deploy.ts | 18 ++++++------- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/cypress/e2e/gno/organization-creation.cy.ts b/cypress/e2e/gno/organization-creation.cy.ts index cb351aed80..81bc06c404 100644 --- a/cypress/e2e/gno/organization-creation.cy.ts +++ b/cypress/e2e/gno/organization-creation.cy.ts @@ -2,7 +2,6 @@ import { connectWallet, resetChain } from "./lib"; describe("Create an organization flow", () => { it("works", () => { - resetChain(); cy.visit("http://localhost:8081/orgs?network=gno-dev", { @@ -31,6 +30,6 @@ describe("Create an organization flow", () => { cy.get('[data-testid="member-settings-next"]').click(); cy.contains("Confirm & Launch the Organization").click(); - cy.contains('Get Started', { timeout: 10000 }).should('exist'); + cy.contains("Get Started", { timeout: 10000 }).should("exist"); }); }); diff --git a/packages/context/WalletsProvider/gnotest/index.tsx b/packages/context/WalletsProvider/gnotest/index.tsx index 065329b52b..fcf2799057 100644 --- a/packages/context/WalletsProvider/gnotest/index.tsx +++ b/packages/context/WalletsProvider/gnotest/index.tsx @@ -296,12 +296,7 @@ const setupAdenaMock = () => { txFee, ); } else { - res = await deployPackage( - state.wallet, - msg, - sendMap, - txFee, - ); + res = await deployPackage(state.wallet, msg, sendMap, txFee); } return { status: "success", @@ -325,24 +320,28 @@ const setupAdenaMock = () => { }; }; - -const deployPackage = async (wallet: GnoWallet, msg: AdenaDoContractMessage, funds: Map | undefined, txFee: TxFee) => { - const files: MemFile[] = msg.value.package.files +const deployPackage = async ( + wallet: GnoWallet, + msg: AdenaDoContractMessage, + funds: Map | undefined, + txFee: TxFee, +) => { + const files: MemFile[] = msg.value.package.files; const pkg: MemPackage = { name: msg.value.package.name, path: msg.value.package.path, - files: files - } + files, + }; const tx = await wallet.deployPackage( pkg, TransactionEndpoint.BROADCAST_TX_COMMIT, funds, txFee, - ) + ); return tx; -} +}; export const useGnotest: () => UseGnotestResult = () => { const { wallet, address } = useGnotestStore(); diff --git a/packages/networks/gno-dev/index.ts b/packages/networks/gno-dev/index.ts index e1e272d54c..ebed57eedc 100644 --- a/packages/networks/gno-dev/index.ts +++ b/packages/networks/gno-dev/index.ts @@ -1,5 +1,5 @@ -import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; import { gnoCurrencies } from "./currencies"; +import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; export const gnoDevNetwork: GnoNetworkInfo = { id: "gno-dev", diff --git a/packages/networks/gno-portal/index.ts b/packages/networks/gno-portal/index.ts index 4955ed1e44..999fbe6289 100644 --- a/packages/networks/gno-portal/index.ts +++ b/packages/networks/gno-portal/index.ts @@ -1,5 +1,5 @@ -import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; import { gnoCurrencies } from "./currencies"; +import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; export const gnoPortalNetwork: GnoNetworkInfo = { id: "gno-portal", diff --git a/packages/networks/gno-teritori/index.ts b/packages/networks/gno-teritori/index.ts index 6a13ce4539..d6d632ea43 100644 --- a/packages/networks/gno-teritori/index.ts +++ b/packages/networks/gno-teritori/index.ts @@ -1,5 +1,5 @@ -import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; import { gnoCurrencies } from "./currencies"; +import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; export const gnoTeritoriNetwork: GnoNetworkInfo = { id: "gno-teritori", diff --git a/packages/utils/gnodao/deploy.ts b/packages/utils/gnodao/deploy.ts index a786726702..296c086fe2 100644 --- a/packages/utils/gnodao/deploy.ts +++ b/packages/utils/gnodao/deploy.ts @@ -43,11 +43,11 @@ func init() { votingModuleFactory := func(core dao_interfaces.IDAOCore) dao_interfaces.IVotingModule { group = voting_group.NewVotingGroup() ${conf.initialMembers - .map( - (member) => - `group.SetMemberPower("${member.address}", ${member.weight});`, - ) - .join("\n\t")} + .map( + (member) => + `group.SetMemberPower("${member.address}", ${member.weight});`, + ) + .join("\n\t")} return group } @@ -56,11 +56,11 @@ func init() { proposalModulesFactories := []dao_interfaces.ProposalModuleFactory{ func(core dao_interfaces.IDAOCore) dao_interfaces.IProposalModule { tt := proposal_single.PercentageThresholdPercent(${Math.ceil( - conf.thresholdPercent * 100, - )}) // ${Math.ceil(conf.thresholdPercent * 100) / 100}% + conf.thresholdPercent * 100, + )}) // ${Math.ceil(conf.thresholdPercent * 100) / 100}% tq := proposal_single.PercentageThresholdPercent(${Math.ceil( - conf.quorumPercent * 100, - )}) // ${Math.ceil(conf.quorumPercent * 100) / 100}% + conf.quorumPercent * 100, + )}) // ${Math.ceil(conf.quorumPercent * 100) / 100}% return proposal_single.NewDAOProposalSingle(core, &proposal_single.DAOProposalSingleOpts{ MaxVotingPeriod: dao_utils.DurationTime(time.Second * ${conf.maxVotingPeriodSeconds}), Threshold: &proposal_single.ThresholdThresholdQuorum{ From 03f1e7c58212bf88a61c0678edd9c97d5116078d Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Tue, 15 Oct 2024 16:44:41 +0200 Subject: [PATCH 12/27] revert: useless modification on e2e test --- cypress/e2e/gno/projects-contractor.cy.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/cypress/e2e/gno/projects-contractor.cy.ts b/cypress/e2e/gno/projects-contractor.cy.ts index df46429003..564ac9ccc6 100644 --- a/cypress/e2e/gno/projects-contractor.cy.ts +++ b/cypress/e2e/gno/projects-contractor.cy.ts @@ -19,6 +19,7 @@ describe("Contractor proposer full flow", () => { cy.contains("Create a Project").click(); connectWallet(); + changeTestUser("bob"); // first step: basic project info cy.get("input[placeholder='Your Grant name']").type(projectName); From cdc95c352ba7b3fbfeb1a02c70ece05a6dfed70b Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Tue, 15 Oct 2024 17:05:36 +0200 Subject: [PATCH 13/27] fix: delete useless pkg comment --- packages/networks/gno-dev/index.ts | 4 +--- packages/networks/gno-portal/index.ts | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/networks/gno-dev/index.ts b/packages/networks/gno-dev/index.ts index ebed57eedc..f3b721df45 100644 --- a/packages/networks/gno-dev/index.ts +++ b/packages/networks/gno-dev/index.ts @@ -1,5 +1,5 @@ -import { gnoCurrencies } from "./currencies"; import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; +import { gnoCurrencies } from "./currencies"; export const gnoDevNetwork: GnoNetworkInfo = { id: "gno-dev", @@ -42,8 +42,6 @@ export const gnoDevNetwork: GnoNetworkInfo = { socialFeedsPkgPath: "gno.land/r/teritori/social_feeds", socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao", nameServiceContractAddress: "gno.land/r/demo/users", - // modboardsPkgPath: "gno.land/r/teritori/modboards", - // groupsPkgPath: "gno.land/r/teritori/groups", votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group", daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single", profilePkgPath: "gno.land/r/demo/profile", diff --git a/packages/networks/gno-portal/index.ts b/packages/networks/gno-portal/index.ts index 999fbe6289..a18f697825 100644 --- a/packages/networks/gno-portal/index.ts +++ b/packages/networks/gno-portal/index.ts @@ -1,5 +1,5 @@ -import { gnoCurrencies } from "./currencies"; import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; +import { gnoCurrencies } from "./currencies"; export const gnoPortalNetwork: GnoNetworkInfo = { id: "gno-portal", @@ -32,8 +32,6 @@ export const gnoPortalNetwork: GnoNetworkInfo = { daoRegistryPkgPath: "gno.land/r/teritori/dao_registry", socialFeedsPkgPath: "gno.land/r/teritori/social_feeds", socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao", - // modboardsPkgPath: "gno.land/r/teritori/modboards_v4", - // groupsPkgPath: "gno.land/r/teritori/groups", votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group", daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single", daoInterfacesPkgPath: "gno.land/p/teritori/dao_interfaces", From c0eb78c67d413cad983fd3571e1948127ea3a3fc Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Tue, 15 Oct 2024 17:08:41 +0200 Subject: [PATCH 14/27] fix: run lint on networks files --- packages/networks/gno-dev/index.ts | 2 +- packages/networks/gno-portal/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/networks/gno-dev/index.ts b/packages/networks/gno-dev/index.ts index f3b721df45..e904112f49 100644 --- a/packages/networks/gno-dev/index.ts +++ b/packages/networks/gno-dev/index.ts @@ -1,5 +1,5 @@ -import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; import { gnoCurrencies } from "./currencies"; +import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; export const gnoDevNetwork: GnoNetworkInfo = { id: "gno-dev", diff --git a/packages/networks/gno-portal/index.ts b/packages/networks/gno-portal/index.ts index a18f697825..040c90fe9b 100644 --- a/packages/networks/gno-portal/index.ts +++ b/packages/networks/gno-portal/index.ts @@ -1,5 +1,5 @@ -import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; import { gnoCurrencies } from "./currencies"; +import { GnoNetworkInfo, NetworkFeature, NetworkKind } from "../types"; export const gnoPortalNetwork: GnoNetworkInfo = { id: "gno-portal", From c3516ce1dc8de6e3265ae560a9edcac4732b0fb3 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Wed, 16 Oct 2024 13:15:35 +0200 Subject: [PATCH 15/27] fix: delete useless console.log --- packages/utils/gno.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/utils/gno.ts b/packages/utils/gno.ts index 76dbddd9d2..7eeff0258a 100644 --- a/packages/utils/gno.ts +++ b/packages/utils/gno.ts @@ -35,7 +35,6 @@ export const adenaDoContract = async ( gasWanted: opts?.gasWanted === undefined ? 10000000 : opts.gasWanted, memo: opts?.memo, }; - console.log(JSON.stringify(req)); const res = await adena.DoContract(req); if (res.status === "failure") { throw new Error(res.message); From dcd664e8cf03479099b0b011fecbcd813fbf9851 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Wed, 16 Oct 2024 13:38:54 +0200 Subject: [PATCH 16/27] feat: use enum to handle adena type message value --- .../socialFeed/SocialActions/FlagModal.tsx | 9 ++++++--- .../socialFeed/SocialActions/TipModal.tsx | 9 ++++++--- .../socialFeed/modals/FlagConfirmModal.tsx | 7 +++++-- .../components/user/modals/EditProfileModal.tsx | 13 +++++++++---- packages/context/WalletsProvider/gnotest/index.tsx | 13 ++++++++++--- packages/hooks/feed/useFeedPosting.ts | 8 ++++---- packages/hooks/feed/useSocialReactions.ts | 4 ++-- packages/utils/gno.ts | 9 +++++++-- 8 files changed, 49 insertions(+), 23 deletions(-) diff --git a/packages/components/socialFeed/SocialActions/FlagModal.tsx b/packages/components/socialFeed/SocialActions/FlagModal.tsx index 9c3d46e4c9..128a690116 100644 --- a/packages/components/socialFeed/SocialActions/FlagModal.tsx +++ b/packages/components/socialFeed/SocialActions/FlagModal.tsx @@ -6,8 +6,11 @@ import { useSelectedNetworkInfo } from "../../../hooks/useSelectedNetwork"; import useSelectedWallet from "../../../hooks/useSelectedWallet"; import { mustGetGnoNetwork } from "../../../networks"; import { TERITORI_FEED_ID } from "../../../utils/feed/constants"; -import { adenaDoContract } from "../../../utils/gno"; -import { neutral77, neutral33 } from "../../../utils/style/colors"; +import { + adenaDoContract, + AdenaDoContractMessageType, +} from "../../../utils/gno"; +import { neutral33, neutral77 } from "../../../utils/style/colors"; import { fontSemibold14, fontSemibold16 } from "../../../utils/style/fonts"; import { BrandText } from "../../BrandText"; import FlexRow from "../../FlexRow"; @@ -53,7 +56,7 @@ export const FlagModal: React.FC = ({ try { await adenaDoContract( selectedNetworkId || "", - [{ type: "/vm.m_call", value: vmCall }], + [{ type: AdenaDoContractMessageType.CALL, value: vmCall }], { gasWanted: 2_000_000, }, diff --git a/packages/components/socialFeed/SocialActions/TipModal.tsx b/packages/components/socialFeed/SocialActions/TipModal.tsx index e359b675cf..39f2d14bea 100644 --- a/packages/components/socialFeed/SocialActions/TipModal.tsx +++ b/packages/components/socialFeed/SocialActions/TipModal.tsx @@ -11,14 +11,17 @@ import { useBalances } from "../../../hooks/useBalances"; import { useSelectedNetworkInfo } from "../../../hooks/useSelectedNetwork"; import useSelectedWallet from "../../../hooks/useSelectedWallet"; import { - NetworkKind, getStakingCurrency, keplrCurrencyFromNativeCurrencyInfo, + NetworkKind, } from "../../../networks"; import { prettyPrice } from "../../../utils/coins"; import { defaultSocialFeedFee } from "../../../utils/fee"; import { TERITORI_FEED_ID } from "../../../utils/feed/constants"; -import { adenaDoContract } from "../../../utils/gno"; +import { + adenaDoContract, + AdenaDoContractMessageType, +} from "../../../utils/gno"; import { neutral77, primaryColor } from "../../../utils/style/colors"; import { fontSemibold13, fontSemibold14 } from "../../../utils/style/fonts"; import { BrandText } from "../../BrandText"; @@ -95,7 +98,7 @@ export const TipModal: React.FC<{ try { await adenaDoContract( selectedNetworkId || "", - [{ type: "/vm.m_call", value: vmCall }], + [{ type: AdenaDoContractMessageType.CALL, value: vmCall }], { gasWanted: 1_000_000, }, diff --git a/packages/components/socialFeed/modals/FlagConfirmModal.tsx b/packages/components/socialFeed/modals/FlagConfirmModal.tsx index 230d0680bc..5a6d576825 100644 --- a/packages/components/socialFeed/modals/FlagConfirmModal.tsx +++ b/packages/components/socialFeed/modals/FlagConfirmModal.tsx @@ -7,7 +7,10 @@ import { useFeedbacks } from "../../../context/FeedbacksProvider"; import { useSelectedNetworkId } from "../../../hooks/useSelectedNetwork"; import useSelectedWallet from "../../../hooks/useSelectedWallet"; import { mustGetGnoNetwork } from "../../../networks"; -import { adenaDoContract } from "../../../utils/gno"; +import { + adenaDoContract, + AdenaDoContractMessageType, +} from "../../../utils/gno"; import { GnoDAOVoteRequest } from "../../../utils/gnodao/messages"; import { neutral77 } from "../../../utils/style/colors"; import { @@ -74,7 +77,7 @@ export const FlagConfirmModal: React.FC = ({ const txHash = await adenaDoContract( selectedNetworkId, - [{ type: "/vm.m_call", value: vmCall }], + [{ type: AdenaDoContractMessageType.CALL, value: vmCall }], { gasWanted: 2_000_000, }, diff --git a/packages/components/user/modals/EditProfileModal.tsx b/packages/components/user/modals/EditProfileModal.tsx index 8c838d8bcb..3b5fa3eae4 100644 --- a/packages/components/user/modals/EditProfileModal.tsx +++ b/packages/components/user/modals/EditProfileModal.tsx @@ -6,8 +6,8 @@ import React, { useMemo } from "react"; import { View } from "react-native"; import { - ExecuteMsg as TNSExecuteMsg, Metadata, + ExecuteMsg as TNSExecuteMsg, } from "../../../contracts-clients/teritori-name-service/TeritoriNameService.types"; import { EditProfileForm } from "../forms/EditProfileForm"; import { TNSModalCommonProps } from "../types"; @@ -22,7 +22,12 @@ import { useNSUserInfo } from "@/hooks/useNSUserInfo"; import { useRunOrProposeTransaction } from "@/hooks/useRunOrProposeTransaction"; import useSelectedWallet from "@/hooks/useSelectedWallet"; import { getNetwork, NetworkKind, UserKind } from "@/networks"; -import { adenaDoContract, AdenaDoContractMessage, VmCall } from "@/utils/gno"; +import { + adenaDoContract, + AdenaDoContractMessage, + AdenaDoContractMessageType, + VmCall, +} from "@/utils/gno"; import { neutral17, neutral77 } from "@/utils/style/colors"; import { fontMedium16 } from "@/utils/style/fonts"; import { EMPTY_PROFILE, ProfileData } from "@/utils/upp"; @@ -183,7 +188,7 @@ export const EditProfileModal: React.FC = ({ func: "Register", args: ["", usernameValue, ""], }; - msgs.push({ type: "/vm.m_call", value: vmCall }); + msgs.push({ type: AdenaDoContractMessageType.CALL, value: vmCall }); } // FIXME: the contract supports only update data one by one @@ -242,7 +247,7 @@ export const EditProfileModal: React.FC = ({ args: [field, val], }; - msgs.push({ type: "/vm.m_call", value: vmCall }); + msgs.push({ type: AdenaDoContractMessageType.CALL, value: vmCall }); } if (msgs.length === 0) { diff --git a/packages/context/WalletsProvider/gnotest/index.tsx b/packages/context/WalletsProvider/gnotest/index.tsx index fcf2799057..04ebacd001 100644 --- a/packages/context/WalletsProvider/gnotest/index.tsx +++ b/packages/context/WalletsProvider/gnotest/index.tsx @@ -18,7 +18,11 @@ import { getUserId } from "@/networks"; import { gnoDevNetwork } from "@/networks/gno-dev"; import { setSelectedWalletId } from "@/store/slices/settings"; import { useAppDispatch } from "@/store/store"; -import { AdenaDoContractMessage, RequestDocontractMessage } from "@/utils/gno"; +import { + AdenaDoContractMessage, + AdenaDoContractMessageType, + RequestDocontractMessage, +} from "@/utils/gno"; import { WalletProvider } from "@/utils/walletProvider"; type UseGnotestResult = [true, boolean, Wallet[]] | [false, boolean, undefined]; @@ -270,7 +274,10 @@ const setupAdenaMock = () => { throw new Error("Wallet not connected"); } const msg = req.messages[0]; - if (msg.type !== "/vm.m_call" && msg.type !== "/vm.m_addpkg") { + if ( + msg.type !== AdenaDoContractMessageType.CALL && + msg.type !== AdenaDoContractMessageType.ADD_PKG + ) { throw new Error("Unsupported message type: " + msg.type); } const txFee: TxFee = { @@ -286,7 +293,7 @@ const setupAdenaMock = () => { sendMap.set("ugnot", +sendAmount); } let res; - if (msg.type === "/vm.m_call") { + if (msg.type === AdenaDoContractMessageType.CALL) { res = await state.wallet.callMethod( msg.value.pkg_path, msg.value.func, diff --git a/packages/hooks/feed/useFeedPosting.ts b/packages/hooks/feed/useFeedPosting.ts index 0139bc52ca..40376b9e24 100644 --- a/packages/hooks/feed/useFeedPosting.ts +++ b/packages/hooks/feed/useFeedPosting.ts @@ -13,16 +13,16 @@ import { useBalances } from "../useBalances"; import { signingSocialFeedClient } from "@/client-creators/socialFeedClient"; import { - parseUserId, getStakingCurrency, mustGetCosmosNetwork, NetworkKind, + parseUserId, } from "@/networks"; import { prettyPrice } from "@/utils/coins"; import { defaultSocialFeedFee } from "@/utils/fee"; import { TERITORI_FEED_ID } from "@/utils/feed/constants"; -import { FeedPostingStepId, feedPostingStep } from "@/utils/feed/posting"; -import { adenaDoContract } from "@/utils/gno"; +import { feedPostingStep, FeedPostingStepId } from "@/utils/feed/posting"; +import { adenaDoContract, AdenaDoContractMessageType } from "@/utils/gno"; import { PostCategory } from "@/utils/types/feed"; export const useFeedPosting = ( @@ -124,7 +124,7 @@ export const useFeedPosting = ( const txHash = await adenaDoContract( network.id, - [{ type: "/vm.m_call", value: vmCall }], + [{ type: AdenaDoContractMessageType.CALL, value: vmCall }], { gasWanted: 2_000_000 }, ); diff --git a/packages/hooks/feed/useSocialReactions.ts b/packages/hooks/feed/useSocialReactions.ts index af9ab02ac9..3dc42f3c6b 100644 --- a/packages/hooks/feed/useSocialReactions.ts +++ b/packages/hooks/feed/useSocialReactions.ts @@ -15,7 +15,7 @@ import { NetworkKind, } from "@/networks"; import { TERITORI_FEED_ID } from "@/utils/feed/constants"; -import { adenaDoContract } from "@/utils/gno"; +import { adenaDoContract, AdenaDoContractMessageType } from "@/utils/gno"; import { DISLIKE_EMOJI, getUpdatedReactions, @@ -77,7 +77,7 @@ export const useSocialReactions = ({ }; const txHash = await adenaDoContract( post.networkId, - [{ type: "/vm.m_call", value: vmCall }], + [{ type: AdenaDoContractMessageType.CALL, value: vmCall }], { gasWanted: 2_000_000, }, diff --git a/packages/utils/gno.ts b/packages/utils/gno.ts index 7eeff0258a..de41e6fcda 100644 --- a/packages/utils/gno.ts +++ b/packages/utils/gno.ts @@ -2,6 +2,11 @@ import { GnoJSONRPCProvider } from "@gnolang/gno-js-client"; import { mustGetGnoNetwork } from "../networks"; +export enum AdenaDoContractMessageType { + CALL = "/vm.m_call", + ADD_PKG = "/vm.m_addpkg", +} + export interface AdenaDoContractMessage { type: string; value: { [key in string]: any }; @@ -72,7 +77,7 @@ export const adenaVMCall = async ( ) => { await adenaDoContract( networkId, - [{ type: "/vm.m_call", value: vmCall }], + [{ type: AdenaDoContractMessageType.CALL, value: vmCall }], opts, ); }; @@ -101,7 +106,7 @@ export const adenaAddPkg = async ( ) => { await adenaDoContract( networkId, - [{ type: "/vm.m_addpkg", value: vmAddPackage }], + [{ type: AdenaDoContractMessageType.ADD_PKG, value: vmAddPackage }], { ...opts, }, From 55176c8fa720c0abb75c25e33e4ef9c55ab797b6 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Tue, 22 Oct 2024 14:29:33 +0200 Subject: [PATCH 17/27] fix: delete mint & burn tori token for common dao --- packages/utils/gnodao/deploy.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/utils/gnodao/deploy.ts b/packages/utils/gnodao/deploy.ts index 296c086fe2..868e75ed28 100644 --- a/packages/utils/gnodao/deploy.ts +++ b/packages/utils/gnodao/deploy.ts @@ -80,12 +80,6 @@ func init() { propMod := core.ProposalModules()[0] return proposal_single.NewUpdateSettingsHandler(propMod.Module.(*proposal_single.DAOProposalSingle)) }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return tori.NewMintToriHandler() - }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return tori.NewBurnToriHandler() - }, func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { return tori.NewChangeAdminHandler() }, @@ -162,7 +156,7 @@ export const adenaDeployGnoDAO = async ( files: [{ name: `${conf.name}.gno`, body: source }], }, }, - { gasWanted: 10000000 }, + { gasWanted: 20000000 }, ); return pkgPath; }; From b0cf985521253224eb18391d04309a8ab185e743 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Thu, 31 Oct 2024 17:32:50 +0100 Subject: [PATCH 18/27] fix(dao): remove modboard related code --- packages/components/dao/GnoDemo.tsx | 247 +--------------------------- 1 file changed, 2 insertions(+), 245 deletions(-) diff --git a/packages/components/dao/GnoDemo.tsx b/packages/components/dao/GnoDemo.tsx index 4dc94295fb..ecb25c1d3e 100644 --- a/packages/components/dao/GnoDemo.tsx +++ b/packages/components/dao/GnoDemo.tsx @@ -1,5 +1,3 @@ -import { GnoJSONRPCProvider } from "@gnolang/gno-js-client"; -import { useQuery } from "@tanstack/react-query"; import { useState } from "react"; import { View } from "react-native"; @@ -7,17 +5,12 @@ import { useFeedbacks } from "../../context/FeedbacksProvider"; import { useInvalidateDAOProposals } from "../../hooks/dao/useDAOProposals"; import useSelectedWallet from "../../hooks/useSelectedWallet"; import { NetworkKind, parseUserId } from "../../networks"; -import { adenaVMCall, extractGnoNumber } from "../../utils/gno"; +import { adenaVMCall } from "../../utils/gno"; import { GnoDAOUpdateSettings, GnoSingleChoiceProposal, - GnoModboardsDeletePostMessage, - GnoModboardsCreateMessage, - GnoMintToriMessage, } from "../../utils/gnodao/messages"; -import { fontSemibold20 } from "../../utils/style/fonts"; import { modalMarginPadding } from "../../utils/style/modals"; -import { BrandText } from "../BrandText"; import { PrimaryButton } from "../buttons/PrimaryButton"; import { TextInputCustom } from "../inputs/TextInputCustom"; import ModalBase from "../modals/ModalBase"; @@ -40,11 +33,8 @@ export const GnoDemo: React.FC<{ - - - wrapWithFeedback(async () => { @@ -85,239 +75,6 @@ export const GnoDemo: React.FC<{ ); }; -const DeletePost: React.FC<{ daoId: string }> = ({ daoId }) => { - const [network, daoAddress] = parseUserId(daoId); - const wallet = useSelectedWallet(); - const { wrapWithFeedback } = useFeedbacks(); - const addressParts = daoAddress.split("/"); - const [name, setName] = useState( - addressParts.length > 0 ? addressParts[addressParts.length - 1] : "", - ); - const [threadId, setThreadId] = useState("1"); - const [postId, setPostId] = useState("1"); - const [reason, setReason] = useState("Moderated"); - - const { data: flagCount } = useQuery( - ["flagCount", name, threadId, postId], - async () => { - if (network?.kind !== NetworkKind.Gno || !network.modboardsPkgPath) { - return 0; - } - const client = new GnoJSONRPCProvider(network.endpoint); - const boardIdRes = await client.evaluateExpression( - network.modboardsPkgPath, - `GetBoardIDFromName("${name}")`, - ); - const boardIdNum = extractGnoNumber(boardIdRes); - if (!boardIdNum) { - throw new Error(`invalid board id ${boardIdNum}`); - } - return extractGnoNumber( - await client.evaluateExpression( - network.modboardsPkgPath, - `getBoard(${boardIdNum}).flags.GetFlagCount(getFlagID(${threadId}, ${postId}))`, - ), - ); - }, - ); - - if (network?.kind !== NetworkKind.Gno || !wallet) return null; - return ( - - Delete a post - - - - - - - - - - Flagged: {flagCount || 0} time(s) - - { - if (network?.kind !== NetworkKind.Gno || !network.modboardsPkgPath) { - throw new Error("invalid network"); - } - const client = new GnoJSONRPCProvider(network.endpoint); - const boardIdRes = await client.evaluateExpression( - network.modboardsPkgPath, - `GetBoardIDFromName("${name}")`, - ); - console.log(boardIdRes); - const boardIdNum = extractGnoNumber(boardIdRes); - if (!boardIdNum) { - throw new Error(`invalid board id ${boardIdNum}`); - } - const threadIdNum = parseInt(threadId, 10); - const postIdNum = parseInt(postId, 10); - const payload: GnoModboardsDeletePostMessage = { - type: "gno.land/r/teritori/modboards.DeletePost", - payload: { - boardId: boardIdNum, - threadId: threadIdNum, - postId: postIdNum, - reason, - }, - }; - const propReq: GnoSingleChoiceProposal = { - title: threadIdNum === postIdNum ? "Delete thread" : "Delete post", - description: "", - messages: [payload], - }; - await adenaVMCall( - network.id, - { - pkg_path: daoAddress, - func: "ProposeJSON", - caller: wallet.address, - send: "", - args: ["0", JSON.stringify(propReq)], - }, - { gasWanted: 10000000 }, - ); - })} - /> - - ); -}; - -const CreateBoard: React.FC<{ daoId: string }> = ({ daoId }) => { - const [network, daoAddress] = parseUserId(daoId); - const wallet = useSelectedWallet(); - const { wrapWithFeedback } = useFeedbacks(); - const [name, setName] = useState(""); - - if (network?.kind !== NetworkKind.Gno || !wallet) return null; - return ( - - Create a board - - - - { - const payload: GnoModboardsCreateMessage = { - type: "gno.land/r/teritori/modboards.CreateBoard", - payload: { - name, - }, - }; - const propReq: GnoSingleChoiceProposal = { - title: `Create board ${name}`, - description: "", - messages: [payload], - }; - await adenaVMCall( - network.id, - { - pkg_path: daoAddress, - func: "ProposeJSON", - caller: wallet.address, - send: "", - args: ["0", JSON.stringify(propReq)], - }, - { gasWanted: 10000000 }, - ); - })} - /> - - ); -}; - -const MintTori: React.FC<{ daoId: string }> = ({ daoId }) => { - const [network, daoAddress] = parseUserId(daoId); - const wallet = useSelectedWallet(); - const { wrapWithFeedback } = useFeedbacks(); - const [amount, setAmount] = useState("1"); - const [recipient, setRecipient] = useState(""); - - if (network?.kind !== NetworkKind.Gno || !wallet) return null; - return ( - - Mint Tori - - - - - - { - const payload: GnoMintToriMessage = { - type: "gno.land/r/teritori/tori.Mint", - payload: { - amount: parseInt(amount, 10), - address: recipient, - }, - }; - const msg: GnoSingleChoiceProposal = { - title: `Mint ${amount} utori to ${recipient}`, - description: "", - messages: [payload], - }; - await adenaVMCall(network.id, { - pkg_path: daoAddress, - func: "ProposeJSON", - caller: wallet.address, - send: "", - args: ["0", JSON.stringify(msg)], - }); - })} - /> - - ); -}; - const GnoCreateProposal: React.FC<{ daoId: string | undefined }> = ({ daoId, }) => { @@ -376,7 +133,7 @@ const GnoCreateProposal: React.FC<{ daoId: string | undefined }> = ({ { caller: selectedWallet.address, send: "", - pkg_path: daoAddress, + pkg_path: "gno.land/r/" + selectedWallet, func: "ProposeJSON", args: ["0", JSON.stringify(propReq)], }, From ff5bca0cecf63bbc7dd8463dc137c40dac6e02d1 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Thu, 31 Oct 2024 21:56:40 +0100 Subject: [PATCH 19/27] fix(gnovm): remove leftover of tori import --- networks.json | 11 ++++++----- packages/utils/gnodao/deploy.ts | 1 - 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/networks.json b/networks.json index 724d0927fe..80e02260e7 100644 --- a/networks.json +++ b/networks.json @@ -4519,13 +4519,13 @@ "socialFeedsPkgPath": "gno.land/r/teritori/social_feeds", "socialFeedsDAOPkgPath": "gno.land/r/teritori/social_feeds_dao", "nameServiceContractAddress": "gno.land/r/demo/users", - "modboardsPkgPath": "gno.land/r/teritori/modboards", - "groupsPkgPath": "gno.land/r/teritori/groups", "votingGroupPkgPath": "gno.land/p/teritori/dao_voting_group", "daoProposalSinglePkgPath": "gno.land/p/teritori/dao_proposal_single", "profilePkgPath": "gno.land/r/demo/profile", "daoInterfacesPkgPath": "gno.land/p/teritori/dao_interfaces", "daoCorePkgPath": "gno.land/p/teritori/dao_core", + "daoUtilsPkgPath": "gno.land/p/teritori/dao_utils", + "toriPkgPath": "gno.land/r/teritori/tori", "nameServiceDefaultImage": "ipfs://bafkreignptjimiu7wuux6mk6uh4hb4odb6ff62ny4bvdokrhes7g67huse", "gnowebURL": "http://127.0.0.1:8888", "txIndexerURL": "http://127.0.0.1:8546" @@ -4569,11 +4569,12 @@ "daoRegistryPkgPath": "gno.land/r/teritori/dao_registry", "socialFeedsPkgPath": "gno.land/r/teritori/social_feeds", "socialFeedsDAOPkgPath": "gno.land/r/teritori/social_feeds_dao", - "groupsPkgPath": "gno.land/r/teritori/groups", "votingGroupPkgPath": "gno.land/p/teritori/dao_voting_group", "daoProposalSinglePkgPath": "gno.land/p/teritori/dao_proposal_single", "daoInterfacesPkgPath": "gno.land/p/teritori/dao_interfaces", "daoCorePkgPath": "gno.land/p/teritori/dao_core", + "daoUtilsPkgPath": "gno.land/r/teritori/dao_utils", + "toriPkgPath": "gno.land/r/teritori/tori", "profilePkgPath": "gno.land/r/demo/profile", "txIndexerURL": "https://indexer.portal-loop.gno.testnet.teritori.com" }, @@ -4623,12 +4624,12 @@ "daoRegistryPkgPath": "gno.land/r/teritori/dao_registry_v4", "socialFeedsPkgPath": "gno.land/r/teritori/social_feeds_v4", "socialFeedsDAOPkgPath": "gno.land/r/teritori/social_feeds_dao_v2", - "modboardsPkgPath": "gno.land/r/teritori/modboards_v4", - "groupsPkgPath": "gno.land/r/teritori/groups_v4", "votingGroupPkgPath": "gno.land/p/teritori/dao_voting_group_v2", "daoProposalSinglePkgPath": "gno.land/p/teritori/dao_proposal_single_v4", "daoInterfacesPkgPath": "gno.land/p/teritori/dao_interfaces_v5", + "daoUtilsPkgPath": "", "daoCorePkgPath": "gno.land/p/teritori/dao_core_v4", + "toriPkgPath": "", "gnowebURL": "https://testnet.gno.teritori.com", "faucetURL": "https://testnet.gno.teritori.com:5050/?toaddr=$addr" }, diff --git a/packages/utils/gnodao/deploy.ts b/packages/utils/gnodao/deploy.ts index 868e75ed28..8fbf92519b 100644 --- a/packages/utils/gnodao/deploy.ts +++ b/packages/utils/gnodao/deploy.ts @@ -30,7 +30,6 @@ const generateDAORealmSource = (networkId: string, conf: GnoDAOConfig) => { "${network.daoUtilsPkgPath}" voting_group "${network.votingGroupPkgPath}" "${network.daoRegistryPkgPath}" - "${network.toriPkgPath}" ) var ( From 5caf06fa4611db03fcb76d348a0fb49d1d2bc6e3 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Thu, 31 Oct 2024 22:45:43 +0100 Subject: [PATCH 20/27] feat: add a call to members JSON --- gno/p/dao_voting_group/voting_group.gno | 10 ++++++++++ packages/hooks/dao/useDAOMembers.ts | 15 +-------------- packages/utils/gnodao/configs.ts | 3 ++- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/gno/p/dao_voting_group/voting_group.gno b/gno/p/dao_voting_group/voting_group.gno index 2cc7975018..c9f925d2e2 100644 --- a/gno/p/dao_voting_group/voting_group.gno +++ b/gno/p/dao_voting_group/voting_group.gno @@ -150,6 +150,16 @@ func (g *VotingGroup) GetMembers(start, end string, limit uint64, height int64) return members } +func (g *VotingGroup) GetMembersJSON(start, end string, limit uint64, height int64) *json.Node { + members := g.GetMembers(start, end, limit, height) + nodes := make([]*json.Node, len(members)) + for i, m := range members { + nodes[i] = m.ToJSON() + } + + return json.ArrayNode("", nodes) +} + func (v *VotingGroup) Render(path string) string { sb := strings.Builder{} sb.WriteString("Member count: ") diff --git a/packages/hooks/dao/useDAOMembers.ts b/packages/hooks/dao/useDAOMembers.ts index 70db6b77d1..857989ee5c 100644 --- a/packages/hooks/dao/useDAOMembers.ts +++ b/packages/hooks/dao/useDAOMembers.ts @@ -10,14 +10,11 @@ import { parseUserId, } from "@/networks"; import { extractGnoJSONString } from "@/utils/gno"; -import { VotingGroupConfig } from "@/utils/gnodao/configs"; // FIXME: pagination type GnoDAOMember = { address: string; - id: number; - metadata: string; weight: number; }; @@ -46,23 +43,13 @@ export const useDAOMembers = (daoId: string | undefined) => { return members; } case NetworkKind.Gno: { - if (!network.groupsPkgPath) { - return []; - } const provider = new GnoJSONRPCProvider(network.endpoint); - const moduleConfig: VotingGroupConfig = extractGnoJSONString( + const res: GnoDAOMember[] = extractGnoJSONString( await provider.evaluateExpression( daoAddress, "daoCore.VotingModule().ConfigJSON()", ), ); - const { groupId } = moduleConfig; - const res: GnoDAOMember[] = extractGnoJSONString( - await provider.evaluateExpression( - network.groupsPkgPath, - `GetMembersJSON(${groupId})`, - ), - ); return res.map((member) => ({ addr: member.address, weight: member.weight, diff --git a/packages/utils/gnodao/configs.ts b/packages/utils/gnodao/configs.ts index c839b87b2d..9e27a92520 100644 --- a/packages/utils/gnodao/configs.ts +++ b/packages/utils/gnodao/configs.ts @@ -1,3 +1,4 @@ export interface VotingGroupConfig { - groupId: number; + totalPower: number; + members: number; } From ed52b3fd029a015960f565224e32bbcb72ae0e35 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Thu, 31 Oct 2024 22:46:41 +0100 Subject: [PATCH 21/27] feat: add a call to members JSON --- gno/p/dao_voting_group/voting_group.gno | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gno/p/dao_voting_group/voting_group.gno b/gno/p/dao_voting_group/voting_group.gno index c9f925d2e2..37b6cf122a 100644 --- a/gno/p/dao_voting_group/voting_group.gno +++ b/gno/p/dao_voting_group/voting_group.gno @@ -150,14 +150,14 @@ func (g *VotingGroup) GetMembers(start, end string, limit uint64, height int64) return members } -func (g *VotingGroup) GetMembersJSON(start, end string, limit uint64, height int64) *json.Node { +func (g *VotingGroup) GetMembersJSON(start, end string, limit uint64, height int64) string { members := g.GetMembers(start, end, limit, height) nodes := make([]*json.Node, len(members)) for i, m := range members { nodes[i] = m.ToJSON() } - return json.ArrayNode("", nodes) + return json.ArrayNode("", nodes).String() } func (v *VotingGroup) Render(path string) string { From 0fa0a0ad23d87ce08d603980924ce8626be3bee1 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Thu, 31 Oct 2024 23:02:22 +0100 Subject: [PATCH 22/27] fix: remove tori admin handler --- packages/utils/gnodao/deploy.ts | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/utils/gnodao/deploy.ts b/packages/utils/gnodao/deploy.ts index 8fbf92519b..7ac30a5e4a 100644 --- a/packages/utils/gnodao/deploy.ts +++ b/packages/utils/gnodao/deploy.ts @@ -42,11 +42,11 @@ func init() { votingModuleFactory := func(core dao_interfaces.IDAOCore) dao_interfaces.IVotingModule { group = voting_group.NewVotingGroup() ${conf.initialMembers - .map( - (member) => - `group.SetMemberPower("${member.address}", ${member.weight});`, - ) - .join("\n\t")} + .map( + (member) => + `group.SetMemberPower("${member.address}", ${member.weight});`, + ) + .join("\n\t")} return group } @@ -55,11 +55,11 @@ func init() { proposalModulesFactories := []dao_interfaces.ProposalModuleFactory{ func(core dao_interfaces.IDAOCore) dao_interfaces.IProposalModule { tt := proposal_single.PercentageThresholdPercent(${Math.ceil( - conf.thresholdPercent * 100, - )}) // ${Math.ceil(conf.thresholdPercent * 100) / 100}% + conf.thresholdPercent * 100, + )}) // ${Math.ceil(conf.thresholdPercent * 100) / 100}% tq := proposal_single.PercentageThresholdPercent(${Math.ceil( - conf.quorumPercent * 100, - )}) // ${Math.ceil(conf.quorumPercent * 100) / 100}% + conf.quorumPercent * 100, + )}) // ${Math.ceil(conf.quorumPercent * 100) / 100}% return proposal_single.NewDAOProposalSingle(core, &proposal_single.DAOProposalSingleOpts{ MaxVotingPeriod: dao_utils.DurationTime(time.Second * ${conf.maxVotingPeriodSeconds}), Threshold: &proposal_single.ThresholdThresholdQuorum{ @@ -79,9 +79,6 @@ func init() { propMod := core.ProposalModules()[0] return proposal_single.NewUpdateSettingsHandler(propMod.Module.(*proposal_single.DAOProposalSingle)) }, - func(core dao_interfaces.IDAOCore) dao_interfaces.MessageHandler { - return tori.NewChangeAdminHandler() - }, } daoCore = dao_core.NewDAOCore(votingModuleFactory, proposalModulesFactories, messageHandlersFactories) From 4e08f27e897e5209d982a51890f147474ea1fad6 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Thu, 31 Oct 2024 23:05:25 +0100 Subject: [PATCH 23/27] chore: run eslint --- packages/utils/gnodao/deploy.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/utils/gnodao/deploy.ts b/packages/utils/gnodao/deploy.ts index 7ac30a5e4a..7c50be7315 100644 --- a/packages/utils/gnodao/deploy.ts +++ b/packages/utils/gnodao/deploy.ts @@ -42,11 +42,11 @@ func init() { votingModuleFactory := func(core dao_interfaces.IDAOCore) dao_interfaces.IVotingModule { group = voting_group.NewVotingGroup() ${conf.initialMembers - .map( - (member) => - `group.SetMemberPower("${member.address}", ${member.weight});`, - ) - .join("\n\t")} + .map( + (member) => + `group.SetMemberPower("${member.address}", ${member.weight});`, + ) + .join("\n\t")} return group } @@ -55,11 +55,11 @@ func init() { proposalModulesFactories := []dao_interfaces.ProposalModuleFactory{ func(core dao_interfaces.IDAOCore) dao_interfaces.IProposalModule { tt := proposal_single.PercentageThresholdPercent(${Math.ceil( - conf.thresholdPercent * 100, - )}) // ${Math.ceil(conf.thresholdPercent * 100) / 100}% + conf.thresholdPercent * 100, + )}) // ${Math.ceil(conf.thresholdPercent * 100) / 100}% tq := proposal_single.PercentageThresholdPercent(${Math.ceil( - conf.quorumPercent * 100, - )}) // ${Math.ceil(conf.quorumPercent * 100) / 100}% + conf.quorumPercent * 100, + )}) // ${Math.ceil(conf.quorumPercent * 100) / 100}% return proposal_single.NewDAOProposalSingle(core, &proposal_single.DAOProposalSingleOpts{ MaxVotingPeriod: dao_utils.DurationTime(time.Second * ${conf.maxVotingPeriodSeconds}), Threshold: &proposal_single.ThresholdThresholdQuorum{ From fce1b40737722d910eb27bfe7ce8c935b6121a8c Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Thu, 31 Oct 2024 23:11:15 +0100 Subject: [PATCH 24/27] fix: add a TODO to fix later the groupId --- packages/components/dao/DAOMembers.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/dao/DAOMembers.tsx b/packages/components/dao/DAOMembers.tsx index b4a5ef0593..b0e9acd913 100644 --- a/packages/components/dao/DAOMembers.tsx +++ b/packages/components/dao/DAOMembers.tsx @@ -268,14 +268,14 @@ const useProposeToAddMembers = (daoId: string | undefined) => { "daoCore.VotingModule().ConfigJSON()", ), ); - const { groupId } = moduleConfig; + // const { groupId } = moduleConfig; const msgs: GnoAddMemberMessage[] = []; for (const member of membersToAdd) { msgs.push({ type: "gno.land/r/teritori/groups.AddMember", payload: { - groupId, + groupId: 0, // TODO: FIX ME address: member, weight, metadata: "", From ca673e016ba67b6a5c6c41ebcafb72e40381533a Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Thu, 31 Oct 2024 23:19:04 +0100 Subject: [PATCH 25/27] fix: remove groupId --- packages/components/dao/DAOMembers.tsx | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/packages/components/dao/DAOMembers.tsx b/packages/components/dao/DAOMembers.tsx index b0e9acd913..f575dfce28 100644 --- a/packages/components/dao/DAOMembers.tsx +++ b/packages/components/dao/DAOMembers.tsx @@ -1,4 +1,3 @@ -import { GnoJSONRPCProvider } from "@gnolang/gno-js-client"; import { Buffer } from "buffer"; import React, { useCallback, useState } from "react"; import { StyleProp, View, ViewStyle, useWindowDimensions } from "react-native"; @@ -13,8 +12,7 @@ import { useInvalidateDAOProposals } from "../../hooks/dao/useDAOProposals"; import { useNameSearch } from "../../hooks/search/useNameSearch"; import useSelectedWallet from "../../hooks/useSelectedWallet"; import { NetworkKind, getUserId, parseUserId } from "../../networks"; -import { adenaVMCall, extractGnoJSONString } from "../../utils/gno"; -import { VotingGroupConfig } from "../../utils/gnodao/configs"; +import { adenaVMCall } from "../../utils/gno"; import { GnoAddMemberMessage, GnoSingleChoiceProposal, @@ -260,22 +258,12 @@ const useProposeToAddMembers = (daoId: string | undefined) => { break; } case NetworkKind.Gno: { - const client = new GnoJSONRPCProvider(network.endpoint); - - const moduleConfig: VotingGroupConfig = extractGnoJSONString( - await client.evaluateExpression( - daoAddress, - "daoCore.VotingModule().ConfigJSON()", - ), - ); - // const { groupId } = moduleConfig; - const msgs: GnoAddMemberMessage[] = []; for (const member of membersToAdd) { msgs.push({ type: "gno.land/r/teritori/groups.AddMember", payload: { - groupId: 0, // TODO: FIX ME + groupId: 0, address: member, weight, metadata: "", From 8be6a98a78257ab1d72626a2bfdf856cc4381993 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Fri, 1 Nov 2024 11:02:01 +0100 Subject: [PATCH 26/27] fix: keep only e2e related code --- gno/p/dao_voting_group/voting_group.gno | 10 - networks.json | 5 + packages/components/dao/DAOMembers.tsx | 15 +- packages/components/dao/GnoDemo.tsx | 242 +++++++++++++++++++++++- packages/hooks/dao/useDAOMembers.ts | 15 +- packages/networks/gno-dev/index.ts | 2 + packages/networks/gno-portal/index.ts | 2 + packages/networks/gno-teritori/index.ts | 2 + packages/networks/types.ts | 2 + packages/utils/gnodao/configs.ts | 3 +- 10 files changed, 282 insertions(+), 16 deletions(-) diff --git a/gno/p/dao_voting_group/voting_group.gno b/gno/p/dao_voting_group/voting_group.gno index 37b6cf122a..2cc7975018 100644 --- a/gno/p/dao_voting_group/voting_group.gno +++ b/gno/p/dao_voting_group/voting_group.gno @@ -150,16 +150,6 @@ func (g *VotingGroup) GetMembers(start, end string, limit uint64, height int64) return members } -func (g *VotingGroup) GetMembersJSON(start, end string, limit uint64, height int64) string { - members := g.GetMembers(start, end, limit, height) - nodes := make([]*json.Node, len(members)) - for i, m := range members { - nodes[i] = m.ToJSON() - } - - return json.ArrayNode("", nodes).String() -} - func (v *VotingGroup) Render(path string) string { sb := strings.Builder{} sb.WriteString("Member count: ") diff --git a/networks.json b/networks.json index 80e02260e7..23fcb07bb8 100644 --- a/networks.json +++ b/networks.json @@ -4519,6 +4519,8 @@ "socialFeedsPkgPath": "gno.land/r/teritori/social_feeds", "socialFeedsDAOPkgPath": "gno.land/r/teritori/social_feeds_dao", "nameServiceContractAddress": "gno.land/r/demo/users", + "modboardsPkgPath": "gno.land/r/teritori/modboards", + "groupsPkgPath": "gno.land/r/teritori/groups", "votingGroupPkgPath": "gno.land/p/teritori/dao_voting_group", "daoProposalSinglePkgPath": "gno.land/p/teritori/dao_proposal_single", "profilePkgPath": "gno.land/r/demo/profile", @@ -4569,6 +4571,7 @@ "daoRegistryPkgPath": "gno.land/r/teritori/dao_registry", "socialFeedsPkgPath": "gno.land/r/teritori/social_feeds", "socialFeedsDAOPkgPath": "gno.land/r/teritori/social_feeds_dao", + "groupsPkgPath": "gno.land/r/teritori/groups", "votingGroupPkgPath": "gno.land/p/teritori/dao_voting_group", "daoProposalSinglePkgPath": "gno.land/p/teritori/dao_proposal_single", "daoInterfacesPkgPath": "gno.land/p/teritori/dao_interfaces", @@ -4624,6 +4627,8 @@ "daoRegistryPkgPath": "gno.land/r/teritori/dao_registry_v4", "socialFeedsPkgPath": "gno.land/r/teritori/social_feeds_v4", "socialFeedsDAOPkgPath": "gno.land/r/teritori/social_feeds_dao_v2", + "modboardsPkgPath": "gno.land/r/teritori/modboards_v4", + "groupsPkgPath": "gno.land/r/teritori/groups_v4", "votingGroupPkgPath": "gno.land/p/teritori/dao_voting_group_v2", "daoProposalSinglePkgPath": "gno.land/p/teritori/dao_proposal_single_v4", "daoInterfacesPkgPath": "gno.land/p/teritori/dao_interfaces_v5", diff --git a/packages/components/dao/DAOMembers.tsx b/packages/components/dao/DAOMembers.tsx index f575dfce28..3c8538fb64 100644 --- a/packages/components/dao/DAOMembers.tsx +++ b/packages/components/dao/DAOMembers.tsx @@ -1,3 +1,4 @@ +import { GnoJSONRPCProvider } from "@gnolang/gno-js-client"; import { Buffer } from "buffer"; import React, { useCallback, useState } from "react"; import { StyleProp, View, ViewStyle, useWindowDimensions } from "react-native"; @@ -12,7 +13,8 @@ import { useInvalidateDAOProposals } from "../../hooks/dao/useDAOProposals"; import { useNameSearch } from "../../hooks/search/useNameSearch"; import useSelectedWallet from "../../hooks/useSelectedWallet"; import { NetworkKind, getUserId, parseUserId } from "../../networks"; -import { adenaVMCall } from "../../utils/gno"; +import { adenaVMCall, extractGnoJSONString } from "../../utils/gno"; +import { VotingGroupConfig } from "../../utils/gnodao/configs"; import { GnoAddMemberMessage, GnoSingleChoiceProposal, @@ -258,12 +260,21 @@ const useProposeToAddMembers = (daoId: string | undefined) => { break; } case NetworkKind.Gno: { + const client = new GnoJSONRPCProvider(network.endpoint); + + const moduleConfig: VotingGroupConfig = extractGnoJSONString( + await client.evaluateExpression( + daoAddress, + "daoCore.VotingModule().ConfigJSON()", + ), + ); + const { groupId } = moduleConfig; const msgs: GnoAddMemberMessage[] = []; for (const member of membersToAdd) { msgs.push({ type: "gno.land/r/teritori/groups.AddMember", payload: { - groupId: 0, + groupId, address: member, weight, metadata: "", diff --git a/packages/components/dao/GnoDemo.tsx b/packages/components/dao/GnoDemo.tsx index ecb25c1d3e..f6b8e9134d 100644 --- a/packages/components/dao/GnoDemo.tsx +++ b/packages/components/dao/GnoDemo.tsx @@ -1,3 +1,5 @@ +import { GnoJSONRPCProvider } from "@gnolang/gno-js-client"; +import { useQuery } from "@tanstack/react-query"; import { useState } from "react"; import { View } from "react-native"; @@ -5,12 +7,17 @@ import { useFeedbacks } from "../../context/FeedbacksProvider"; import { useInvalidateDAOProposals } from "../../hooks/dao/useDAOProposals"; import useSelectedWallet from "../../hooks/useSelectedWallet"; import { NetworkKind, parseUserId } from "../../networks"; -import { adenaVMCall } from "../../utils/gno"; +import { adenaVMCall, extractGnoNumber } from "../../utils/gno"; import { GnoDAOUpdateSettings, + GnoMintToriMessage, + GnoModboardsCreateMessage, + GnoModboardsDeletePostMessage, GnoSingleChoiceProposal, } from "../../utils/gnodao/messages"; +import { fontSemibold20 } from "../../utils/style/fonts"; import { modalMarginPadding } from "../../utils/style/modals"; +import { BrandText } from "../BrandText"; import { PrimaryButton } from "../buttons/PrimaryButton"; import { TextInputCustom } from "../inputs/TextInputCustom"; import ModalBase from "../modals/ModalBase"; @@ -75,6 +82,239 @@ export const GnoDemo: React.FC<{ ); }; +const DeletePost: React.FC<{ daoId: string }> = ({ daoId }) => { + const [network, daoAddress] = parseUserId(daoId); + const wallet = useSelectedWallet(); + const { wrapWithFeedback } = useFeedbacks(); + const addressParts = daoAddress.split("/"); + const [name, setName] = useState( + addressParts.length > 0 ? addressParts[addressParts.length - 1] : "", + ); + const [threadId, setThreadId] = useState("1"); + const [postId, setPostId] = useState("1"); + const [reason, setReason] = useState("Moderated"); + + const { data: flagCount } = useQuery( + ["flagCount", name, threadId, postId], + async () => { + if (network?.kind !== NetworkKind.Gno || !network.modboardsPkgPath) { + return 0; + } + const client = new GnoJSONRPCProvider(network.endpoint); + const boardIdRes = await client.evaluateExpression( + network.modboardsPkgPath, + `GetBoardIDFromName("${name}")`, + ); + const boardIdNum = extractGnoNumber(boardIdRes); + if (!boardIdNum) { + throw new Error(`invalid board id ${boardIdNum}`); + } + return extractGnoNumber( + await client.evaluateExpression( + network.modboardsPkgPath, + `getBoard(${boardIdNum}).flags.GetFlagCount(getFlagID(${threadId}, ${postId}))`, + ), + ); + }, + ); + + if (network?.kind !== NetworkKind.Gno || !wallet) return null; + return ( + + Delete a post + + + + + + + + + + Flagged: {flagCount || 0} time(s) + + { + if (network?.kind !== NetworkKind.Gno || !network.modboardsPkgPath) { + throw new Error("invalid network"); + } + const client = new GnoJSONRPCProvider(network.endpoint); + const boardIdRes = await client.evaluateExpression( + network.modboardsPkgPath, + `GetBoardIDFromName("${name}")`, + ); + console.log(boardIdRes); + const boardIdNum = extractGnoNumber(boardIdRes); + if (!boardIdNum) { + throw new Error(`invalid board id ${boardIdNum}`); + } + const threadIdNum = parseInt(threadId, 10); + const postIdNum = parseInt(postId, 10); + const payload: GnoModboardsDeletePostMessage = { + type: "gno.land/r/teritori/modboards.DeletePost", + payload: { + boardId: boardIdNum, + threadId: threadIdNum, + postId: postIdNum, + reason, + }, + }; + const propReq: GnoSingleChoiceProposal = { + title: threadIdNum === postIdNum ? "Delete thread" : "Delete post", + description: "", + messages: [payload], + }; + await adenaVMCall( + network.id, + { + pkg_path: daoAddress, + func: "ProposeJSON", + caller: wallet.address, + send: "", + args: ["0", JSON.stringify(propReq)], + }, + { gasWanted: 10000000 }, + ); + })} + /> + + ); +}; + +const CreateBoard: React.FC<{ daoId: string }> = ({ daoId }) => { + const [network, daoAddress] = parseUserId(daoId); + const wallet = useSelectedWallet(); + const { wrapWithFeedback } = useFeedbacks(); + const [name, setName] = useState(""); + + if (network?.kind !== NetworkKind.Gno || !wallet) return null; + return ( + + Create a board + + + + { + const payload: GnoModboardsCreateMessage = { + type: "gno.land/r/teritori/modboards.CreateBoard", + payload: { + name, + }, + }; + const propReq: GnoSingleChoiceProposal = { + title: `Create board ${name}`, + description: "", + messages: [payload], + }; + await adenaVMCall( + network.id, + { + pkg_path: daoAddress, + func: "ProposeJSON", + caller: wallet.address, + send: "", + args: ["0", JSON.stringify(propReq)], + }, + { gasWanted: 10000000 }, + ); + })} + /> + + ); +}; + +const MintTori: React.FC<{ daoId: string }> = ({ daoId }) => { + const [network, daoAddress] = parseUserId(daoId); + const wallet = useSelectedWallet(); + const { wrapWithFeedback } = useFeedbacks(); + const [amount, setAmount] = useState("1"); + const [recipient, setRecipient] = useState(""); + + if (network?.kind !== NetworkKind.Gno || !wallet) return null; + return ( + + Mint Tori + + + + + + { + const payload: GnoMintToriMessage = { + type: "gno.land/r/teritori/tori.Mint", + payload: { + amount: parseInt(amount, 10), + address: recipient, + }, + }; + const msg: GnoSingleChoiceProposal = { + title: `Mint ${amount} utori to ${recipient}`, + description: "", + messages: [payload], + }; + await adenaVMCall(network.id, { + pkg_path: daoAddress, + func: "ProposeJSON", + caller: wallet.address, + send: "", + args: ["0", JSON.stringify(msg)], + }); + })} + /> + + ); +}; + const GnoCreateProposal: React.FC<{ daoId: string | undefined }> = ({ daoId, }) => { diff --git a/packages/hooks/dao/useDAOMembers.ts b/packages/hooks/dao/useDAOMembers.ts index 857989ee5c..70db6b77d1 100644 --- a/packages/hooks/dao/useDAOMembers.ts +++ b/packages/hooks/dao/useDAOMembers.ts @@ -10,11 +10,14 @@ import { parseUserId, } from "@/networks"; import { extractGnoJSONString } from "@/utils/gno"; +import { VotingGroupConfig } from "@/utils/gnodao/configs"; // FIXME: pagination type GnoDAOMember = { address: string; + id: number; + metadata: string; weight: number; }; @@ -43,13 +46,23 @@ export const useDAOMembers = (daoId: string | undefined) => { return members; } case NetworkKind.Gno: { + if (!network.groupsPkgPath) { + return []; + } const provider = new GnoJSONRPCProvider(network.endpoint); - const res: GnoDAOMember[] = extractGnoJSONString( + const moduleConfig: VotingGroupConfig = extractGnoJSONString( await provider.evaluateExpression( daoAddress, "daoCore.VotingModule().ConfigJSON()", ), ); + const { groupId } = moduleConfig; + const res: GnoDAOMember[] = extractGnoJSONString( + await provider.evaluateExpression( + network.groupsPkgPath, + `GetMembersJSON(${groupId})`, + ), + ); return res.map((member) => ({ addr: member.address, weight: member.weight, diff --git a/packages/networks/gno-dev/index.ts b/packages/networks/gno-dev/index.ts index e904112f49..8f1e2e06f9 100644 --- a/packages/networks/gno-dev/index.ts +++ b/packages/networks/gno-dev/index.ts @@ -42,6 +42,8 @@ export const gnoDevNetwork: GnoNetworkInfo = { socialFeedsPkgPath: "gno.land/r/teritori/social_feeds", socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao", nameServiceContractAddress: "gno.land/r/demo/users", + modboardsPkgPath: "gno.land/r/teritori/modboards", + groupsPkgPath: "gno.land/r/teritori/groups", votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group", daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single", profilePkgPath: "gno.land/r/demo/profile", diff --git a/packages/networks/gno-portal/index.ts b/packages/networks/gno-portal/index.ts index 040c90fe9b..a2fa0d2dce 100644 --- a/packages/networks/gno-portal/index.ts +++ b/packages/networks/gno-portal/index.ts @@ -32,6 +32,8 @@ export const gnoPortalNetwork: GnoNetworkInfo = { daoRegistryPkgPath: "gno.land/r/teritori/dao_registry", socialFeedsPkgPath: "gno.land/r/teritori/social_feeds", socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao", + // modboardsPkgPath: "gno.land/r/teritori/modboards_v4", + groupsPkgPath: "gno.land/r/teritori/groups", votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group", daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single", daoInterfacesPkgPath: "gno.land/p/teritori/dao_interfaces", diff --git a/packages/networks/gno-teritori/index.ts b/packages/networks/gno-teritori/index.ts index d6d632ea43..b511fd9053 100644 --- a/packages/networks/gno-teritori/index.ts +++ b/packages/networks/gno-teritori/index.ts @@ -37,6 +37,8 @@ export const gnoTeritoriNetwork: GnoNetworkInfo = { daoRegistryPkgPath: "gno.land/r/teritori/dao_registry_v4", socialFeedsPkgPath: "gno.land/r/teritori/social_feeds_v4", socialFeedsDAOPkgPath: "gno.land/r/teritori/social_feeds_dao_v2", + modboardsPkgPath: "gno.land/r/teritori/modboards_v4", + groupsPkgPath: "gno.land/r/teritori/groups_v4", votingGroupPkgPath: "gno.land/p/teritori/dao_voting_group_v2", daoProposalSinglePkgPath: "gno.land/p/teritori/dao_proposal_single_v4", daoInterfacesPkgPath: "gno.land/p/teritori/dao_interfaces_v5", diff --git a/packages/networks/types.ts b/packages/networks/types.ts index d442d3596d..d9002aaeae 100644 --- a/packages/networks/types.ts +++ b/packages/networks/types.ts @@ -109,12 +109,14 @@ export type GnoNetworkInfo = NetworkInfoBase & { nameServiceDefaultImage: string; gnowebURL: string; daoRegistryPkgPath?: string; + modboardsPkgPath?: string; socialFeedsPkgPath?: string; socialFeedsDAOPkgPath?: string; votingGroupPkgPath?: string; daoProposalSinglePkgPath?: string; daoInterfacesPkgPath?: string; daoCorePkgPath?: string; + groupsPkgPath?: string; daoUtilsPkgPath?: string; toriPkgPath?: string; profilePkgPath?: string; diff --git a/packages/utils/gnodao/configs.ts b/packages/utils/gnodao/configs.ts index 9e27a92520..c839b87b2d 100644 --- a/packages/utils/gnodao/configs.ts +++ b/packages/utils/gnodao/configs.ts @@ -1,4 +1,3 @@ export interface VotingGroupConfig { - totalPower: number; - members: number; + groupId: number; } From 010420e2875a0e658ae0427291c547f7f56744a4 Mon Sep 17 00:00:00 2001 From: MikaelVallenet Date: Fri, 1 Nov 2024 11:04:19 +0100 Subject: [PATCH 27/27] fix: keep only e2e related code --- packages/components/dao/DAOMembers.tsx | 1 + packages/components/dao/GnoDemo.tsx | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/components/dao/DAOMembers.tsx b/packages/components/dao/DAOMembers.tsx index 3c8538fb64..b4a5ef0593 100644 --- a/packages/components/dao/DAOMembers.tsx +++ b/packages/components/dao/DAOMembers.tsx @@ -269,6 +269,7 @@ const useProposeToAddMembers = (daoId: string | undefined) => { ), ); const { groupId } = moduleConfig; + const msgs: GnoAddMemberMessage[] = []; for (const member of membersToAdd) { msgs.push({ diff --git a/packages/components/dao/GnoDemo.tsx b/packages/components/dao/GnoDemo.tsx index f6b8e9134d..4fed515cac 100644 --- a/packages/components/dao/GnoDemo.tsx +++ b/packages/components/dao/GnoDemo.tsx @@ -40,8 +40,11 @@ export const GnoDemo: React.FC<{ + + + wrapWithFeedback(async () => {