Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

token.gno

2.40 Kb · 102 lines
  1package metadata
  2
  3import (
  4	"chain"
  5
  6	"gno.land/p/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/bazaar/grc721/v0"
  7)
  8
  9const Kind = "metadata"
 10
 11// NewMetadata attaches a metadata extension and registers it as a core Extension.
 12// Attach it before the first mint so every token is indexed.
 13func NewMetadata(coreLedger *grc721.PrivateLedger) (*Metadata, *Ledger) {
 14	if coreLedger == nil {
 15		panic("metadata: nil core ledger")
 16	}
 17
 18	st := &storage{}
 19	core := coreLedger.ReadToken()
 20	led := &Ledger{core: core, st: st}
 21	coreLedger.RegisterExtension(led)
 22
 23	return &Metadata{core: core, st: st}, led
 24}
 25
 26func (m *Metadata) ExtensionKind() string { return Kind }
 27
 28func (m *Metadata) TokenID() string { return m.core.ID() }
 29
 30func (m *Metadata) TokenURI(tid grc721.TokenID) (string, error) {
 31	v := m.st.uris.Get(tid.String())
 32	if v == nil {
 33		return "", ErrNoTokenURI
 34	}
 35
 36	return v.(string), nil
 37}
 38
 39func (m *Metadata) TokenMetadata(tid grc721.TokenID) (Data, error) {
 40	v := m.st.data.Get(tid.String())
 41	if v == nil {
 42		return Data{}, ErrNoMetadata
 43	}
 44
 45	return v.(Data), nil
 46}
 47
 48func (m *Metadata) HasTokenURI(tid grc721.TokenID) bool {
 49	return m.st.uris.Has(tid.String())
 50}
 51
 52func (m *Metadata) HasMetadata(tid grc721.TokenID) bool {
 53	return m.st.data.Has(tid.String())
 54}
 55
 56// SetTokenURI sets the EIP-721 tokenURI of tid; issuer-only so a holder cannot
 57// rewrite the URI after acquisition.
 58func (led *Ledger) SetTokenURI(tid grc721.TokenID, uri string) error {
 59	if _, err := led.core.OwnerOf(tid); err != nil {
 60		return ErrTokenNotMinted
 61	}
 62
 63	led.st.uris.Set(tid.String(), uri)
 64
 65	chain.Emit(
 66		TokenURIUpdateEvent,
 67		"token", led.core.ID(),
 68		"tokenId", tid.String(),
 69		"uri", uri,
 70	)
 71
 72	return nil
 73}
 74
 75// SetTokenMetadata sets the OpenSea on-chain metadata of tid; issuer-only.
 76func (led *Ledger) SetTokenMetadata(tid grc721.TokenID, data Data) error {
 77	if _, err := led.core.OwnerOf(tid); err != nil {
 78		return ErrTokenNotMinted
 79	}
 80
 81	led.st.data.Set(tid.String(), data)
 82
 83	chain.Emit(
 84		MetadataUpdateEvent,
 85		"token", led.core.ID(),
 86		"tokenId", tid.String(),
 87	)
 88
 89	return nil
 90}
 91
 92func (led *Ledger) ExtensionKind() string { return Kind }
 93
 94func (led *Ledger) OnMint(to address, tid grc721.TokenID)           {}
 95func (led *Ledger) OnTransfer(from, to address, tid grc721.TokenID) {}
 96
 97// OnBurn clears per-token state so it cannot resurface on re-mint.
 98func (led *Ledger) OnBurn(tid grc721.TokenID) {
 99	tidStr := tid.String()
100	led.st.uris.Remove(tidStr)
101	led.st.data.Remove(tidStr)
102}