Skip to content

Commit

Permalink
add nft module
Browse files Browse the repository at this point in the history
  • Loading branch information
slandymani committed Oct 9, 2024
1 parent 3a01548 commit 1ff4450
Show file tree
Hide file tree
Showing 12 changed files with 781 additions and 14 deletions.
175 changes: 175 additions & 0 deletions database/nft.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package database

import (
"bytes"
"encoding/json"
"fmt"
"io"
"strings"

"github.com/gabriel-vasile/mimetype"
shell "github.com/ipfs/go-ipfs-api"

onfttypes "github.com/ODIN-PROTOCOL/odin-core/x/onft/types"
)

func (db *Db) SaveNFTClass(class *onfttypes.Class, height int64) error {
return db.SaveNFTClasses([]*onfttypes.Class{class}, height)
}

func (db *Db) SaveNFTClasses(classes []*onfttypes.Class, height int64) error {
stmt := `INSERT INTO nft_class(id, name, symbol, description, uri, uri_hash, data, owner, metadata, height) VALUES`

var params []interface{}
for i, class := range classes {
metadata, _ := fetchMetadataFromIPFS(class.Uri)

vi := i * 10
stmt += fmt.Sprintf("($%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d),", vi+1, vi+2, vi+3, vi+4, vi+5, vi+6, vi+7, vi+8, vi+9, vi+10)
params = append(params, class.Id,
class.Name,
class.Symbol,
class.Description,
class.Uri,
class.UriHash,
class.Data,
class.Owner,
metadata,
height,
)
}

stmt = stmt[:len(stmt)-1] // Remove trailing ","
stmt += `
ON CONFLICT (id) DO UPDATE
SET name = excluded.name,
symbol = excluded.symbol,
description = excluded.description,
uri = excluded.uri,
uri_hash = excluded.uri_hash,
data = excluded.data,
owner = excluded.owner,
metadata = excluded.metadata,
height = excluded.height
WHERE nft_class.height <= excluded.height`

_, err := db.SQL.Exec(stmt, params...)
if err != nil {
return fmt.Errorf("error while storing classes: %s", err)
}
return nil
}

func (db *Db) ChangeNFTClassOwner(classID, newOwner string, height int64) error {
stmt := `UPDATE nft_class SET owner=$1, height=$2 WHERE id=$3 and height<=$2`

_, err := db.SQL.Exec(stmt, newOwner, height, classID)
if err != nil {
return fmt.Errorf("error while updating nft owner: %s", err)
}
return nil
}

func (db *Db) SaveNFT(nft *onfttypes.NFT, height int64) error {
return db.SaveNFTs([]*onfttypes.NFT{nft}, height)
}

func (db *Db) SaveNFTs(nfts []*onfttypes.NFT, height int64) error {
stmt := `INSERT INTO nft(id, class_id, uri, uri_hash, data, owner, metadata, height) VALUES`

var params []interface{}
for i, nft := range nfts {
metadata, _ := fetchMetadataFromIPFS(nft.Uri)

vi := i * 8
stmt += fmt.Sprintf("($%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d),", vi+1, vi+2, vi+3, vi+4, vi+5, vi+6, vi+7, vi+8)
params = append(params, nft.Id,
nft.ClassId,
nft.Uri,
nft.UriHash,
nft.Data,
nft.Owner,
metadata,
height,
)
}

stmt = stmt[:len(stmt)-1] // Remove trailing ","
stmt += `
ON CONFLICT (id, class_id) DO UPDATE
SET uri = excluded.uri,
uri_hash = excluded.uri_hash,
data = excluded.data,
owner = excluded.owner,
metadata = excluded.metadata,
height = excluded.height
WHERE nft.height <= excluded.height`

_, err := db.SQL.Exec(stmt, params...)
if err != nil {
return fmt.Errorf("error while storing nfts: %s", err)
}

return nil
}

