Search Apps Documentation Source Content File Folder Download Copy Actions Download

utils.gno

5.88 Kb Β· 129 lines
  1package simple_dao
  2
  3import (
  4	"strings"
  5	"unicode"
  6
  7	"gno.land/p/mason/md"
  8	"gno.land/p/moul/txlink"
  9	"gno.land/p/nt/ufmt/v0"
 10	"gno.land/p/samcrew/basedao"
 11	"gno.land/p/samcrew/daocond"
 12	"gno.land/p/samcrew/daokit"
 13)
 14
 15// Creates a number of initial proposals and votes.
 16// It divides the proposals into 4 parts: AddMember, RemoveMember, AssignRole, EditProfile.
 17// It initializes votes for each proposal type.
 18func initProposals(cur realm, nb int) {
 19	const financeOfficer = "g1demo1234567890abcdefghijklmnopqrstuvwxyz"
 20	const nbTypes = 4
 21	proposalsPerType := nb / nbTypes
 22	offsets := []int{0, proposalsPerType, 2 * proposalsPerType, 3 * proposalsPerType, nb} // AddMember, Remove, AssignRole, EditProfile
 23
 24	lastAddr := financeOfficer
 25
 26	for t, start := range offsets[:nbTypes] {
 27		end := offsets[t+1]
 28		for i := start; i < end; i++ {
 29			addr := ufmt.Sprintf("g1fakemember000000000000000000000000000%02d", i)
 30			var action daokit.Action
 31			var title string
 32			var description string
 33
 34			// CREATE
 35			switch t {
 36			case 0: // AddMember
 37				action = basedao.NewAddMemberAction(&basedao.ActionAddMember{Address: address(addr), Roles: []string{}})
 38				title = ufmt.Sprintf("Add member %s with no role", addr)
 39				description = ufmt.Sprintf("This proposal will add %s as a new member of the DAO without any specific roles. They will be able to participate in governance and vote on proposals.", addr)
 40			case 1: // RemoveMember
 41				action = basedao.NewRemoveMemberAction(address(addr))
 42				title = ufmt.Sprintf("Remove member %s", addr)
 43				description = ufmt.Sprintf("This proposal will remove %s from the DAO membership. They will no longer be able to participate in governance or vote on proposals.", addr)
 44			case 2: // AssignRole
 45				role := "public-relationships"
 46				action = basedao.NewAssignRoleAction(&basedao.ActionAssignRole{Address: address(financeOfficer), Role: role})
 47				title = ufmt.Sprintf("Assign role %s for %s", role, addr)
 48				description = ufmt.Sprintf("This proposal will assign the '%s' role to the finance officer. This role grants additional responsibilities and permissions within the DAO.", role)
 49			case 3: // EditProfile
 50				action = basedao.NewEditProfileAction([2]string{"Bio", "A demo DAO showcasing governance and community decision-making."})
 51				title = "Edit the DAO's profile"
 52				description = "This proposal will update the DAO's bio with a simple description of our purpose as a demonstration DAO."
 53			}
 54			req := daokit.ProposalRequest{
 55				Title:       title,
 56				Action:      action,
 57				Description: description,
 58			}
 59			id := daoPrivate.Core.Propose(lastAddr, req)
 60
 61			// VOTE
 62			quart := i * 4 / nb
 63			switch quart {
 64			case 0: // VoteNo
 65				daoPrivate.Core.Vote(financeOfficer, id, daocond.VoteNo)
 66			case 1: // VoteYes
 67				daoPrivate.Core.Vote(financeOfficer, id, daocond.VoteYes)
 68			case 2: // VoteAbstain
 69				daoPrivate.Core.Vote(financeOfficer, id, daocond.VoteAbstain)
 70			case 3: // VoteYes + Execute
 71				daoPrivate.Core.Vote(financeOfficer, id, daocond.VoteYes)
 72				daoPrivate.Core.Execute(id, cur)
 73			}
 74
 75			lastAddr = addr
 76		}
 77	}
 78}
 79
 80// Bypass limitation by adding yourself to the DAO.
 81// It is necessary to be part of the DAO to create a Proposal.
 82func AddMember(cur realm) {
 83	id := daoPrivate.CallerID()
 84	daoPrivate.Members.AddMember(id, make([]string, 0))
 85}
 86
 87// Creates a Proposal to add a new member to the DAO with specified roles.
 88// This function exist to let users try the userflow of daokit with a simple MsgCall (maketx call) instead of a MsgRun.
 89// See why a run is necessary for creating a proposal -> https://docs.gno.land/users/interact-with-gnokey#run.
 90// Parameters:
 91//   - address: The std.Address of the member to be added
 92//   - roles: Comma-separated roles (e.g., "public-relationships,finance-officer" or "finance-officer")
 93func ProposeAddMember(cur realm, address address, roles string) {
 94	rs := strings.Split(roles, ",")
 95	for i, s := range rs {
 96		rs[i] = strings.TrimFunc(s, unicode.IsSpace)
 97	}
 98	req := daokit.ProposalRequest{
 99		Title: ufmt.Sprintf("Add member %s with roles %s", address, strings.Join(rs, ", ")),
100		Action: basedao.NewAddMemberAction(&basedao.ActionAddMember{
101			Address: address,
102			Roles:   rs,
103		}),
104	}
105	localDAO.Propose(req)
106}
107
108func renderDemo() string {
109	s := ""
110	s += "# πŸ›οΈ Simple DAO Actions\n\n"
111	s += "Welcome to Simple DAO! This is a demonstration of basic DAO functionality.\n\n"
112	s += "## ℹ️ How it Works\n\n"
113	s += "1. **Join the DAO** using the " + md.Link("AddMember", txlink.Call("AddMember")) + " function.\n\n"
114	s += "2. **Create a pre-made Proposal** using " + md.Link("ProposeAddMember", txlink.Call("ProposeAddMember")) + "  function using this parameters:\n\n"
115	s += "- `address`: The address of the member to add\n"
116	s += "- `roles`: Comma-separated roles (e.g., \"public-relationships,finance-officer\" or \"finance-officer\")\n\n"
117	s += "3. " + md.Link("Vote", txlink.Call("Vote")) + " on proposals using their ID.\n\n"
118	s += "4. " + md.Link("Execute", txlink.Call("Execute")) + " proposals that have passed (met the required voting conditions).\n\n"
119	s += "   πŸ“ **Note**: Only proposals that have met the governance conditions can be executed. You need both **40% of member approval** AND at least **1 finance-officer** to execute a proposal.\n\n"
120	s += "## πŸ“‹ Available Actions\n\n"
121	s += "### Member Management\n"
122	s += "- " + md.Link("πŸ”— Add Yourself as Member", txlink.Call("AddMember")) + " - Join the DAO to participate in governance\n"
123	s += "- " + md.Link("πŸ”— Propose Add Member", txlink.Call("ProposeAddMember")) + " - Create a proposal to add a new member with specific roles\n\n"
124	s += "### Other Demos\n"
125	s += "- " + md.Link("πŸ”— Custom Resource Example", "/r/samcrew/daodemo/custom_resource") + " - See a demo of custom resource implementation\n"
126	s += "- " + md.Link("πŸ”— Custom Condition Example", "/r/samcrew/daodemo/custom_condition") + " - See a demo of custom condition implementation\n\n"
127	s += "*This is a demonstration DAO built with gno.land and daokit*"
128	return s
129}