PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/moul/grants/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
moul / grants
Files
9 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/moul/grants/v0
gno
0.9

Files (9)

  • README.mdmarkdown
  • gnomod.tomltoml
  • grants.gnogno
  • lifecycle.gnogno
  • program.gnogno
  • render.gnogno
  • grants_test.gnogno
  • program_test.gnogno
  • render_test.gnogno
  • program.gnogno
    1package grants23import (4	"strconv"5	"strings"6)78

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    // Program is a Board plus the money that moves around it: what came in, what
    9// went out, and the denomination it is all counted in.
    10//
    11// It still holds no coins and calls no banker. A realm hands it the current
    12// treasury balance whenever a decision depends on one, and executes the
    13// Payment it hands back. That split is the whole point: everything a grant
    14// program decides is testable without a node, and the realm on top is thin
    15// enough to read in one screen.
    16type Program struct {
    17 Board *Board
    18 Denom string
    19 Donations []Donation
    20 Payments []Payment
    21}
    22
    23// Donation is one top-up of the treasury, credited to a name.
    24type Donation struct {
    25 Height int64
    26 From address
    27 Amount int64
    28}
    29
    30// Payment is one released tranche. The ledger of these is a program's answer
    31// to "where did the money go".
    32type Payment struct {
    33 Height int64
    34 Request int
    35 Milestone int
    36 To address
    37 Amount int64
    38}
    39
    40// NewProgram returns a program whose board is seated with founders. denom is
    41// the coin everything is counted in ("ugnot" on gno.land); it is carried so a
    42// renderer can label amounts without the realm telling it twice.
    43func NewProgram(denom string, founders ...address) *Program {
    44 return &Program{Board: New(founders...), Denom: denom}
    45}
    46
    47// Fund records a top-up. The coins have already moved by the time this is
    48// called: a realm calls it to put a name next to a transfer that would
    49// otherwise be anonymous.
    50func (p *Program) Fund(from address, amount, height int64) error {
    51 if amount <= 0 {
    52 return ErrNothingSent
    53 }
    54 if !from.IsValid() {
    55 return ErrBadAddress
    56 }
    57 p.Donations = append(p.Donations, Donation{Height: height, From: from, Amount: amount})
    58 return nil
    59}
    60
    61// Apply files a grant request from a milestone spec, "design:100,ship:400".
    62// See ParseMilestones for the grammar.
    63func (p *Program) Apply(applicant address, title, body, spec string, height int64) (*Request, error) {
    64 return p.ApplyFor(applicant, applicant, "", title, body, spec, height)
    65}
    66
    67// ApplyFor is Apply for a request whose money goes to someone other than the
    68// address filing it. See Board.SubmitFor for why the reason is required.
    69func (p *Program) ApplyFor(applicant, beneficiary address, reason, title, body, spec string, height int64) (*Request, error) {
    70 ms, err := ParseMilestones(spec)
    71 if err != nil {
    72 return nil, err
    73 }
    74 return p.Board.SubmitFor(applicant, beneficiary, reason, title, body, ms, height)
    75}
    76
    77// Review casts a member's verdict on the proof under review and, when that
    78// verdict releases the tranche, records the payment and hands it back for the
    79// caller to execute.
    80//
    81// balance is what the treasury holds right now. A verdict that would release
    82// more than that is refused with ErrUnderfunded and changes NOTHING: no
    83// ballot, no release, no payment. That ordering is the reason Board.Review is
    84// not called directly by a realm. A refusal is always free to record, since it
    85// costs the treasury nothing.
    86func (p *Program) Review(voter address, id, idx int, accept bool, reason string, height, balance int64) (Outcome, *Payment, error) {
    87 if releases, out := p.Board.ReviewDecides(id, idx, voter, accept); releases && out == Accepted {
    88 if amount := p.Board.Get(id).Milestones[idx].Amount; balance < amount {
    89 return UnderReview, nil, ErrUnderfunded
    90 }
    91 }
    92
    93 out, err := p.Board.Review(voter, id, idx, accept, reason, height)
    94 if err != nil || out != Accepted {
    95 return out, nil, err
    96 }
    97
    98 r := p.Board.Get(id)
    99 pay := Payment{
    100 Height: height,
    101 Request: id,
    102 Milestone: idx,
    103 To: r.Payee(),
    104 Amount: r.Milestones[idx].Amount,
    105 }
    106 p.Payments = append(p.Payments, pay)
    107 return out, &pay, nil
    108}
    109
    110// Raised is everything ever donated through Fund.
    111func (p *Program) Raised() int64 {
    112 var n int64
    113 for _, d := range p.Donations {
    114 n += d.Amount
    115 }
    116 return n
    117}
    118
    119// Disbursed is everything ever released.
    120func (p *Program) Disbursed() int64 { return p.Board.Disbursed() }
    121
    122// Committed is what approved grants can still claim.
    123func (p *Program) Committed() int64 { return p.Board.Committed() }
    124
    125// Available is balance minus what is already promised. It goes NEGATIVE when
    126// the board has approved more than the treasury holds, which is allowed on
    127// purpose: a board that can only approve what it already has cannot approve
    128// anything before a donor shows up. Renderers say so out loud.
    129func (p *Program) Available(balance int64) int64 { return balance - p.Committed() }
    130
    131// ParseMilestones reads "design:100,ship:400" into milestones, amounts in the
    132// program's denomination, paid in the order written. A title may not contain a
    133// comma, and the amount is whatever follows the LAST colon, so
    134// "port gno:land tooling:250" parses the way it reads.
    135func ParseMilestones(spec string) ([]*Milestone, error) {
    136 out := []*Milestone{}
    137 for _, part := range strings.Split(spec, ",") {
    138 part = strings.TrimSpace(part)
    139 if part == "" {
    140 continue
    141 }
    142 i := strings.LastIndex(part, ":")
    143 if i < 0 {
    144 return nil, ErrBadSpec
    145 }
    146 amount, err := strconv.ParseInt(strings.TrimSpace(part[i+1:]), 10, 64)
    147 if err != nil {
    148 return nil, ErrBadSpec
    149 }
    150 out = append(out, NewMilestone(strings.TrimSpace(part[:i]), amount))
    151 }
    152 if len(out) == 0 {
    153 return nil, ErrBadSpec
    154 }
    155 return out, nil
    156}
    157