Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

daokit source pure

Constants 3

const ActionExecuteLambdaKind

1const ActionExecuteLambdaKind = "gno.land/p/samcrew/daokit.ExecuteLambda"
source

////////////////////////////////////////////////////////// ActionExecuteLambdaKind

Built-in action type for executing lambda functions.

const ActionInstantExecuteKind

1const ActionInstantExecuteKind = "gno.land/p/samcrew/daokit.InstantExecute"
source

////////////////////////////////////////////////////////// ActionInstantExecuteKind

Built-in action type for instantly executing sub-proposals.

Functions 10

func InstantExecute

1func InstantExecute(d DAO, req ProposalRequest, rlm realm) uint64
source

Creates, votes yes, and immediately executes a proposal in one operation. Useful when you have enough permission to execute an action directly. Examples: migrations, adding members.

SAME REALM ONLY. Every step threads rlm, and each entry point requires it to be the receiving DAO's own — so d must be a DAO hosted by the realm calling this. Handing it a DAO belonging to another realm is refused.

That refusal is the point. Driving a foreign DAO by passing it your realm is the donation shape: it makes the DAO act under YOUR identity, and it is what a caller holding the handle could previously do to any DAO. It appeared to work only because nothing checked.

A parent DAO can still drive a child. Reach the child through the child REALM's own crossing function — child.Propose(cross(cur), req) — so the child mints its own realm and sees the parent as its caller. Make the parent a member of the child; the child then authorises it like any other member.

func NewAction

1func NewAction(kind string, payload interface{}) Action
source

func NewInstantExecuteAction

1func NewInstantExecuteAction(dao DAO, req ProposalRequest) Action
source

SAME REALM ONLY, for the reason on InstantExecute: the handler forwards the EXECUTING DAO's realm, so dao must be hosted by the same realm. A child DAO in another realm is refused — reach it through that realm's crossing function instead.

func NewActionHandler

1func NewActionHandler(kind string, executor func(interface{}, realm)) ActionHandler
source

SECURITY: the executor MUST type-assert the payload to a CONCRETE type, never to an interface.

The concrete assertion is what makes the action's own rendering safe to show a voter: a hostile proposer can submit any payload, but one of the wrong type is rejected before the executor sees it, and one of the right type renders through that type's own String(). Assert to an interface instead and any conforming type passes — including one whose String() understates what its data does, so the proposal reads as something milder than it executes.

Stronger still, and what the destructive built-ins do: make the payload type UNEXPORTED and expose only a constructor, so a proposer cannot build one at all. basedao's ChangeDAOImplementation and daokit's InstantExecute both do.

Moving rendering onto the handler would remove this footgun rather than document it, since the handler is registered by the DAO and the payload is not — gnodaokit#13. That changes ActionHandler, so it belongs to a version boundary rather than a patch.

func NewCore

1func NewCore() *Core
source

Creates a new DAO core with empty stores.

Types 15

type Action

interface
1type Action interface {
2	// Returns human-readable description of the action.
3	String() string
4	// Returns unique identifier for the action type.
5	Type() string
6}
source

Interface storing Action's data.

SECURITY: String() is what a member reads before voting, and for an action built with NewAction it is the PAYLOAD's own rendering — supplied by whoever created the proposal. It is not trustworthy on its own.

Two things keep it honest. Type() must be truthful or the wrong handler is looked up and its type assertion fails, so the action's KIND cannot be disguised; and the proposal view renders the Resource's registered DisplayName, Description and Condition beside it, which come from the DAO's own registry keyed by Type(), not from the proposal. A member therefore always sees what KIND of action this is from a trusted source.

What String() can still misrepresent is the payload's DETAIL — and only if the handler lets a hostile payload through. See NewActionHandler.

type ActionHandler

interface
1type ActionHandler interface {
2	// Executes the given action's logic. The rlm realm is threaded so
3	// handlers can perform cross-realm calls during execution.
4	Execute(action Action, rlm realm)
5	// Returns the action type this handler processes.
6	Type() string
7}
source

Interface storing executable function that processes Action's data.

type Core

struct
1type Core struct {
2	Resources  *ResourcesStore  // Available actions and their conditions
3	Proposals  *ProposalsStore  // All proposals and their voting state
4	Extensions *ExtensionsStore // Pluggable functionality modules
5}
source