func (db *Db) ChangeNFTOwner(classID, nftID, newOwner string, height int64) error {
stmt := `UPDATE nft SET owner=$1, height=$2 WHERE id=$3 and class_id=$4 and height<=$2`

_, err := db.SQL.Exec(stmt, newOwner, height, nftID, classID)
if err != nil {
return fmt.Errorf("error while updating nft owner: %s", err)
}

return nil
}

func fetchMetadataFromIPFS(cid string) (string, error) {
if cid == "" {
return "", nil
}

parts := strings.Split(cid, "/")
cid = parts[len(parts)-1]

// Connect to the local IPFS node
sh := shell.NewShell("localhost:5001") // Update with your IPFS node address if different

// Fetch the file from IPFS
reader, err := sh.Cat(cid)
if err != nil {
return "", fmt.Errorf("error while fetching file from IPFS: %w", err)
}
defer reader.Close()

// Read the content into a buffer
buf := new(bytes.Buffer)
_, err = io.Copy(buf, reader)
if err != nil {
return "", fmt.Errorf("error while reading file from IPFS: %w", err)
}

// Detect MIME type
mime := mimetype.Detect(buf.Bytes())

// Check if the MIME type indicates an image
if strings.HasPrefix(mime.String(), "image/") {
// If the file is an image, return an empty string
return "", nil
}

// If it's not an image, try to decode the content as JSON
var jsonData interface{}
err = json.Unmarshal(buf.Bytes(), &jsonData)
if err != nil {
return "", fmt.Errorf("error while parsing JSON: %w", err)
}

// Convert JSON back to a formatted string (optional)
jsonString, err := json.MarshalIndent(jsonData, "", " ")
if err != nil {
return "", fmt.Errorf("error while formatting JSON: %w", err)
}

return string(jsonString), nil
}
26 changes: 26 additions & 0 deletions database/schema/15-nft.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
CREATE TABLE nft_class
(
id TEXT PRIMARY KEY,
name TEXT,
symbol TEXT,
description TEXT,
uri TEXT,
uri_hash TEXT,
data TEXT NULL,
owner TEXT NOT NULL,
metadata TEXT,
height BIGINT NOT NULL
);

