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/r/moul/x/social/threads/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
moul / x / social / threads
Files
5 (README)(gnomod.toml)
Exported functions
18
Module
gno.land/r/moul/x/social/threads/v0
gno
0.9
This realm implements a recognized token.THREAD →

Files (5)

  • README.mdmarkdown
  • gnomod.tomltoml
  • render.gnogno
  • threads.gnogno
  • threads_test.gnogno
README.mdPreviewRaw
# `gno.land/r/moul/x/social/threads/v0`

**A discussion block any realm can embed**, keyed on the page it appears on
rather than on the realm that stores it. Two lines in the host realm, which
stores nothing:

```go
import "gno.land/r/moul/x/social/threads/v0"

func Render(path string) string {
	return body + threads.RenderBlock()
}
```

`RenderBlock` takes no argument because it does not need one. A plain read
exported by a realm and called by another opens no realm frame, so
`unsafe.CurrentRealm()` inside it reports the **caller**: the host realm's own
path is the page key, and nothing has to be configured, registered or passed.
`RenderBlockFor(page)` is the explicit form, for a realm that renders several
pages or already holds its path as a constant. Adding a `cur realm` parameter to
either would silently reverse that and key every embed to this realm.

It is the text half of
[`r/moul/reactions`](https://github.com/moul/gno-contracts/tree/main/r/moul/reactions):
the same embed shape, the same page keys, and the same reason for existing.

## The token, and the three things it has to answer

THREAD is a GRC20 issued through
[`p/moul/x/social/coin`](https://github.com/moul/gno-contracts/tree/main/p/moul/x/social/coin),
which refuses to create a token until all three of these are written down:

| | |
|---|---|
| **mint** | 1 THREAD to a thread's author, the first time each distinct address replies to it. People, not messages, and never yourself. |
| **sink** | `Boost` burns 10 THREAD to pin a thread to the top of its page for 1,000 blocks. It is the only thing that removes supply, and the only thing the token does. |
| **buyer** | anyone who wants placement and has not earned it. They have to acquire THREAD from somebody who did, with `Transfer`. |

**Placement is the one thing a discussion has that people want and cannot all
have at once**, which is what makes it a sink worth paying for rather than a
leaderboard. A pin extends from whichever is later, now or the current pin, so
buying one never shortens somebody else's, and `Boost` charges before it pins.

**It is farmable, and saying so is cheaper than pretending otherwise**: two
addresses replying to each other mint one THREAD each per thread. The fix is a
gate on who counts as a replier, which belongs in
[`r/moul/x/social/vouch`](https://github.com/moul/gno-contracts/tree/main/r/moul/x/social/vouch)
and not here. Until then the cost of farming is one transaction per point and
the benefit is capped by what a pin is worth.

The token is registered with `r/nt/grc20reg`, so a realm that does not import
this one can still find and move it by key: `TokenKey()` returns it.

## Why this realm is not private

Every other realm in the `x/social` family is `private = true` and can be
redeployed in place. This one cannot be, twice over: a private realm cannot be
imported at all, which would delete the embed, and handing an object to another
realm (registering the token) panics at runtime from a private realm. Every
thread, balance and pin under this path belongs to the people who wrote them, so
a fix ships as a `v1` beside it rather than as a redeploy that wipes the lot.

## Reading it

`Render("")` is the index: the counts, the recent threads across every page, the
token's three declarations, and the embed snippet. `Render("page/<page key>")`
is one page's threads, `Render("thread/<id>")` is one thread with its replies and
the reply and boost buttons.

<!-- BEGIN GNOCONTRACTS FOOTER (generated by `make readmes`; do not edit below) -->

---

Part of **[moul/gno-contracts](https://github.com/moul/gno-contracts)** — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.

**On mainnet:** [![deployment status](https://gnoscope.com/_badges/shield/status/r/moul/x/social/threads/v0?network=mainnet)](https://gnoscope.com/realm/r/moul/x/social/threads/v0) [![transactions](https://gnoscope.com/_badges/shield/txs/r/moul/x/social/threads/v0?network=mainnet)](https://gnoscope.com/realm/r/moul/x/social/threads/v0) [![unique callers](https://gnoscope.com/_badges/shield/users/r/moul/x/social/threads/v0?network=mainnet)](https://gnoscope.com/realm/r/moul/x/social/threads/v0) [![deployed revision](https://gnoscope.com/_badges/shield/version/r/moul/x/social/threads/v0?network=mainnet)](https://gnoscope.com/realm/r/moul/x/social/threads/v0)

**Dependency graph:**

![gno.land/r/moul/x/social/threads/v0 dependency graph](https://raw.githubusercontent.com/moul/gno-contracts/main/_assets/gno.land/r/moul/x/social/threads/v0/deps.png)

> 🧪 **Highly experimental — potentially vibe-coded.** Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: [DISCLAIMER](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md).

<!-- END GNOCONTRACTS FOOTER -->

Functions

  • Allowance(owner string, spender string) int64

  • Approve(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, spender string, amount int64)

  • BalanceOf(owner string) int64

  • Boost(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, threadID int64)

  • Count(page string) int

  • Pages() int

  • PinnedUntil(threadID int64) int64

  • Post(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, page string, body string) int64

  • Render(path string) string

  • RenderBlock() string

  • RenderBlockFor(page string) string

  • Repliers(threadID int64) int

  • Reply(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, threadID int64, body string)

  • TokenKey() string

  • Total() int

  • TotalSupply() int64

  • Transfer(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, to string, amount int64)

  • TransferFrom(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, from string, to string, amount int64)

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

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.