framelab.gno
1.58 Kb · 34 lines
1// Package framelab probes, at runtime, which realm frame pure-package code
2// executes in when a realm forwards its own `cur` into it.
3//
4// The whole instance-per-realm ("factory") pattern rests on the answer: if a
5// p/ helper acting on `cur` binds to the *importing realm's* identity, then a
6// 20-line instance realm can hold state and funds while every line of logic
7// lives in one shared pure package. If instead the frame shifts, the pattern
8// is dead and each instance has to carry its own copy of the logic.
9package framelab
10
11import "gno.land/p/nt/grc20/v0"
12
13// The leading `_ int` is mandatory, not cosmetic: gno rejects a function whose
14// FIRST parameter is `realm` when it is declared in a pure package ("crossing
15// function declared in non-realm package"). Same reason grc20's Teller methods
16// are shaped `Transfer(_ int, rlm realm, ...)`. The name matters too: only the
17// first realm argument of a real crossing function may be called `cur`.
18//
19// Who reports the frame identity as seen from inside pure-package code.
20func Who(_ int, rlm realm) (pkgPath string, addr address, isCurrent bool) {
21 return rlm.PkgPath(), rlm.Address(), rlm.IsCurrent()
22}
23
24// Pull performs the operation the pattern actually needs: a GRC20 pull done by
25// pure-package code, under the importing realm's identity. It returns the
26// address the teller bound to, which is the claim under test.
27func Pull(_ int, rlm realm, tok *grc20.Token, from address, amount int64) address {
28 self := rlm.Address()
29 err := tok.RealmTeller(0, rlm).TransferFrom(0, rlm, from, self, amount)
30 if err != nil {
31 panic(err)
32 }
33 return self
34}