Manages the essential components of a DAO: resources, proposals, and extensions.

Methods on Core

func Execute

method on Core
1func (d *Core) Execute(proposalID uint64, rlm realm)
source

Executes a proposal if it meets the required voting conditions.

func Propose

method on Core
1func (d *Core) Propose(proposerID string, req ProposalRequest) uint64
source

Creates a new proposal for voting and returns its ID.

func Vote

method on Core
1func (d *Core) Vote(voterID string, proposalID uint64, vote daocond.Vote)
source

Records a vote for a specific proposal from a voter.

type DAO

interface
 1type DAO interface {
 2	// Creates a new proposal and returns its ID.
 3	Propose(req ProposalRequest, rlm realm) uint64
 4	// Casts a vote on a specific proposal.
 5	Vote(id uint64, vote daocond.Vote, rlm realm)
 6	// Executes a proposal if it meets the required conditions.
 7	Execute(id uint64, rlm realm)
 8
 9	// Generates a web interface representation for the given path.
10	Render(path string) string
11
12	// Gets an extension by path, returns nil if not found. A PRIVATE extension
13	// additionally requires the DAO realm's own live realm, on the same terms
14	// as the entry points above; a public one ignores it.
15	Extension(path string, rlm realm) Extension
16	// Lists all available extensions.
17	ExtensionsList() ExtensionsList
18}
source

Every entry point threads the DAO realm's own realm value.

It serves two purposes. Execute forwards it to the action handlers, which cross out under it, so the implementation must refuse any realm that is not its own — otherwise a caller holding this handle could make the DAO act under the CALLER's identity. And because the realm is then known to be the DAO's, rlm.Previous() names the DAO's immediate caller, which a stack walk cannot do: reached through this handle there is no DAO realm frame on the stack at all, so a walk reports the signing account instead.

An implementation must require the realm to be BOTH its own by pkgpath and current: every realm the DAO crosses out into receives the DAO's own realm as its cur.Previous() and can hand it back within the same transaction, and only IsCurrent() tells that apart from the live one.

The realm is deliberately never the first parameter: a function whose first parameter is a realm is read as crossing, which /p/ packages may not declare.

type Extension

interface
1type Extension interface {
2	// Returns metadata about this extension including its path, version,
3	// query path for external access, and privacy settings.
4	Info() ExtensionInfo
5}
source

Interface must be implemented by any object that wants to be registered as a DAO extension. Extensions expose functionality through well-defined interfaces while maintaining encapsulation.

type ExtensionInfo

struct
 1type ExtensionInfo struct {
 2	Path      string // Unique extension identifier (e.g., "gno.land/p/samcrew/basedao.MembersView")
 3	Version   string // Extension version (e.g., "1", "2.0", etc.)
 4	QueryPath string // Path for external queries to access this extension's data
 5	// If true, only the registering realm can obtain the extension VALUE
 6	// through DAO.Extension — which is a capability, not a secret. Realm state
 7	// on a public chain is world-readable over ABCI regardless, and this
 8	// ExtensionInfo (including QueryPath) is listed by ExtensionsList without a
 9	// check. Private restricts who can call the extension's methods under the
10	// DAO's authority; it does not hide anything.
11	Private bool
12}
source

type ExtensionsList

interface
 1type ExtensionsList interface {
 2	// Returns the total number of registered extensions.
 3	Len() int
 4	// Returns extension info at the specified index, or nil if index is out of bounds.
 5	Get(index int) *ExtensionInfo
 6	// Returns a slice of ExtensionInfo from startIndex to endIndex.
 7	Slice(startIndex, endIndex int) []ExtensionInfo
 8	// Iterates over all extensions, calling fn for each one.
 9	// Iteration stops if fn returns true.
10	ForEach(fn func(index int, value ExtensionInfo) bool)
11}
source

type ExtensionsStore

struct
1type ExtensionsStore struct {
2	Tree avl.Tree
3}
source

Methods on ExtensionsStore

func Get

method on ExtensionsStore
1func (es *ExtensionsStore) Get(path string) (Extension, bool)
source

func List

