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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

v0 source realm

Package bolo, at v0, is Bolo: give together, and see where it goes. Each campaign's money sits at its own address, wh...

Overview

Package bolo, at v0, is Bolo: give together, and see where it goes. Each campaign's money sits at its own address, where anyone can check it. Bolo takes no fee, and nothing in Bolo can freeze a gift. Its pages start at /r/g12yg9nh4ncma44emgm8msxe8aavzywt0p95tanv/bolo/v0.

For developers: its interface is docs/API.md, its design docs/adr/0001-bolo-realm-design.md, and docs/TRACEABILITY.md maps each of their rules to the tests that hold it.

Constants 1

const ErrNotFound, ErrNotUserCall, ErrSessionKey, ErrWrongDenom, ErrBadAmount, ErrDepositMismatch, ErrPaused, ErrNotOrganizer, ErrNotBeneficiary, ErrNotAdmin, ErrCampaignClosed, ErrCampaignSettled, ErrBondSlashed, ErrNoBond, ErrHoldEnded, ErrWrongMode, ErrNothingToRefund, ErrRefundWindowClosed, ErrExitOpen, ErrNotClosable, ErrNotFinalizable, ErrNothingToWithdraw, ErrTitle, ErrDescription, ErrMessage, ErrUpdate, ErrNotice, ErrImage, ErrMarkup, ErrBeneficiary, ErrCategory, ErrMode, ErrDeadline, ErrGoal, ErrSetting, ErrSunset, ErrCapReached, ErrBooksMismatch

 1const (
 2	ErrNotFound           Error = "err.not_found: no such campaign or receipt"
 3	ErrNotUserCall        Error = "err.use_wallet: not a direct transaction from a wallet"
 4	ErrSessionKey         Error = "err.master_key: a session key can't do this"
 5	ErrWrongDenom         Error = "err.amount: only ugnot is accepted"
 6	ErrBadAmount          Error = "err.amount: the amount is wrong"
 7	ErrDepositMismatch    Error = "err.amount: send exactly the creation deposit"
 8	ErrPaused             Error = "err.paused: Bolo is paused"
 9	ErrNotOrganizer       Error = "err.not_allowed: only the organizer can do this"
10	ErrNotBeneficiary     Error = "err.not_allowed: only the beneficiary can do this"
11	ErrNotAdmin           Error = "err.not_allowed: only the admin can do this"
12	ErrCampaignClosed     Error = "err.state: the campaign is closed"
13	ErrCampaignSettled    Error = "err.state: the campaign is settled"
14	ErrBondSlashed        Error = "err.state: the bond was slashed"
15	ErrNoBond             Error = "err.state: there is no bond to slash"
16	ErrHoldEnded          Error = "err.state: the bond's hold has ended"
17	ErrWrongMode          Error = "err.mode: not for this custody mode"
18	ErrNothingToRefund    Error = "err.refund: nothing to refund"
19	ErrRefundWindowClosed Error = "err.refund: no refund window is open"
20	ErrExitOpen           Error = "err.exit_open: the exit window is open"
21	ErrNotClosable        Error = "err.not_yet: the campaign can't be closed yet"
22	ErrNotFinalizable     Error = "err.not_yet: the campaign can't be finalized yet"
23	ErrNothingToWithdraw  Error = "err.withdraw: nothing to withdraw"
24	ErrTitle              Error = "err.text: the title's length is out of bounds"
25	ErrDescription        Error = "err.text: the story's length is out of bounds"
26	ErrMessage            Error = "err.text: the message's length is out of bounds"
27	ErrUpdate             Error = "err.text: the update's length is out of bounds"
28	ErrNotice             Error = "err.text: the notice's length is out of bounds"
29	ErrImage              Error = "err.text: the photo or its description is invalid"
30	ErrMarkup             Error = "err.markup: a story or update holds no image and no raw HTML"
31	ErrBeneficiary        Error = "err.input: invalid beneficiary"
32	ErrCategory           Error = "err.input: unknown category"
33	ErrMode               Error = "err.input: invalid custody mode"
34	ErrDeadline           Error = "err.input: invalid deadline"
35	ErrGoal               Error = "err.input: invalid goal"
36	ErrSetting            Error = "err.input: invalid setting"
37	ErrSunset             Error = "err.sunset: this version takes no new campaigns"
38	ErrCapReached         Error = "err.cap: the campaign's escrow cap is reached"
39	ErrBooksMismatch      Error = "err.internal: the books exceed the bank (INV-1)"
40)
source

