Search Apps Documentation Source Content File Folder Download Copy Actions Download

actions.gno

3.96 Kb · 138 lines
  1package daokit
  2
  3// Defines executable operations that proposals can perform.
  4// Each action has a type and handler functions that implements the actual logic.
  5//
  6// Example: Adding a member, transferring funds, or updating configuration.
  7
  8import (
  9	"errors"
 10
 11	"gno.land/p/moul/md"
 12	"gno.land/p/nt/ufmt/v0"
 13)
 14
 15// Interface storing Action's data.
 16type Action interface {
 17	// Returns human-readable description of the action.
 18	String() string
 19	// Returns unique identifier for the action type.
 20	Type() string
 21}
 22
 23// Interface storing executable function that processes Action's data.
 24type ActionHandler interface {
 25	// Executes the given action's logic. The rlm realm is threaded so
 26	// handlers can perform cross-realm calls during execution.
 27	Execute(action Action, rlm realm)
 28	// Returns the action type this handler processes.
 29	Type() string
 30}
 31
 32// Generic action implementation that stores a type and a payload.
 33// Payload contains the data parameters that will be processed by the handler.
 34// Example: {kind="/p/demo/transfer.Transfer", payload={amount: 1000, recipient: "user123"}}
 35type genericAction struct {
 36	kind    string
 37	payload interface{}
 38}
 39
 40// Generic action handler that executes a function with a given payload.
 41// Example: A transfer handler that processes {amount, recipient} to move funds.
 42// {kind="transfer", executor=transferFunds}
 43type genericActionHandler struct {
 44	kind     string
 45	executor func(payload interface{}, rlm realm)
 46}
 47
 48func NewAction(kind string, payload interface{}) Action {
 49	return &genericAction{kind: kind, payload: payload}
 50}
 51
 52// Returns string representation of the action's payload.
 53func (g *genericAction) String() string {
 54	return ufmt.Sprintf("%v", g.payload)
 55}
 56
 57// Returns the action's type identifier.
 58func (g *genericAction) Type() string {
 59	return g.kind
 60}
 61
 62func NewActionHandler(kind string, executor func(interface{}, realm)) ActionHandler {
 63	return &genericActionHandler{kind: kind, executor: executor}
 64}
 65
 66// Executes the action by calling the executor function with the payload.
 67func (g *genericActionHandler) Execute(iaction Action, rlm realm) {
 68	action, ok := iaction.(*genericAction)
 69	if !ok {
 70		panic(errors.New("invalid action type"))
 71	}
 72	g.executor(action.payload, rlm)
 73}
 74
 75// Returns the action's type identifier.
 76func (g *genericActionHandler) Type() string {
 77	return g.kind
 78}
 79
 80// Creates a new empty action instance.
 81func (g *genericActionHandler) Instantiate() Action {
 82	return &genericAction{
 83		kind: g.kind,
 84	}
 85}
 86
 87// //////////////////////////////////////////////////////////
 88// ActionExecuteLambdaKind
 89//
 90// Built-in action type for executing lambda functions.
 91const ActionExecuteLambdaKind = "gno.land/p/samcrew/daokit.ExecuteLambda"
 92
 93func NewExecuteLambdaHandler() ActionHandler {
 94	return NewActionHandler(ActionExecuteLambdaKind, func(i interface{}, _ realm) {
 95		cb, ok := i.(func())
 96		if !ok {
 97			panic(errors.New("invalid action type"))
 98		}
 99		cb()
100	})
101}
102
103func NewExecuteLambdaAction(cb func()) Action {
104	return NewAction(ActionExecuteLambdaKind, cb)
105}
106
107// //////////////////////////////////////////////////////////
108// ActionInstantExecuteKind
109//
110// Built-in action type for instantly executing sub-proposals.
111const ActionInstantExecuteKind = "gno.land/p/samcrew/daokit.InstantExecute"
112
113type actionInstantExecute struct {
114	dao DAO             // Target DAO to execute on
115	req ProposalRequest // Proposal to execute instantly
116}
117
118func (a *actionInstantExecute) String() string {
119	// XXX: find a way to be explicit about the subdao
120	s := ""
121	s += md.Paragraph(md.Blockquote(a.req.Action.Type()))
122	s += md.Paragraph(a.req.Action.String())
123	return s
124}
125
126func NewInstantExecuteHandler() ActionHandler {
127	return NewActionHandler(ActionInstantExecuteKind, func(i interface{}, rlm realm) {
128		action, ok := i.(*actionInstantExecute)
129		if !ok {
130			panic(errors.New("invalid action type"))
131		}
132		InstantExecute(action.dao, action.req, rlm)
133	})
134}
135
136func NewInstantExecuteAction(dao DAO, req ProposalRequest) Action {
137	return NewAction(ActionInstantExecuteKind, &actionInstantExecute{dao: dao, req: req})
138}