1// PKGPATH: gno.land/r/demo/grc721veto23// Extension hooks run before the Transfer event is emitted, so a hook that vetoes4// a movement leaves nothing on the event stream. Only the second mint, which no5// hook refuses, is announced.6package grc721veto78import (9 "gno.land/p/nt/grc721/v0"10)1112type vetoExtension struct {13 refuse grc721.TokenID14}1516func (e *vetoExtension) ExtensionKind() string { return "veto" }1718func (e *vetoExtension) OnMint(to address, tid grc721.TokenID) {19 if tid == e.refuse {20 panic("veto: mint refused")21 }22}2324func (e *vetoExtension) OnTransfer(from, to address, tid grc721.TokenID) {}2526func (e *vetoExtension) OnBurn(tid grc721.TokenID) {}2728func main(cur realm) {29 _, ledger := grc721.NewToken("Veto", "VETO", 0, cur)30 ledger.RegisterExtension(&vetoExtension{refuse: "1"})3132 func() {33 defer func() { println("recovered:", recover()) }()34 ledger.Mint(cur.Address(), "1")35 }()3637 ledger.Mint(cur.Address(), "2")38}3940// Output:41// recovered: veto: mint refused4243// Events:44// [45// {46// "type": "NewToken",47// "attrs": [48// {49// "key": "token",50// "value": "gno.land/r/demo/grc721veto.VETO.0000000"51// },52// {53// "key": "name",54// "value": "Veto"55// },56// {57// "key": "symbol",58// "value": "VETO"59// }60// ],61// "pkg_path": "gno.land/p/nt/grc721/v0"62// },63// {64// "type": "Transfer",65// "attrs": [66// {67// "key": "token",68// "value": "gno.land/r/demo/grc721veto.VETO.0000000"69// },70// {71// "key": "from",72// "value": ""73// },74// {75// "key": "to",76// "value": "g1dywcn8v2jdpl6fuks8tw3l8gnzer0hv8mfkraa"77// },78// {79// "key": "tokenId",80// "value": "2"81// }82// ],83// "pkg_path": "gno.land/p/nt/grc721/v0"84// }85// ]86Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.