Functions 44

func AcceptAdmin

crossing Action
1func AcceptAdmin(cur realm)
source

AcceptAdmin makes the proposed admin the admin, and ends the proposal.

func AddCategory

crossing Action
1func AddCategory(cur realm, code string)
source

AddCategory adds a category. There is no remove and no rename: every campaign keeps a valid category.

func CanClose

Action
1func CanClose(id string, caller address) (bool, string)
source

CanClose says what Close(id), sent by caller from a wallet, would do now (API §4): true, with the reason it would record — "deadline" or "dormant" for anyone, "organizer" for the organizer alone — or false, with "closed" once closed or settled, and "not_yet" while only the organizer may close.

func CanFinalize

Action
1func CanFinalize(id string) (bool, string)
source

CanFinalize says what Finalize(id) would do now (API §4), a passed deadline counted as recorded: true with "settle" for the first settlement, or "forward" on a settled campaign with something to move; false with "open", "not_yet" while a tracked balance waits for its exit window, or "settled" with nothing to move.

func Close

crossing Action
1func Close(cur realm, id string)
source

Close closes campaign id to new donations. Its organizer can, at any time; anyone can, once it is past its deadline or inactive for long enough — the campaign's page says when. Closing stops gifts only: what the campaign holds still goes to the beneficiary, or back to its donors.

Its branch follows state, never the caller (API §3.1, Q7). Past its deadline, Close records the close if nothing has yet, and never fails. A dormant campaign closes as dormant, whoever calls. Only an open campaign nobody else may close yet takes the organizer's branch, which checks how the call arrived (C11) before it reads who sent it.

func CreateCampaign

crossing Action
1func CreateCampaign(cur realm, title, description, category, imageCID, imageAlt string, beneficiary address, goal int64, mode string, deadline int64) string
source

CreateCampaign opens a campaign, which you organize, and returns its ID. Send the creation deposit with it — Bolo's "Start a campaign" link attaches it — and it comes back when the campaign completes. title and description are public, and the description may hold links, never an image. category is one of Bolo's categories. imageCID and imageAlt are a photo on IPFS and what it shows, or both empty. beneficiary is the address the money goes to, which can never change. goal is in ugnot, 0 for none. mode is "escrow" or "direct". deadline is a Unix time, 0 for none.

It opens a campaign for its caller, the organizer (API §3.1). The envelope is exactly the creation deposit, which goes to the campaign's bond address: the realm keeps nothing (INV-3).

func Delist

crossing Action
1func Delist(cur realm, id, notice string, slash bool)
source

Delist takes the campaign off the active lists, with a public notice, and with slash moves its bond to the slashed address, where nothing ever spends it (INV-8). Delisting again replaces the notice, and may slash a bond not yet slashed.

func Donate

crossing Action
1func Donate(cur realm, id string, tip int64, message string, anonymous bool) string
source

Donate gives to campaign id, and returns your receipt's ID. Send the gift and any tip together: tip is the part of what you send that goes to Bolo, in ugnot — 0 for none. message is optional, and public. anonymous, if true, keeps your address off Bolo's pages; the chain still shows it. In a direct campaign the gift goes straight to the beneficiary; in escrow, to the campaign's escrow, until the beneficiary withdraws it.

Any user, by a direct transaction, the donor being the caller (API §3.2). The envelope is the gift plus the tip. The gift goes to the beneficiary, or to the campaign's escrow, and the tip to the tip recipient: the realm keeps nothing (INV-3), and coins found there are never credited (C4).

func Finalize

crossing Action
1func Finalize(cur realm, id string)
source

Finalize completes closed campaign id: anyone can, once the campaign's page offers it. It returns the organizer's deposit, and sends the beneficiary the coins someone sent to the escrow outside Bolo. What donors can still reclaim stays theirs.

It settles a closed campaign, and forwards what no donor is owed (API §3.4): anyone may call, with no identity. At its first call it settles the campaign; every call forwards the coins sent to the escrow outside Bolo to the beneficiary, and everything at the bond address but a bond still on hold to the organizer — the deposit, and the bond once its hold has ended. It never moves the tracked balance: that stays the donors' (INV-16).

