Skip to content
Open
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
12 changes: 10 additions & 2 deletions .github/workflows/interchaintest-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ name: ictest E2E

on:
pull_request:
branches:
- main
- master
branches-ignore:
- "mvp/**"

Comment on lines +5 to +10
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix invalid pull_request filters (branches + branches-ignore are mutually exclusive).

actionlint flags this; GitHub Actions ignores one set unpredictably. Also note: pull_request filters apply to base branch, not head. To exclude PRs from mvp/** heads, drop branches-ignore here and gate jobs with an if condition.

Apply this diff to the trigger:

   pull_request:
-    branches:
-      - main
-      - master
-    branches-ignore:
-      - "mvp/**"
+    branches:
+      - main
+      - master

Then add a job-level guard to skip PRs whose head starts with mvp/ (outside this hunk):

jobs:
  build-docker:
    if: ${{ github.event_name != 'pull_request' || !startsWith(github.head_ref, 'mvp/') }}
    ...
  e2e-tests:
    if: ${{ github.event_name != 'pull_request' || !startsWith(github.head_ref, 'mvp/') }}
    ...
🧰 Tools
🪛 actionlint (1.7.7)

8-8: both "branches" and "branches-ignore" filters cannot be used for the same event "pull_request". note: use '!' to negate patterns

(events)

🤖 Prompt for AI Agents
.github/workflows/interchaintest-e2e.yml lines 5-10: the pull_request trigger
currently uses both branches and branches-ignore which are mutually exclusive
and branches-ignore is inappropriate for filtering PR heads; remove the
branches-ignore entry and keep only the branches list under the pull_request
trigger, then add job-level guards on each job (e.g., build-docker and
e2e-tests) to skip PRs whose head ref starts with "mvp/" by using an if
condition that allows the job when the event is not pull_request or when
startsWith(github.head_ref, 'mvp/') is false (i.e., if: ${{ github.event_name !=
'pull_request' || !startsWith(github.head_ref, 'mvp/') }}).

push:
tags:
- "**"
branches:
- "main"
- "master"
- main
- master
branches-ignore:
- "mvp/**"
Comment on lines +15 to +18
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix invalid push filters (branches + branches-ignore conflict).

Use negative patterns in branches instead of branches-ignore.

   push:
     tags:
       - "**"
     branches:
-      - main
-      - master
-    branches-ignore:
-      - "mvp/**"
+      - main
+      - master
+      - '!mvp/**'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- main
- master
branches-ignore:
- "mvp/**"
push:
tags:
- "**"
branches:
- main
- master
- '!mvp/**'
🧰 Tools
🪛 actionlint (1.7.7)

17-17: both "branches" and "branches-ignore" filters cannot be used for the same event "push". note: use '!' to negate patterns

(events)

🤖 Prompt for AI Agents
.github/workflows/interchaintest-e2e.yml lines 15-18: the workflow currently
mixes branches and branches-ignore which conflicts for push filters; remove the
branches-ignore entry and replace it by using negative patterns in the branches
list (e.g., keep the allowed branches like main and master and add the negative
pattern for the mvp/** paths) so the push trigger uses only a valid branches
array with exclusion patterns.


permissions:
contents: read
Expand Down
11 changes: 11 additions & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
"github.com/bitsongofficial/go-bitsong/x/fantoken"
fantokenkeeper "github.com/bitsongofficial/go-bitsong/x/fantoken/keeper"
fantokentypes "github.com/bitsongofficial/go-bitsong/x/fantoken/types"
nftkeeper "github.com/bitsongofficial/go-bitsong/x/nft/keeper"
nfttypes "github.com/bitsongofficial/go-bitsong/x/nft/types"
"github.com/bitsongofficial/go-bitsong/x/smart-account/authenticator"
smartaccountkeeper "github.com/bitsongofficial/go-bitsong/x/smart-account/keeper"
smartaccounttypes "github.com/bitsongofficial/go-bitsong/x/smart-account/types"
Expand Down Expand Up @@ -149,6 +151,7 @@ type AppKeepers struct {
ICQKeeper *icqkeeper.Keeper
EvidenceKeeper evidencekeeper.Keeper
FanTokenKeeper fantokenkeeper.Keeper
NftKeeper nftkeeper.Keeper
WasmKeeper wasmkeeper.Keeper
CadenceKeeper cadencekeeper.Keeper
IBCFeeKeeper ibcfeekeeper.Keeper
Expand Down Expand Up @@ -406,6 +409,14 @@ func NewAppKeepers(
BlockedAddrs(),
)

appKeepers.NftKeeper = nftkeeper.NewKeeper(
appCodec,
keys[nfttypes.StoreKey],
runtime.NewKVStoreService(appKeepers.keys[nfttypes.StoreKey]),
appKeepers.AccountKeeper,
bApp.Logger(),
)

// Stargate Queries
acceptedStargateQueries := wasmkeeper.AcceptedQueries{
// ibc
Expand Down
2 changes: 2 additions & 0 deletions app/keepers/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keepers

import (
storetypes "cosmossdk.io/store/types"
nfttypes "github.com/bitsongofficial/go-bitsong/x/nft/types"

"cosmossdk.io/x/feegrant"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
Expand Down Expand Up @@ -57,6 +58,7 @@ func (appKeepers *AppKeepers) GenerateKeys() {
wasmtypes.StoreKey,
icqtypes.StoreKey,
fantokentypes.StoreKey,
nfttypes.StoreKey,
cadencetypes.StoreKey,
smartaccounttypes.StoreKey,
protocolpooltypes.StoreKey,
Expand Down
40 changes: 40 additions & 0 deletions proto/bitsong/drop/v1beta1/drop.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
syntax = "proto3";
package bitsong.drop.v1beta1;

option go_package = "github.com/bitsongofficial/go-bitsong/x/drop/types";

import "gogoproto/gogo.proto";
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Buf compile error: cannot resolve gogoproto.

The import path is correct, but buf deps list uses the wrong module name. See buf.yaml fix to use buf.build/cosmos/gogoproto.

🧰 Tools
🪛 Buf (1.55.1)

6-6: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

🤖 Prompt for AI Agents
In proto/bitsong/drop/v1beta1/drop.proto around line 6 the import
"gogoproto/gogo.proto" is correct but BUF fails because buf.yaml lists the wrong
module; open buf.yaml and replace the incorrect dependency module with the
canonical module "buf.build/cosmos/gogoproto" (or add it if missing), then run
buf mod update / buf build to fetch the dependency so the gogoproto import
resolves correctly.

import "google/protobuf/timestamp.proto";
import "amino/amino.proto";

message Template {
option (gogoproto.goproto_getters) = false;

string name = 1;
string uri = 2;
}

message Rule {
option (gogoproto.goproto_getters) = false;

uint64 id = 1;

google.protobuf.Timestamp start_time = 2
[(gogoproto.stdtime) = true, (gogoproto.nullable) = false, (amino.dont_omitempty) = true];

google.protobuf.Timestamp end_time = 3
[(gogoproto.stdtime) = true, (gogoproto.nullable) = false, (amino.dont_omitempty) = true];
}
Comment on lines +20 to +27
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Unify Rule.id type with storage and validations.

Currently proto uses uint64 but storage keys use string and you have MaxRuleIDLength. If string IDs are intended, switch proto to string; otherwise update storage to use uint64.

Option A (string IDs in proto):

-  uint64 id = 1;
+  string id = 1;

Option B (numeric IDs end-to-end): change Rules map to collections.Map[collections.Pair[string, uint64], types.Rule] and drop MaxRuleIDLength.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uint64 id = 1;
google.protobuf.Timestamp start_time = 2
[(gogoproto.stdtime) = true, (gogoproto.nullable) = false, (amino.dont_omitempty) = true];
google.protobuf.Timestamp end_time = 3
[(gogoproto.stdtime) = true, (gogoproto.nullable) = false, (amino.dont_omitempty) = true];
}
// File: proto/bitsong/drop/v1beta1/drop.proto
// —————————————————————————————————————————————
string id = 1;
google.protobuf.Timestamp start_time = 2
[(gogoproto.stdtime) = true, (gogoproto.nullable) = false, (amino.dont_omitempty) = true];
google.protobuf.Timestamp end_time = 3
[(gogoproto.stdtime) = true, (gogoproto.nullable) = false, (amino.dont_omitempty) = true];
}
🤖 Prompt for AI Agents
In proto/bitsong/drop/v1beta1/drop.proto around lines 20 to 27, the Rule.id
field is declared as uint64 but storage and validation use string keys and
MaxRuleIDLength; unify the ID type end-to-end. Either (A) change the proto field
to string and update any generated code, RPC handlers, and validations to treat
IDs as strings (remove numeric parsing and length checks remain valid), or (B)
keep numeric IDs by updating storage map types and validations to use uint64
keys (change Rules map to collections.Map[collections.Pair[string, uint64],
types.Rule] or equivalent, remove MaxRuleIDLength and any string-length
validation, and ensure all serialization/deserialization and clients
parse/format uint64 consistently). Implement the chosen option across proto
definitions, storage types, validation logic, and any client/server parsing
spots so IDs are consistently typed end-to-end.


message Drop {
option (gogoproto.goproto_getters) = false;

string collection = 1;

uint64 max_available = 2;

Template template = 3;

// Template hidden_template
// bool is_hidden
}
53 changes: 53 additions & 0 deletions proto/bitsong/nft/v1beta1/nft.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
syntax = "proto3";
package bitsong.nft.v1beta1;

import "gogoproto/gogo.proto";
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

buf: missing dependency for gogoproto; build will fail.

Add gogoproto to buf deps or vendor third_party/proto/gogoproto/gogo.proto.

Add to buf.yaml:

version: v2
deps:
  - buf.build/cosmos/gogo-proto

If you also rely on google/cosmos imports elsewhere, include:

  • buf.build/googleapis/googleapis
  • buf.build/cosmos/cosmos-proto
  • buf.build/cosmos/cosmos-sdk
🧰 Tools
🪛 Buf (1.55.1)

4-4: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

🤖 Prompt for AI Agents
In proto/bitsong/nft/v1beta1/nft.proto around line 4, the file imports
gogoproto/gogo.proto but buf.yaml has no dependency for gogoproto which will
cause builds to fail; update buf.yaml to add the gogoproto dependency
(buf.build/cosmos/gogo-proto) or vendor third_party/proto/gogoproto/gogo.proto
into the repo, and if your project also uses google/cosmos imports add the
recommended buf deps (buf.build/googleapis/googleapis,
buf.build/cosmos/cosmos-proto, buf.build/cosmos/cosmos-sdk) so the proto import
resolves during buf build.


option go_package = "github.com/bitsongofficial/go-bitsong/x/nft/types";

message Collection {
option (gogoproto.goproto_getters) = false;

string denom = 1;

string symbol = 2;
string name = 3;
string uri = 5;

Comment on lines +11 to +16
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reserve skipped field number 4 in Collection.

You’re using 1,2,3,5. Reserve 4 to prevent accidental reuse and wire incompatibility later.

 message Collection {
   option (gogoproto.goproto_getters) = false;
+  reserved 4;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
string denom = 1;
string symbol = 2;
string name = 3;
string uri = 5;
message Collection {
option (gogoproto.goproto_getters) = false;
reserved 4;
string denom = 1;
string symbol = 2;
string name = 3;
string uri = 5;
}
🤖 Prompt for AI Agents
In proto/bitsong/nft/v1beta1/nft.proto around lines 11 to 16, the Collection
message currently uses field numbers 1, 2, 3 and 5 but skips 4; reserve field
number 4 to prevent accidental reuse and wire incompatibility by adding a
reserved declaration for field number 4 inside the Collection message (e.g.,
reserve the numeric tag 4) so future changes cannot reuse that tag.

string creator = 6;
string minter = 7; // who can mint new nfts, if not set no one can mint
string authority = 8; // who can update name and uri, if not set no one can update, this is valid for the all nfts in this collection

uint64 num_tokens = 9;
}

message Nft {
option (gogoproto.goproto_getters) = false;

string collection = 1;
string token_id = 2;

string name = 3;
string uri = 5;

string owner = 6;
Comment on lines +27 to +33
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reserve skipped field number 4 in Nft.

Same rationale as Collection: protect future evolution.

 message Nft {
   option (gogoproto.goproto_getters) = false;
+  reserved 4;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
string collection = 1;
string token_id = 2;
string name = 3;
string uri = 5;
string owner = 6;
message Nft {
option (gogoproto.goproto_getters) = false;
reserved 4;
string collection = 1;
string token_id = 2;
string name = 3;
string uri = 5;
string owner = 6;
}
🤖 Prompt for AI Agents
In proto/bitsong/nft/v1beta1/nft.proto around lines 27 to 33, the Nft message is
missing a reservation for field number 4; add a reserved 4; declaration inside
the Nft message (e.g., after token_id = 2;) to explicitly reserve field number 4
so it cannot be reused in future evolutions; ensure the reserved statement uses
protobuf syntax "reserved 4;" and keep it near the other field declarations for
clarity.

// string authority = 7; // who can update name, description and uri, if not set no one can update

// TODO: add max_editions
// uint64 max_editions = 8; // max number of printed editions, 0 means no limit
uint64 editions = 7; // number of printed editions

// seller_fee_bps
// payment_address
}

message Edition {
option (gogoproto.goproto_getters) = false;

string collection = 1;
string token_id = 2;

uint64 seq = 3; // seq is the edition number

string owner = 4;
}
128 changes: 128 additions & 0 deletions proto/bitsong/nft/v1beta1/query.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
syntax = "proto3";
package bitsong.nft.v1beta1;

import "gogoproto/gogo.proto";
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

buf: missing dependency for gogoproto; build will fail.

Same as nft.proto: add gogoproto (and likely googleapis/cosmos) to buf deps or vendor the files.

Add to buf.yaml:

version: v2
deps:
  - buf.build/cosmos/gogo-proto
  - buf.build/googleapis/googleapis
  - buf.build/cosmos/cosmos-proto
  - buf.build/cosmos/cosmos-sdk
🧰 Tools
🪛 Buf (1.55.1)

4-4: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

🤖 Prompt for AI Agents
In proto/bitsong/nft/v1beta1/query.proto around line 4, the file imports
gogoproto/gogo.proto but buf build is missing that dependency so the build will
fail; update the repository's buf.yaml to include the required buf deps
(examples: buf.build/cosmos/gogo-proto, buf.build/googleapis/googleapis and any
cosmos proto/sdk repos referenced) or vendor the gogoproto and googleapis files
into the proto tree, then re-run buf mod update and buf generate to ensure
imports resolve; also verify import paths in the .proto files match the added
deps.

import "google/api/annotations.proto";
import "cosmos/query/v1/query.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "bitsong/nft/v1beta1/nft.proto";
Comment on lines +4 to +8
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

buf build will fail: missing gogoproto (and likely cosmos/google) deps

Add deps to buf.yaml (or vendor).

Example buf.yaml:

version: v2
deps:
  - buf.build/cosmos/gogo-proto
  - buf.build/googleapis/googleapis
  - buf.build/cosmos/cosmos-proto
  - buf.build/cosmos/cosmos-sdk

Then:

  • buf mod update
  • buf generate
🧰 Tools
🪛 Buf (1.55.1)

4-4: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

🤖 Prompt for AI Agents
In proto/bitsong/nft/v1beta1/query.proto around lines 4 to 8, the file imports
external proto packages (gogoproto, google api, cosmos query) but the
repository's buf.yaml lacks those deps causing buf build/generate to fail;
update buf.yaml to add the missing module dependencies (for example add entries
for gogo-proto, googleapis, and the relevant cosmos proto modules) or vendor
those protos, then run buf mod update and buf generate to fetch modules and
regenerate artifacts.


option go_package = "github.com/bitsongofficial/go-bitsong/x/nft/types";

service Query {
rpc Collection(QueryCollectionRequest) returns (QueryCollectionResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/bitsong/nft/v1beta1/collections/{collection}";
}

// TODO: rpc AllCollections(QueryAllCollectionsRequest) returns (QueryAllCollectionsResponse).....

rpc OwnerOf(QueryOwnerOfRequest) returns (QueryOwnerOfResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/bitsong/nft/v1beta1/collections/{collection}/{token_id}/owner";
}

rpc NftInfo(QueryNftInfoRequest) returns (QueryNftInfoResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/bitsong/nft/v1beta1/collections/{collection}/{token_id}";
}

rpc Nfts(QueryNftsRequest) returns (QueryNftsResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/bitsong/nft/v1beta1/collections/{collection}/nfts";
}

rpc AllNftsByOwner(QueryAllNftsByOwnerRequest) returns (QueryAllNftsByOwnerResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/bitsong/nft/v1beta1/nfts_by_owner/{owner}";
}

// Edition returns a specific edition of an nft
// OwnerOfEdition returns the owner of a specific edition
// NftEditions returns all editions of a specific nft
// AllNftEditionsByOwner returns all nft editions owned by the owner
}

message QueryCollectionRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string collection = 1;
}

message QueryCollectionResponse {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

bitsong.nft.v1beta1.Collection collection = 1;
}

message QueryOwnerOfRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string collection = 1;
string token_id = 2;
}

message QueryOwnerOfResponse {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string owner = 1;
}

message QueryNftInfoRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string collection = 1;
string token_id = 2;
}

message QueryNftInfoResponse {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

bitsong.nft.v1beta1.Nft nft = 1;
}

message QueryNftsRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string collection = 1;

cosmos.base.query.v1beta1.PageRequest pagination = 2;
}

message QueryNftsResponse {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

repeated bitsong.nft.v1beta1.Nft nfts = 1 [
(gogoproto.nullable) = false
];

cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

message QueryAllNftsByOwnerRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string owner = 1;

cosmos.base.query.v1beta1.PageRequest pagination = 2;
}

message QueryAllNftsByOwnerResponse {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

repeated bitsong.nft.v1beta1.Nft nfts = 1 [
(gogoproto.nullable) = false
];

cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
95 changes: 95 additions & 0 deletions proto/bitsong/nft/v1beta1/tx.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
syntax = "proto3";;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix proto syntax typo

Double semicolon breaks compilation.

-syntax = "proto3";;
+syntax = "proto3";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
syntax = "proto3";;
syntax = "proto3";
🤖 Prompt for AI Agents
In proto/bitsong/nft/v1beta1/tx.proto around line 1, the proto syntax
declaration has a double semicolon; replace the line `syntax = "proto3";;` with
a single semicolon `syntax = "proto3";` and then re-run your protobuf
generation/compilation step to verify the fix.

package bitsong.nft.v1beta1;

import "gogoproto/gogo.proto";
import "cosmos/msg/v1/msg.proto";
import "amino/amino.proto";
import "cosmos_proto/cosmos.proto";
Comment on lines +4 to +7
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Buf import resolution: add module deps (preferred) or vendor third_party protos

Buf error indicates missing deps. Add these to buf.yaml to resolve imports.

Example buf.yaml snippet:

version: v1
deps:
  - buf.build/cosmos/gogo-proto
  - buf.build/cosmos/cosmos-proto
  - buf.build/cosmos/amino
  - buf.build/cosmos/cosmos-sdk

Alternatively, vendor files under third_party/proto and adjust buf.yaml roots.

🧰 Tools
🪛 Buf (1.55.1)

4-4: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

🤖 Prompt for AI Agents
In proto/bitsong/nft/v1beta1/tx.proto around lines 4 to 7, the file imports
third-party protos (gogoproto, cosmos msg/amino/cosmos_proto) but Buf cannot
resolve them; update buf.yaml to add the recommended module dependencies
(buf.build entries for gogo-proto, cosmos-proto, amino, cosmos-sdk) or vendor
those third-party protos under third_party/proto and adjust buf.yaml roots
accordingly so the imports resolve during buf build.


option go_package = "github.com/bitsongofficial/go-bitsong/x/nft/types";

service Msg {
option (cosmos.msg.v1.service) = true;

rpc CreateCollection(MsgCreateCollection) returns (MsgCreateCollectionResponse);
rpc MintNFT(MsgMintNFT) returns (MsgMintNFTResponse);
rpc SendNFT(MsgSendNFT) returns (MsgSendNFTResponse);
rpc PrintEdition(MsgPrintEdition) returns (MsgPrintEditionResponse);
}

message MsgCreateCollection {
option (cosmos.msg.v1.signer) = "creator";
option (amino.name) = "cosmos-sdk/nft/MsgCreateCollection";

Comment on lines +22 to +23
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use module-specific amino names to avoid collisions

Prefix amino names with “bitsong/nft/…” rather than “cosmos-sdk/nft/…”.

-  option (amino.name) = "cosmos-sdk/nft/MsgCreateCollection";
+  option (amino.name) = "bitsong/nft/MsgCreateCollection";
@@
-  option (amino.name) = "cosmos-sdk/nft/MsgMintNFT";
+  option (amino.name) = "bitsong/nft/MsgMintNFT";
@@
-  option (amino.name) = "cosmos-sdk/nft/MsgSendNFT";
+  option (amino.name) = "bitsong/nft/MsgSendNFT";
@@
-  option (amino.name) = "cosmos-sdk/nft/MsgPrintEdition";
+  option (amino.name) = "bitsong/nft/MsgPrintEdition";

Also applies to: 42-43, 63-64, 79-80

🤖 Prompt for AI Agents
In proto/bitsong/nft/v1beta1/tx.proto around lines 22-23 (and similarly at
42-43, 63-64, 79-80), the amino.name options use the generic prefix
"cosmos-sdk/nft/…", which can cause name collisions; update each amino.name to
use the module-specific prefix "bitsong/nft/…" (e.g., replace
"cosmos-sdk/nft/MsgCreateCollection" with "bitsong/nft/MsgCreateCollection") for
all occurrences mentioned so the amino names are unique to the Bitsong NFT
module.

option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string symbol = 1;
string name = 2;
string uri = 3;

string creator = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string minter = 5 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string authority = 6 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

message MsgCreateCollectionResponse {
string denom = 1;
}

message MsgMintNFT {
option (cosmos.msg.v1.signer) = "minter";
option (amino.name) = "cosmos-sdk/nft/MsgMintNFT";

option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string collection = 1;
string token_id = 2;
string name = 3;
string uri = 4;

string minter = 5 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string recipient = 7 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

message MsgMintNFTResponse {
string collection = 1;
string token_id = 2;
}

message MsgSendNFT {
option (cosmos.msg.v1.signer) = "sender";
option (amino.name) = "cosmos-sdk/nft/MsgSendNFT";

option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string collection = 1;
string token_id = 2;

string sender = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string recipient = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

message MsgSendNFTResponse {}

message MsgPrintEdition {
option (cosmos.msg.v1.signer) = "minter";
option (amino.name) = "cosmos-sdk/nft/MsgPrintEdition";

option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string collection = 1;
string token_id = 2;

string minter = 5 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string recipient = 7 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

message MsgPrintEditionResponse {
string collection = 1;
string token_id = 2;
uint64 seq = 3;
}
Loading