Cosmic Bull

Build with Cosmic Bull

The reusable packages are live, verified and importable by anyone. This page walks the whole journey: an objective, the packages that fit it, when not to use them, the exact imports, real minimal examples, and how to verify every claim against the chain before you depend on it.

1. Start from an objective

The worked example on this page: build a Gno application that accepts payments, tracks bounded fees, and holds a scheduled obligation. Swap in your own objective; the journey is the same.

2. Discover the packages

Four reusable /p/ primitives are live on pearl-1. For this objective: coinio (accepting and paying out coins, safely), feeledger (balances and bounded fees, with a conservation contract), and duebook (scheduled obligations with exactly-once claims).

Machine-readable versions of everything on this site, for tooling: data/portfolio.json (the verified manifest: paths, provenance, dependencies, consumers, limitations) and api/ (the chain-derived API reference, one Markdown file per package). Both are verbatim copies of the artifacts this site is generated from.

3. Decide when — and when not — to use them

curated Each package page carries a curated summary and its known limitations; read both before composing. The one-line cautions:

When not to use them: if you need upgradeable logic (deployed bytes are immutable), non-ugnot assets beyond what coinio's denom parameter covers, or push-based payouts (everything here is pull/claim by design).

4. Import them

On gno.land the import path is the deployed address; there is no package manager and nothing to pin — the bytes at these paths can never change.

import "gno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/coinio"
import "gno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/duebook"
import "gno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/feeledger"

Declare each in your gnomod.toml module as usual.

5. Read the APIs

gnoweb's $help shows only top-level functions of a /p/ package — for these packages that hides most of the surface (types and methods). The full chain-derived API is on each package page here, coinio, duebook, feeledger, permbook, and as raw Markdown under api/.

6. Start from a real minimal example

These three live realms are the canonical minimal consumers — each exists precisely to demonstrate one primitive composed for real, and each was deployed, byte-verified and attacked on chain:

coindemothe smallest real coinio + feeledger composition: an echo-vault that receives, credits, and pays back outsource
duebook_demoa persistent duebook Book driven by real transactions: schedule, claim-exactly-once, expiresource
permbook_demoa permbook permission gate proven to open and close across blocks, with holder-vs-admin authority separationsource

For a full-scale composition, read subscriptions — plans, windowed renewals and fee handling over the same two value primitives.

7. Call a live realm

Realms are driven from the command line, and you do not need to hand-write the transaction: gnoweb generates the exact command for any exported function, with the argument names filled in — the call builder for service_registry.AcceptOwnership. It looks like this:

gnokey maketx call \
  -pkgpath gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/service_registry \
  -func AcceptOwnership \
  -gas-fee 1000000ugnot -gas-wanted 2000000 \
  -remote https://rpc.pearl.testnets.gno.land:443 \
  -chainid pearl-1 \
  <your-key>

Read-only views cost nothing to inspect; every package page links the rendered page and the state explorer. If you are integrating against a realm that moves value, read its known limitations and the linked deployment record first — those record what was not verified on chain, which is usually the part that matters.

8. Verify before you depend

Every package page carries the digest of the deployed bytes and the command that fetches them from the chain — proof that needs no trust in this site. For coinio:

curl -sS 'https://pearl.testnets.gno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/coinio$download&file=coinio.gno' | shasum -a 256

Expect ea9d467d380ff2971695d452f96fe64ea46d847d094023f755edf5f79995b09d (5,685 bytes). The same check works for every package, with its own digest on its page.

9. Compose your application

The pattern every live consumer follows: guard the payment at the door, account for it in the ledger, record the obligation, and pay out only by pull. In outline:

// A sketch of the composition -- the demo realms above are the
// full, deployed, attacked pattern. Receive guards the payment,
// the ledger holds balances and the bounded fee, the book holds
// the scheduled obligation.
var (
    ledger = feeledger.MustNew(maxFeeBps) // hard fee cap, forever
    book   = duebook.MustNew(minDelay, maxDelay, maxOpen)
)

func Pay(cur realm) {
    payer, amount := coinio.Receive(0, cur, "ugnot")
    ledger.MustDeposit(payer.String(), amount, feeBps)
    book.MustSchedule(payer.String(), payload,
        runtime.ChainHeight(), delay, ttl)
}

func Claim(cur realm, amount int64) {
    caller := cur.Previous().Address()
    if err := ledger.Withdraw(caller.String(), amount); err != nil {
        panic(err)
    }
    coinio.Payout(0, cur, caller, "ugnot", amount)
}

From here, the Verification page explains exactly what has been proved about everything you just imported — and what has not.