func GetAdmin

Action
1func GetAdmin() (address, address)
source

GetAdmin returns the admin and the proposed admin, "" when there is none (API §4).

func HideImage

crossing Action
1func HideImage(cur realm, id string)
source

HideImage hides campaign id's photo, for good: its organizer can, and so can Bolo's moderator.

Its organizer may, by a direct transaction, and so may the moderator, with the master key — a DAO realm, once one holds the role, through C11's realm branch (API §3.1, §3.5). The CID stays: it is a fingerprint, and never replaced. Hiding a hidden photo, or a campaign with none, changes nothing.

func HideMessage

crossing Action
1func HideMessage(cur realm, id string, seq int64)
source

HideMessage hides one gift's message (API §3.5): visibility only. The receipt, its amount and its donor stay, and so does the stored text. Hiding a hidden message, or a receipt without one, changes nothing.

func Pause

crossing Action
1func Pause(cur realm)
source

Pause stops CreateCampaign, Donate and PostBond — money coming in, never money going out. Pausing while paused changes nothing.

func PostBond

crossing Action
1func PostBond(cur realm, id string)
source

PostBond adds what you send to campaign id's bond: a stake its organizer may post, lost if Bolo's moderator delists the campaign for fraud. It is not a guarantee. The organizer only, while the campaign is open.

It adds the envelope to the campaign's bond (API §3.1): its organizer only, by a direct transaction, while the campaign is open, its bond unslashed and Bolo not paused. The bond only grows, and the coins go on to the bond address: the realm keeps nothing (INV-3).

func PostUpdate

crossing Action
1func PostUpdate(cur realm, id, body string) string
source

PostUpdate posts an update on campaign id, shown under its story, and returns the update's number: its organizer only. body may hold links, never an image.

It appends an update to the campaign (API §3.1): its organizer only, by a direct transaction, in every status and while paused. Updates are append-only, and each resets the dormancy clock.

func ProposeAdmin

crossing Action
1func ProposeAdmin(cur realm, next address)
source

ProposeAdmin proposes next as the admin, who takes over by accepting. None of Bolo's own addresses can ever accept, so none can be proposed. A second proposal replaces the first.

func Refund

crossing Action
1func Refund(cur realm, id string) int64
source

Refund gives you back, from campaign id's escrow, what you can take back now, and returns how much: your whole gift until the beneficiary first withdraws, or, once the beneficiary's window after the campaign closes has passed, your share of what they left uncollected. The campaign's page offers it when a donor can.

It pays the caller back from their own contribution to the campaign (API §3.2, INV-13): a donor, by a direct transaction, while a refund window is open to them. The open window — no tracked withdrawal ever — pays everything not yet refunded.

func Relist

crossing Action
1func Relist(cur realm, id string)
source

Relist puts a delisted campaign back on the lists, and into the active indexes if it is still open (API §3.5). Its notice stays, as does a slash. Relisting a listed campaign changes nothing.

func Render

1func Render(path string) string
source

Render returns the markdown page for path (API §5).

func SetEscrowCap

crossing Action
1func SetEscrowCap(cur realm, max int64)
source

SetEscrowCap sets the most one campaign's tracked escrow balance may reach; 0 removes the cap. It gates gifts only, never money going out (INV-4).

func SetMinDonation

crossing Action
1func SetMinDonation(cur realm, amount int64)
source

SetMinDonation sets the smallest gift Donate accepts, in ugnot, for new gifts.

func SetNotice

crossing Action
1func SetNotice(cur realm, id, notice string)
source

SetNotice attaches a public warning to the campaign without delisting it, or clears it with "" (API §3.5). An unchanged notice changes nothing.

func SetParams

crossing Action
1func SetParams(cur realm, deposit int64, dormancyDays, exitDelayDays, bondHoldDays int)
source

SetParams sets the Params new campaigns get; every live campaign keeps its own (INV-5).

func SetPresets

crossing Action
1func SetPresets(cur realm, a, b, c, d int64)
source

SetPresets sets the four one-click amounts, in ugnot. Display only.

func SetTipRecipient

