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

memba_feed_v1 source realm

Constants 1

const MaxBodyLen, MaxMediaCIDs, MaxCIDLen, FeedPageSize, MaxPageLimit, MaxRenderPage, MaxRepliesPerPost, FlagThreshold, MinAccountAgeForFlag, FlagsPerDayBudget, BlocksPerDay, MinPostIntervalBlocks, YoungMinPostIntervalBlocks, YoungAccountBlocks

 1const (
 2	MaxBodyLen   = 1000 // post body (roadmap 4.1)
 3	MaxMediaCIDs = 4    // stored per post; pin/serve pipeline is P2
 4	MaxCIDLen    = 128  // defensive cap on a single CID string
 5
 6	FeedPageSize  = 20  // posts per rendered page / default JSON window
 7	MaxPageLimit  = 100 // hard cap on any JSON read window (DoS guard)
 8	MaxRenderPage = 50  // deepest gnoweb page; beyond → use the cursor API
 9
10	// B1 reply bound (mirrors channels_v2's MaxRepliesPerThread). Caps the
11	// LIVE reply set per post so (a) the byParent index under any one parent is
12	// bounded, and (b) SweepTombstones can range-delete a swept parent's reply
13	// links in bounded work. Deleting a reply frees a slot.
14	MaxRepliesPerPost = 500
15
16	// Flag pipeline. channels_v2 auto-hides at 3 member flags; the feed is
17	// open-write, so the threshold starts higher and flagging is rate-limited.
18	// These are damping knobs, not a brigade-proof gate: 5 aged sybils can
19	// still hide a post (the age gate is one post + a one-time wait, farmable
20	// in parallel). They raise the cost and slow coordination; genuine brigade
21	// resistance is the W8.2 moderation board (reversible mod actions + audit).
22	// All are governance-tunable post-deploy via a future realm version; they
23	// are constants here so the adversarial tests pin their behavior.
24	FlagThreshold        = 5     // unique flags before auto-hide
25	MinAccountAgeForFlag = 1200  // blocks since first post (~1-2h)
26	FlagsPerDayBudget    = 10    // per address per BlocksPerDay window
27	BlocksPerDay         = 17280 // ~5s blocks; approximation is fine
28
29	// Posting cooldowns (blocks). Young accounts (first seen < YoungAccountBlocks
30	// ago) wait longer between posts — cheap sybil throttle.
31	MinPostIntervalBlocks      = 2
32	YoungMinPostIntervalBlocks = 12
33	YoungAccountBlocks         = 17280 // first ~day
34)
source

Functions 24

func AddModerator

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

AddModerator grants the moderator role (owner only).

func AddReaction

crossing Action
1func AddReaction(cur realm, id uint64, emoji string)
source

AddReaction records the caller's emoji reaction. A repeat aborts (rather than no-op) so an optimistic client's double-tap cannot silently burn gas twice — the client gates the button on HasReacted / indexed state.

func CreatePost

crossing Action
1func CreatePost(cur realm, body string, replyTo uint64) uint64
source

CreatePost publishes a post (replyTo == 0) or a reply (replyTo == parent id). Open write: any wallet, subject to the block cooldown and body caps. Returns the new post id.

func DeletePost

crossing Action
1func DeletePost(cur realm, id uint64)
source

DeletePost soft-deletes the author's own post: content cleared, dropped from every live index (frees render slots immediately — B1), queued for hard-GC (B2). Replies stay: they render as replies to an unavailable post.

func EditPost

crossing Action
1func EditPost(cur realm, id uint64, newBody string)
source

EditPost lets the author replace the body of a visible post.

func FlagPost

crossing Action
1func FlagPost(cur realm, id uint64)
source

FlagPost files a community flag. Guards, in order:

  • flag rights are EARNED BY PARTICIPATION: the caller must have a firstSeen record (anchored by their first successful CreatePost) at least MinAccountAgeForFlag blocks old. A failed flag cannot anchor age itself — an on-chain abort reverts every write in the tx, so recording firstSeen here and then panicking would revert the record and deadlock pure flaggers; requiring a prior post is the honest, implementable account-age gate (realms cannot query global account age);
  • one flag per address per post;
  • per-day flag budget per address (blunts coordinated flag-brigades).