CREATE TABLE nft
(
id TEXT NOT NULL,
class_id TEXT NOT NULL REFERENCES nft_class (id),
uri TEXT,
uri_hash TEXT,
data TEXT NULL,
owner TEXT NOT NULL,
metadata TEXT,
height BIGINT NOT NULL,
PRIMARY KEY (id, class_id)
);
35 changes: 29 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ require (
cosmossdk.io/log v1.3.1
cosmossdk.io/math v1.3.0
cosmossdk.io/store v1.1.0
cosmossdk.io/x/evidence v0.1.1
cosmossdk.io/x/feegrant v0.1.1
cosmossdk.io/x/nft v0.1.1
cosmossdk.io/x/upgrade v0.1.3
github.com/ODIN-PROTOCOL/odin-core v0.9.4
github.com/ODIN-PROTOCOL/odin-core v0.10.0-rc.5
github.com/ODIN-PROTOCOL/wasmd v0.51.1
github.com/cometbft/cometbft v0.38.10
github.com/cosmos/cosmos-sdk v0.50.7
github.com/cosmos/gogoproto v1.5.0
github.com/cosmos/ibc-go/v8 v8.3.1
github.com/forbole/juno/v6 v6.0.1
github.com/gabriel-vasile/mimetype v1.4.3
github.com/go-co-op/gocron v1.37.0
github.com/golangci/golangci-lint v1.55.2
github.com/ipfs/go-ipfs-api v0.7.0
github.com/jmoiron/sqlx v1.3.5
github.com/lib/pq v1.10.9
github.com/pelletier/go-toml v1.9.5
Expand Down Expand Up @@ -48,7 +51,7 @@ require (
cosmossdk.io/core v0.11.0 // indirect
cosmossdk.io/depinject v1.0.0-alpha.4 // indirect
cosmossdk.io/x/circuit v0.1.0 // indirect
cosmossdk.io/x/nft v0.1.1 // indirect
cosmossdk.io/x/evidence v0.1.1 // indirect
cosmossdk.io/x/tx v0.13.3 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
github.com/4meepo/tagalign v1.3.3 // indirect
Expand All @@ -64,7 +67,6 @@ require (
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect
github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/ODIN-PROTOCOL/wasmd v0.51.1 // indirect
github.com/ODIN-PROTOCOL/wasmvm/v2 v2.0.18 // indirect
github.com/OpenPeeDeeP/depguard/v2 v2.1.0 // indirect
github.com/alecthomas/go-check-sumtype v0.1.3 // indirect
Expand All @@ -74,11 +76,13 @@ require (
github.com/ashanbrown/forbidigo v1.6.0 // indirect
github.com/ashanbrown/makezero v1.1.1 // indirect
github.com/aws/aws-sdk-go v1.44.224 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
github.com/bits-and-blooms/bitset v1.10.0 // indirect
github.com/bkielbasa/cyclop v1.2.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/blizzy78/varnamelen v0.8.0 // indirect
github.com/bombsimon/wsl/v3 v3.4.0 // indirect
github.com/breml/bidichk v0.2.7 // indirect
Expand All @@ -88,7 +92,7 @@ require (
github.com/butuzov/mirror v1.1.0 // indirect
github.com/catenacyber/perfsprint v0.2.0 // indirect
github.com/ccojocar/zxcvbn-go v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/charithe/durationcheck v0.0.10 // indirect
github.com/chavacava/garif v0.1.0 // indirect
Expand All @@ -111,6 +115,7 @@ require (
github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.1.1-0.20240522213455-a80c693d2262 // indirect
github.com/cosmos/ics23/go v0.10.0 // indirect
github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect
github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect
github.com/curioswitch/go-reassign v0.2.0 // indirect
github.com/daixiang0/gci v0.11.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
Expand Down Expand Up @@ -209,6 +214,8 @@ require (
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/improbable-eng/grpc-web v0.15.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/boxo v0.12.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
github.com/jgautheron/goconst v1.6.0 // indirect
github.com/jingyugao/rowserrcheck v1.1.1 // indirect
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect
Expand All @@ -219,6 +226,7 @@ require (
github.com/kisielk/gotool v1.0.0 // indirect
github.com/kkHAIKE/contextcheck v1.1.4 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/kulti/thelper v0.6.3 // indirect
Expand All @@ -227,6 +235,9 @@ require (
github.com/ldez/gomoddirectives v0.2.3 // indirect
github.com/ldez/tagliatelle v0.5.0 // indirect
github.com/leonklingele/grouper v1.1.1 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p v0.31.0 // indirect
github.com/linxGnu/grocksdb v1.8.14 // indirect
github.com/lufeee/execinquery v1.2.1 // indirect
github.com/macabu/inamedparam v0.1.2 // indirect
Expand All @@ -241,11 +252,21 @@ require (
github.com/mbilski/exhaustivestruct v1.2.0 // indirect
github.com/mgechev/revive v1.3.4 // indirect
github.com/minio/highwayhash v1.0.2 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moricho/tparallel v0.3.1 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/multiformats/go-multiaddr v0.11.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-multistream v0.4.1 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/nakabonne/nestif v0.3.1 // indirect
github.com/nishanths/exhaustive v0.11.0 // indirect
github.com/nishanths/predeclared v0.2.2 // indirect
Expand Down Expand Up @@ -289,6 +310,7 @@ require (
github.com/sonatard/noctx v0.0.2 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/sourcegraph/go-diff v0.7.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
Expand Down Expand Up @@ -327,7 +349,7 @@ require (
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.tmz.dev/musttag v0.7.2 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
Expand All @@ -352,6 +374,7 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
gotest.tools/v3 v3.5.1 // indirect
honnef.co/go/tools v0.4.6 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
mvdan.cc/gofumpt v0.5.0 // indirect
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect
Expand Down
Loading

0 comments on commit 1ff4450

Please sign in to comment.