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.

v1 source realm

Package gnosplit shares a group's expenses, like Tricount: who paid what, who owes whom, and the fewest transfers tha...

Overview

Package gnosplit shares a group's expenses, like Tricount: who paid what, who owes whom, and the fewest transfers that settle everything.

A group has members, each a name with or without a wallet. Members with a wallet linked are the group's editors: they record expenses, incomes and transfers, and get a gnotif notification when one concerns them. Members without one are just names: a friend with no wallet still has a balance.

Amounts are cents of the group's currency, a label such as "€" or "CHF": no coin moves here, a transfer records a payment made elsewhere. Every balance is kept up to date on each write, so reading a group never adds up its history.

Constants 2

const EventGroupCreated, EventMemberAdded, EventMemberLinked, EventEntryAdded, EventEntryDeleted, EventGroupMoved, EventOwnerOffered, EventOwnerChanged, EventSuccessorSet, NotifyExpense, NotifyIncome, NotifyTransfer, NotifyReminder, NotifyJoined

 1const (
 2	EventGroupCreated = "GroupCreated"
 3	EventMemberAdded  = "MemberAdded"
 4	EventMemberLinked = "MemberLinked"
 5	EventEntryAdded   = "EntryAdded"
 6	EventEntryDeleted = "EntryDeleted"
 7	EventGroupMoved   = "GroupMoved"
 8	EventOwnerOffered = "OwnerOffered"
 9	EventOwnerChanged = "OwnerChanged"
10	EventSuccessorSet = "SuccessorSet"
11
12	NotifyExpense  = "Expense"  // to, group, gname, by, title, share
13	NotifyIncome   = "Income"   // to, group, gname, by, title, share
14	NotifyTransfer = "Transfer" // to, group, gname, from, peer, amount
15	NotifyReminder = "Reminder" // to, group, gname, by, amount
16	NotifyJoined   = "Joined"   // to, group, gname, by
17)
source

Events. The first ones say what changed, for indexers and apps. The notify ones each carry "to", a wallet: gnotif turns them into a browser notification for whoever opted in with that address. A notify event goes only to members with a wallet, never to the member who acted.

Functions 18

func Accept

crossing Action
1func Accept(cur realm)
source

Accept takes the role a Transfer offered the caller.

func AddByAmounts

crossing Action
1func AddByAmounts(cur realm, group, title, paidBy, amounts, category string) int
source

AddByAmounts records an expense split by exact amounts: amounts is "Alice:12.50, Bob:7.50", and the expense is their sum.

func AddByShares

crossing Action
1func AddByShares(cur realm, group, title, amount, paidBy, shares, category string) int
source

AddByShares records an expense split by shares: shares is "Alice:2, Bob:1", so Alice owes two thirds.

func AddExpense

crossing Action
1func AddExpense(cur realm, group, title, amount, paidBy, forWhom, category string) int
source

AddExpense records that paidBy paid amount for forWhom (comma-separated names, "" for everyone), split equally. amount is "42.50", or a foreign amount with its rate, "50 USD x0.92". It returns the entry's ID.

func AddIncome

crossing Action
1func AddIncome(cur realm, group, title, amount, receivedBy, forWhom string) int
source

AddIncome records money receivedBy got on behalf of forWhom (a refund, a deposit returned), split equally: it lowers what each of them paid.

func AddMember

crossing Action
1func AddMember(cur realm, group, name, addr string)
source

AddMember adds name to the group, with a wallet if addr is set: that member becomes an editor and is told by gnotif.

func AddTransfer

crossing Action
1func AddTransfer(cur realm, group, from, to, amount string) int
source

AddTransfer records that from paid amount to to, outside the chain.

func CreateGroup

crossing Action
1func CreateGroup(cur realm, name, currency, you, others string) int
source

CreateGroup opens a group named name, counting in currency, with the caller as member you (wallet linked) and others, comma-separated names, without wallets. It returns the group's ID.

func Delete

crossing Action
1func Delete(cur realm, group, entry string)
source

Delete removes an entry and undoes its effect on every balance.

func Export

Action
1func Export(group string) string
source

Export writes a group as CSV: its members, then every entry, oldest first. MoveOut hands it to the successor, and the /csv page shows it.

func LinkMember

crossing Action
1func LinkMember(cur realm, group, name, addr string)
source

LinkMember links a wallet to a member who has none yet, making them an editor. A linked wallet is never replaced, so no editor can take over another's place.

func MoveOut

crossing Action
1func MoveOut(cur realm, group string) string
source

MoveOut marks a group as taken over and returns it, as Export writes it. Only the successor realm can call it, which decides when a group moves (when one of its editors asks). The group stays readable here, frozen.

func Remind

crossing Action
1func Remind(cur realm, group, member string)
source

Remind sends member, who owes the group, a gnotif reminder: at most one every 12 hours, and only to a member with a wallet.

func Render

1func Render(path string) string
source

Render serves "" (home), "u/<address>" (a wallet's groups) and a group's pages: "<id>", then "/add", "/settle", "/settle/<from>/<to>/<cents>", "/members", "/stats", "/history[/<page>]", "/e/<entry>" and "/csv".

func SetSuccessor

crossing Action
1func SetSuccessor(cur realm, pkgpath string)
source

SetSuccessor names the release that takes groups over, once: a realm under this one's namespace, like gno.land/r/<ns>/gnosplit/v2. From then on that realm can move a group with MoveOut; nothing moves by itself.

func Successor

Action
1func Successor() string
source

Successor is the pkgpath of the release that takes groups over, "" if none.

func Transfer

crossing Action
1func Transfer(cur realm, to address)
source

Transfer offers the role to another address, which takes it with Accept.

Types 4

type Entry

struct
 1type Entry struct {
 2	ID    int
 3	Kind  Kind
 4	Title string
 5	Cat   int
 6	Payer int
 7	Total int64
 8	Note  string // the foreign amount, "" if none
 9	Who   []int
10	Owe   []int64
11	At    int64
12	By    address
13}
source

Entry is one expense, income or transfer. Owe[i] is the part of Who[i]; the parts sum to Total. An income stores Total and Owe as negative amounts, so one rule applies every kind: Payer gains Total, each of Who loses its part.

type Group

struct
 1type Group struct {
 2	ID       int
 3	Name     string
 4	Currency string
 5	Members  []Member
 6	Entries  avl.Tree // key(ID) → *Entry
 7	Next     int      // the next entry's ID
 8	Spent    int64    // expenses minus incomes, for the header
 9	ByCat    []int64  // expenses per category, incomes left out
10	Created  int64
11	Moved    bool // taken over by the successor realm: read-only here
12}
source

Group is one shared account.

type Kind

ident
1type Kind uint8
source

Kind is what an entry records.

type Member

struct
1type Member struct {
2	Name   string
3	Addr   address // "" while no wallet is linked
4	Bal    int64
5	Paid   int64 // total of the expenses they paid, net of incomes received
6	Share  int64 // total of their shares of expenses, net of incomes
7	Nudged int64 // when they were last reminded, unix seconds
8}
source

Member is one person in a group. Bal is what they paid minus what they owe, in cents: > 0 the group owes them, < 0 they owe the group.

Dependencies

Source Files 5