crossing Action
1func SetTipRecipient(cur realm, addr address)
source

SetTipRecipient sets where tips and swept strays go: never one of Bolo's own addresses.

func Sunset

crossing Action
1func Sunset(cur realm)
source

Sunset stops CreateCampaign for good. It names no successor: where new campaigns start is the registry's Current() (API §3.7). A second call changes nothing.

func SweepStrays

crossing Action
1func SweepStrays(cur realm) int64
source

SweepStrays sends the coins someone sent to Bolo's own address by mistake to the tip recipient, and returns how much: anyone can.

It sends the ugnot at the realm's address to the tip recipient (API §3.4). The realm holds nothing between transactions (INV-3), so all of it is strays; anyone may call, and with nothing there it sends nothing and emits nothing (Q3).

func Unpause

crossing Action
1func Unpause(cur realm)
source

Unpause lifts a pause. Unpausing while running changes nothing.

func Withdraw

crossing Action
1func Withdraw(cur realm, id string) int64
source

Withdraw sends everything campaign id's escrow holds to its beneficiary, and returns how much: the beneficiary only, until the exit window opens — the campaign's page says when.

The beneficiary only — a user by a direct transaction, or a deployed realm, through C11's realm branch (API §3.3). The tracked part counts as Withdrawn, and only it ends the open refund window; coins sent to the escrow outside Bolo go along, recorded apart.

func GetCampaign

Action
1func GetCampaign(id string) CampaignView
source

GetCampaign returns campaign id's view (API §4). An unknown or non-canonical ID is ErrNotFound (C9).

func ListByBeneficiary

Action
1func ListByBeneficiary(addr address, after string, size int) ([]CampaignView, string)
source

ListByBeneficiary returns the campaigns naming addr as beneficiary, delisted included — the beneficiary must keep seeing them (INV-4) — newest first, from below after, and the cursor to pass next.

func ListByDonor

Action
1func ListByDonor(addr address, after string, size int) ([]CampaignView, string)
source

ListByDonor returns the campaigns addr gave to at least once without anonymity, newest first, from below after, and the cursor to pass next: a campaign where all of addr's gifts were anonymous is in no index under addr.

func ListByOrganizer

Action
1func ListByOrganizer(addr address, after string, size int) ([]CampaignView, string)
source

ListByOrganizer returns the campaigns addr organizes, delisted included, newest first, from below after, and the cursor to pass next. An address is compared as given (C12).

func ListCampaigns

Action
1func ListCampaigns(after string, size int, category string) ([]CampaignView, string)
source

ListCampaigns returns the open, listed campaigns, newest first, from below after ("" for the newest), and the cursor to pass next, "" at the end; category may be "". A campaign past a deadline nobody recorded is left out (Q6). One call reads at most four times size entries, so a page can be short while the cursor isn't "".

func GetContribution

Action
1func GetContribution(id string, donor address) ContributionView
source

GetContribution returns donor's record in campaign id (API §4): zeros and no window for an address that never gave, and no window for an exit claim that rounds to 0, which Refund refuses. An address is compared as given (C12).

func GetParams

Action
1func GetParams() Params
source

GetParams returns the Params a campaign created now would get (API §4).

func GetReceipt

Action
1func GetReceipt(id string, seq int64) ReceiptView
source

GetReceipt returns gift seq of campaign id (API §4): an unknown campaign or sequence number is ErrNotFound.

func ListReceipts

Action
1func ListReceipts(id string, page, size int) []ReceiptView
source

ListReceipts returns a page of the campaign's gifts, newest first.

func ListRecent

Action
1func ListRecent(id string) []ReceiptView
source

ListRecent returns the campaign's last gifts, newest first, at most recentSize (API §4): read through the ring of sequence numbers in its hot state.

func ListRefunds

Action
1func ListRefunds(id string, page, size int) []RefundView
source

ListRefunds returns a page of the campaign's refunds, newest first.

func GetStats

Action
1func GetStats() StatsView
source

GetStats returns Bolo-wide figures (API §4). Open counts a campaign past a deadline nobody recorded until someone does (§3.1).

func ListUpdates

Action
1func ListUpdates(id string, page, size int) []UpdateView
source

ListUpdates returns a page of the campaign's updates, newest first.

func ListWithdrawals

