Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: move the grc721 interface in p/grc/ #139

Merged
merged 1 commit into from
Apr 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions examples/gno.land/p/grc/grc721/grc721.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package grc721

import "std"

type GRC721 interface {
BalanceOf(owner std.Address) (count int64)
OwnerOf(tid TokenID) std.Address
SafeTransferFrom(from, to std.Address, tid TokenID)
TransferFrom(from, to std.Address, tid TokenID)
Approve(approved std.Address, tid TokenID)
SetApprovalForAll(operator std.Address, approved bool)
GetApproved(tid TokenID) std.Address
IsApprovedForAll(owner, operator std.Address) bool
}

type TokenID string

type TransferEvent struct {
From std.Address
To std.Address
TokenID TokenID
}

type ApprovalEvent struct {
Owner std.Address
Approved std.Address
TokenID TokenID
}

type ApprovalForAllEvent struct {
Owner std.Address
Operator std.Address
Approved bool
}
69 changes: 16 additions & 53 deletions examples/gno.land/r/nft/nft.gno
Original file line number Diff line number Diff line change
Expand Up @@ -5,80 +5,43 @@ import (
"strconv"

"gno.land/p/avl"
igrc721 "gno.land/p/grc/grc721"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it customary to name it "i"+name ?
I've been appending "m" instead, for "module". but I suppose not all packages are modules so...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the i prefix is common for packages that only define interfaces

to be honest, I opened this PR early with this first split, but I'm considering more and more to not only push the interface but the interface + a minimal (official?) implementation, so anyone can import it and use the implementation, or import it to ensure having compatibility with the interface

no strong conviction on the naming yet, it's up to you :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the i prefix is common for packages that only define interfaces

to be honest, I opened this PR early with this first split, but I'm considering more and more to not only push the interface but the interface + a minimal (official?) implementation, so anyone can import it and use the implementation, or import it to ensure having compatibility with the interface

no strong conviction on the naming yet, it's up to you :)

Copy link
Contributor

@jaekwon jaekwon Apr 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's stateless, it can still live in /p/grp, and it can be known to be "pure". so as long as the package doesn't have global variables that change value, all good. NOTE if a thing tries to modify a /p/xxx variable, upon realm finalization it panics (or it should). kinda wish gno/go would support the notion of "constant" variables for this reason.

)

//----------------------------------------
// types

type TokenID string

type GRC721 interface {
BalanceOf(owner std.Address) (count int64)
OwnerOf(tid TokenID) std.Address
SafeTransferFrom(from, to std.Address, tid TokenID)
TransferFrom(from, to std.Address, tid TokenID)
Approve(approved std.Address, tid TokenID)
SetApprovalForAll(operator std.Address, approved bool)
GetApproved(tid TokenID) std.Address
IsApprovedForAll(owner, operator std.Address) bool
}

// TODO use
type TransferEvent struct {
From std.Address
To std.Address
TokenID TokenID
}