method on ExtensionsStore
1func (es *ExtensionsStore) List() ExtensionsList
source

Returns an ExtensionsList interface for iterating over all registered extensions. This provides read-only access to the extensions registry.

func Remove

method on ExtensionsStore
1func (es *ExtensionsStore) Remove(path string) (Extension, bool)
source

Remove unregisters an extension by its path. Returns the removed extension and true if found, nil and false otherwise.

func Set

method on ExtensionsStore
1func (es *ExtensionsStore) Set(ext Extension) bool
source

Registers a new extension using its path as the key. Returns true if the extension was successfully registered. If an extension with the same path already exists, it will be replaced.

type Proposal

struct
 1type Proposal struct {
 2	ID            seqid.ID
 3	Title         string
 4	Description   string
 5	CreatedAt     time.Time
 6	CreatedHeight int64
 7	ProposerID    string
 8
 9	Action     Action            // What to execute if passed
10	Condition  daocond.Condition // Voting conditions for this proposal
11	Status     ProposalStatus
12	ExecutedAt time.Time
13
14	Ballot daocond.Ballot // All votes cast on this proposal
15}
source

Methods on Proposal

func DisplayStatus

method on Proposal
1func (p *Proposal) DisplayStatus() ProposalStatus
source

Reports the status a proposal should be displayed as, without writing it.

Reading must never move a proposal. Render is on the cross-realm DAO interface, so anything it touches is reachable by any realm holding the handle: every read path used to call UpdateStatus on each proposal it walked, and a single Render flipped every condition-met proposal from Open to Passed — which, back when Execute demanded Open, bricked it permanently.

func UpdateStatus

method on Proposal
1func (p *Proposal) UpdateStatus()
source

Persists the status implied by the current votes: Open becomes Passed once the condition is met.

Nothing in this package calls it. Execute evaluates the condition itself and the read paths use DisplayStatus, so a proposal that is never passed through here stays Open until it is Executed. It exists for a realm that wants the passed state on-chain rather than computed.

SAFE ONLY BECAUSE Vote and Execute both key on Executed alone. When they demanded Open, calling this was destructive twice over: it froze the ballot, so support could not be withdrawn, and it made the proposal permanently unexecutable. Do not narrow either of those checks without removing this.

It is also a READ path hazard — do not call it while rendering. And once persisted the status no longer tracks the votes: withdraw support afterwards and this still reads Passed, though Execute re-evaluates the condition and will refuse.

type ProposalRequest

struct
1type ProposalRequest struct {
2	Title       string
3	Description string
4	Action      Action
5}
source

Data needed to create a new proposal.

type ProposalStatus

ident
1type ProposalStatus int
source

Methods on ProposalStatus

func String

method on ProposalStatus
1func (s ProposalStatus) String() string
source

type ProposalsStore

struct
1type ProposalsStore struct {
2	Tree  *avl.Tree // int -> Proposal
3	genID seqid.ID
4}
source

Methods on ProposalsStore

func GetProposal

method on ProposalsStore
1func (p *ProposalsStore) GetProposal(id uint64) *Proposal
source

func GetProposals

method on ProposalsStore
1func (p *ProposalsStore) GetProposals(filter func(Proposal) bool) *ProposalsStore
source

Returns all proposals that match the given filter function.

func GetProposalsJSON

method on ProposalsStore
1func (p *ProposalsStore) GetProposalsJSON() string
source

Returns all proposals as a JSON string.

type Resource

struct
1type Resource struct {
2	Handler     ActionHandler     // Executes the action when proposal passes
3	Condition   daocond.Condition // Voting rules required for approval
4	DisplayName string
5	Description string
6}
source

type ResourcesStore

struct
1type ResourcesStore struct {
2	Tree *avl.Tree // string -> daocond.Condition
3}
source

Methods on ResourcesStore

func Get

method on ResourcesStore
1func (r *ResourcesStore) Get(name string) *Resource
source

Retrieves a resource by its handler type name.

func Set

method on ResourcesStore
1func (r *ResourcesStore) Set(resource *Resource)
source

Registers a new resource with its handler type as key.

type SetImplemFn

func
1type SetImplemFn = func(implem DAO)
source

Function type for updating DAO implementation during governance upgrades.

Imports 9

Source Files 6