Action
1func ListWithdrawals(id string, page, size int) []WithdrawalView
source

ListWithdrawals returns a page of the campaign's withdrawals, newest first.

Types 10

type CampaignView

struct
 1type CampaignView struct {
 2	ID, Title, Description, Category, ImageCID, ImageAlt string
 3	ImageHidden                                          bool
 4	Organizer, Beneficiary                               address
 5	Mode, Status, CloseReason                            string
 6	Listed                                               bool
 7	Notice                                               string
 8
 9	Goal      int64
10	Raised    int64
11	Refunded  int64
12	Withdrawn int64
13	NetRaised int64
14	Balance   int64
15	Untracked int64
16
17	DonorCount, DonationCount, RefundCount, UpdateCount int
18
19	Deposit          int64
20	Bond             int64
21	BondSlashed      bool
22	BondReleasableAt int64
23
24	CreatedAt, Deadline, ClosedAt, LastDonationAt, LastUpdateAt int64
25
26	ClosableByAnyoneAt int64
27	ExitOpensAt        int64
28	FinalizableAt      int64
29
30	EverWithdrawn bool
31	ExitOpen      bool
32
33	EscrowAddress address
34	BondAddress   address
35	Params        Params
36}
source

CampaignView is a campaign as clients see it (API §2.4): a copy, holding nothing of the realm's state, its derived fields computed at now without writing.

type ContributionView

struct
1type ContributionView struct {
2	Amount, Refunded, RefundableNow int64
3	Window                          string // "open", "exit", or "" for none: the window Refund would use now
4	ExitClaimed                     bool
5}
source

ContributionView is one donor's record in one campaign (API §2.4), with what Refund would pay them now: a copy.

type Error

ident
1type Error string
source

Error is the type of every failure Bolo reports (API C10, §7). Each one is a constant, never a variable another realm could reassign (C6), and its text starts with its copy key, which a client turns into a message (UI spec §8).

Methods on Error

func Error

method on Error
1func (e Error) Error() string
source

type Params

struct
1type Params struct {
2	CreationDeposit int64
3	DormancyPeriod  int64
4	ExitDelay       int64
5	BondHold        int64
6}
source

Params are the settings snapshotted into each campaign when it is created (API §2.2): its deposit and its timers never change afterwards (INV-5). Durations are in seconds.

type ReceiptView

struct
 1type ReceiptView struct {
 2	ID, CampaignID string
 3	Seq            int64
 4	Donor          address // empty when Anonymous
 5	Anonymous      bool
 6	Amount, Tip    int64
 7	Message        string // empty when MessageHidden
 8	MessageHidden  bool   // hidden by moderation; the receipt and amount stay
 9	At             int64
10	RaisedAfter    int64 // the campaign's gross total right after this gift
11	DonorRefunded  int64 // what this donor was refunded on this campaign after this gift (INV-12)
12}
source

ReceiptView is one gift, as the receipt page and the campaign page show it (API §2.4): a copy, holding nothing of the realm's state.

type RefundView

struct
1type RefundView struct {
2	Seq, Amount, At int64
3	Donor           address
4	Kind            string
5}
source

RefundView is one payout to a donor (API §2.4). Donor is empty when all of that donor's gifts to the campaign were anonymous; Kind is "open" or "exit".

type SettingsView

struct
1type SettingsView struct {
2	Version          string // "v0"
3	Presets          [4]int64
4	MaxEscrowBalance int64 // 0 = no cap
5	Categories       []string
6	TipRecipient     address
7	MinDonation      int64
8	Paused, Sunset   bool
9}
source

SettingsView is the live settings (API §2.4): a copy, holding nothing of the realm's state.

type StatsView

struct
1type StatsView struct {
2	Campaigns, Open, Settled int
3}
source

StatsView is what GetStats returns (API §2.4).

type UpdateView

struct
1type UpdateView struct {
2	Seq, At int64
3	Body    string
4}
source

UpdateView is one organizer update (API §2.4).

type WithdrawalView

struct
1type WithdrawalView struct {
2	Seq, Amount, Untracked, At int64
3	To                         address
4}
source

WithdrawalView is one payout to the beneficiary (API §2.4): its tracked amount and the coins sent outside Bolo it carried, apart.

Dependencies

Source Files 44