// TODO use
type ApprovalEvent struct {
Owner std.Address
Approved std.Address
TokenID TokenID
}
type grc721 struct {
igrc721.GRC721 // implements the GRC721 interface

// TODO use
type ApprovalForAllEvent struct {
Owner std.Address
Operator std.Address
Approved bool
tokenCounter int
tokens *avl.Tree // igrc721.TokenID -> *NFToken{}
operators *avl.Tree // owner std.Address -> operator std.Address
}

type NFToken struct {
owner std.Address
approved std.Address
tokenID TokenID
tokenID igrc721.TokenID
data string
}

//----------------------------------------
// impl

type grc721 struct {
tokenCounter int
tokens *avl.Tree // TokenID -> *NFToken{}
operators *avl.Tree // owner std.Address -> operator std.Address
}

var gGRC721 = &grc721{}

func GetGRC721() *grc721 { return gGRC721 }

func (grc *grc721) nextTokenID() TokenID {
func (grc *grc721) nextTokenID() igrc721.TokenID {
grc.tokenCounter++
s := strconv.Itoa(grc.tokenCounter)
return TokenID(s)
return igrc721.TokenID(s)
}

func (grc *grc721) getToken(tid TokenID) (*NFToken, bool) {
func (grc *grc721) getToken(tid igrc721.TokenID) (*NFToken, bool) {
_, token, ok := grc.tokens.Get(string(tid))
if !ok {
return nil, false
}
return token.(*NFToken), true
}

func (grc *grc721) Mint(to std.Address, data string) TokenID {
func (grc *grc721) Mint(to std.Address, data string) igrc721.TokenID {
tid := grc.nextTokenID()
newTokens, _ := grc.tokens.Set(string(tid), &NFToken{
owner: to,
Expand All @@ -93,7 +56,7 @@ func (grc *grc721) BalanceOf(owner std.Address) (count int64) {
panic("not yet implemented")
}

func (grc *grc721) OwnerOf(tid TokenID) std.Address {
func (grc *grc721) OwnerOf(tid igrc721.TokenID) std.Address {
token, ok := grc.getToken(tid)
if !ok {
panic("token does not exist")
Expand All @@ -102,7 +65,7 @@ func (grc *grc721) OwnerOf(tid TokenID) std.Address {
}

// XXX not fully implemented yet.
func (grc *grc721) SafeTransferFrom(from, to std.Address, tid TokenID) {
func (grc *grc721) SafeTransferFrom(from, to std.Address, tid igrc721.TokenID) {
grc.TransferFrom(from, to, tid)
// When transfer is complete, this function checks if `_to` is a smart
// contract (code size > 0). If so, it calls `onERC721Received` on
Expand All @@ -111,7 +74,7 @@ func (grc *grc721) SafeTransferFrom(from, to std.Address, tid TokenID) {
// XXX ensure "to" is a realm with onERC721Received() signature.
}

func (grc *grc721) TransferFrom(from, to std.Address, tid TokenID) {
func (grc *grc721) TransferFrom(from, to std.Address, tid igrc721.TokenID) {
caller := std.GetCallerAt(2)
token, ok := grc.getToken(tid)
// Throws if `_tokenId` is not a valid NFT.
Expand All @@ -138,7 +101,7 @@ func (grc *grc721) TransferFrom(from, to std.Address, tid TokenID) {
token.owner = to
}

func (grc *grc721) Approve(approved std.Address, tid TokenID) {
func (grc *grc721) Approve(approved std.Address, tid igrc721.TokenID) {
caller := std.GetCallerAt(2)
token, ok := grc.getToken(tid)
// Throws if `_tokenId` is not a valid NFT.
Expand All @@ -164,7 +127,7 @@ func (grc *grc721) SetApprovalForAll(operator std.Address, approved bool) {
grc.operators = newOperators
}

func (grc *grc721) GetApproved(tid TokenID) std.Address {
func (grc *grc721) GetApproved(tid igrc721.TokenID) std.Address {
token, ok := grc.getToken(tid)
// Throws if `_tokenId` is not a valid NFT.
if !ok {
Expand Down
7 changes: 4 additions & 3 deletions tests/files2/zrealm_nft0.gno
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func main() {
// {
// "T": {
// "@type": "/gno.tref",
// "ID": "gno.land/r/nft.TokenID"
// "ID": "gno.land/p/grc/grc721.TokenID"
// },
// "V": {
// "@type": "/gno.vstr",
Expand Down Expand Up @@ -99,7 +99,7 @@ func main() {
// },
// "V": {
// "@type": "/gno.vref",
// "Hash": "d6f02aad674df014ea8e7057d28f345b8185fd91",
// "Hash": "cfbadf6a2492396ea5e3703c57ad9503d423cf16",
// "ObjectID": "6bde79a5f04d2658d17cbc323e45df5fad216511:6"
// }
// }
Expand Down Expand Up @@ -146,6 +146,7 @@ func main() {
// }
// u[6bde79a5f04d2658d17cbc323e45df5fad216511:4]={
// "Fields": [
// {},
// {
// "N": "AQAAAAAAAAA=",
// "T": {
Expand All @@ -172,7 +173,7 @@ func main() {
// },
// "V": {
// "@type": "/gno.vref",
// "Hash": "5bc850fde6b94814d4ab7aac069a70adb6d90ab2",
// "Hash": "97fc33e7e42903156d9bbbf78a0ede94ac6efd24",
// "ObjectID": "6bde79a5f04d2658d17cbc323e45df5fad216511:5"
// }
// }
Expand Down