At FlagThreshold unique flags the post auto-hides (reversible via UnhidePost).

func GetPostJSON

Action
1func GetPostJSON(id uint64) string
source

GetPostJSON returns one post (any state — the indexer needs tombstones too).

func GetStatsJSON

Action
1func GetStatsJSON() string
source

GetStatsJSON returns realm-level counters (monotonic id is informational — no read iterates it).

func HasReacted

Action
1func HasReacted(id uint64, emoji string, addr address) bool
source

HasReacted reports whether addr currently has the given emoji on the post. O(log n) point lookup — never a scan.

func IsModerator

Action
1func IsModerator(addr address) bool
source

IsModerator reports whether addr currently holds the moderator role.

func ListFeedJSON

Action
1func ListFeedJSON(cursor uint64, limit int) string
source

ListFeedJSON returns the newest live posts strictly older than cursor (cursor == 0 → from the top). Pass the last id of the previous window as the next cursor.

ReverseIterate treats BOTH bounds as inclusive (avl/v0 TraverseInRange), so "strictly older than cursor" = end bound padID(cursor-1): ids are integers, keys are fixed-width, hence key < padID(cursor) ⟺ key ≤ padID(cursor-1).

func ListRepliesJSON

Action
1func ListRepliesJSON(parent uint64, cursor uint64, limit int) string
source

ListRepliesJSON returns a post's live replies, OLDEST first (conversation order), starting strictly after cursor (0 → from the beginning).

func ListUserJSON

Action
1func ListUserJSON(addr string, cursor uint64, limit int) string
source

ListUserJSON returns a user's newest live posts strictly older than cursor (same inclusive-bound rule as ListFeedJSON).

func ModRemovePost

crossing Action
1func ModRemovePost(cur realm, id uint64)
source

ModRemovePost permanently hides a post by moderation. Emits an audited ModAction. The node is tombstoned for hard-GC like an author delete.

func RemoveModerator

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

RemoveModerator revokes the moderator role (owner only).

func RemoveReaction

crossing Action
1func RemoveReaction(cur realm, id uint64, emoji string)
source

RemoveReaction removes the caller's emoji reaction (toggle-off). Allowed even on a hidden/deleted post so a reactor can always retract; aborts if the caller had not reacted with that emoji.

func SweepTombstones

crossing Action
1func SweepTombstones(cur realm, limit int) int
source

SweepTombstones hard-removes up to `limit` soft-deleted posts, reclaiming AVL storage so post+delete spam cannot accrete permanent state. Permissionless by design (state-shrink hygiene primitive, not a refund path). Bounded + idempotent: keep `limit` small (1-10); re-running drains the next batch and stops at 0. Returns the number of posts swept.

For a swept post that was a PARENT, its surviving replies' byParent links (`padID(parent):padID(child)`) would otherwise be orphaned under an id no longer in `posts` — a permanent leak plus a read inconsistency (replies still enumerable, getReplyCount() disagreeing). So the sweep range-deletes that byParent prefix; the reply posts themselves stay as standalone live content (their parent was removed by its own author). Bounded because the live reply set per post is capped at MaxRepliesPerPost — but a reply-heavy parent makes one sweep step do up to that many removes, so keep `limit` small (1) when draining known reply-heavy tombstones.

func TransferOwnership

crossing Action
1func TransferOwnership(cur realm, newOwner address)
source

TransferOwnership moves realm ownership (deployer multisig rotation).

func UnhidePost

crossing Action
1func UnhidePost(cur realm, id uint64)
source

UnhidePost clears flags and restores a flag-hidden post to the live set.

Types 1

type Post

struct
 1type Post struct {
 2	ID        uint64
 3	Author    address
 4	Body      string
 5	MediaCIDs []string // IPFS CIDs only; serving goes through the backend proxy
 6	ReplyTo   uint64   // 0 = top-level
 7	RepostOf  uint64   // 0 = original (entrypoint lands in P1; field is schema-stable)
 8	BlockH    int64
 9	EditedAt  int64 // block height of last edit (0 = never)
10	FlagCount int
11	Hidden    bool // flag auto-hide or moderation hide
12	Deleted   bool // author tombstone (awaiting SweepTombstones hard-GC)
13}
source

Imports 7

Source Files 2