diff --git a/services/BasicTypes.proto b/services/BasicTypes.proto
index e04fa943..2d7b4ee5 100644
--- a/services/BasicTypes.proto
+++ b/services/BasicTypes.proto
@@ -85,10 +85,18 @@ message TransferList {
repeated AccountAmount accountAmounts = 1; // Multiple list of AccountAmount pairs, each of which has an account and an amount to transfer into it (positive) or out of it (negative)
}
+/* A sender account, a receiver account, and the serial number of an NFT of a Token with NON_FUNGIBLE_UNIQUE type. */
+message NftTransfer {
+ AccountID senderAccountID = 1; // The accountID of the sender
+ AccountID receiverAccountID = 2; // The accountID of the receiver
+ int64 serialNumber = 3; // The serial number of the NFT
+}
+
/* A list of token IDs and amounts representing the transferred out (negative) or into (positive) amounts, represented in the lowest denomination of the token */
message TokenTransferList {
TokenID token = 1; // The ID of the token
- repeated AccountAmount transfers = 2; // Multiple list of AccountAmounts, each of which has an account and amount
+ repeated AccountAmount transfers = 2; // Applicable to tokens of type FUNGIBLE_COMMON. Multiple list of AccountAmounts, each of which has an account and amount
+ repeated NftTransfer nftTransfers = 3; // Applicable to tokens of type NON_FUNGIBLE_UNIQUE. Multiple list of NftTransfers, each of which has a sender and receiver account, including the serial number of the NFT
}
/* Unique identifier for a topic (used by the consensus service) */
@@ -112,6 +120,44 @@ message ScheduleID {
int64 scheduleNum = 3; // A nonnegative schedule number
}
+/**
+ * Possible Token Types (IWA Compatibility).
+ * Apart from fungible and non-fungible, Tokens can have either a common or unique representation. This distinction might seem subtle, but it is important when considering
+ * how tokens can be traced and if they can have isolated and unique properties.
+ */
+enum TokenType {
+ /**
+ * Interchangeable value with one another, where any quantity of them has the same value as another equal quantity if they are in the same class.
+ * Share a single set of properties, not distinct from one another. Simply represented as a balance or quantity to a given Hedera account.
+ */
+ FUNGIBLE_COMMON = 0;
+ /**
+ * Unique, not interchangeable with other tokens of the same type as they typically have different values.
+ * Individually traced and can carry unique properties (e.g. serial number).
+ */
+ NON_FUNGIBLE_UNIQUE = 1;
+}
+
+
+/**
+ * Possible FeeData Object SubTypes. Supplementary to the main HederaFunctionality Type.
+ * When not explicitly specified, DEFAULT is used.
+ */
+enum SubType {
+ DEFAULT = 0;
+ TOKEN_FUNGIBLE_COMMON = 1;
+ TOKEN_NON_FUNGIBLE_UNIQUE = 2;
+}
+
+/**
+ * Possible Token Supply Types (IWA Compatibility).
+ * Indicates how many tokens can have during its lifetime.
+ */
+enum TokenSupplyType {
+ INFINITE = 0; // Indicates that tokens of that type have an upper bound of Long.MAX_VALUE.
+ FINITE = 1; // Indicates that tokens of that type have an upper bound of maxSupply, provided on token creation.
+}
+
/* Possible Freeze statuses returned on TokenGetInfoQuery or CryptoGetInfoResponse in TokenRelationship */
enum TokenFreezeStatus {
FreezeNotApplicable = 0;
@@ -162,7 +208,7 @@ message KeyList {
/* A Signature corresponding to a Key. It is a sequence of bytes holding a public key signature from one of the three supported systems (ed25519, RSA-3072, ECDSA with p384). Or, it can be a list of signatures corresponding to a single threshold key. Or, it can be the ID of a smart contract instance, which is authorized to act as if it had a key. If an account has an ed25519 key associated with it, then the corresponding private key must sign any transaction to transfer cryptocurrency out of it. If it has a smart contract ID associated with it, then that smart contract is allowed to transfer cryptocurrency out of it. The smart contract doesn't actually have a key, and doesn't actually sign a transaction. But it's as if a virtual transaction were created, and the smart contract signed it with a private key. A key can also be a "threshold key", which means a list of M keys, any N of which must sign in order for the threshold signature to be considered valid. The keys within a threshold signature may themselves be threshold signatures, to allow complex signature requirements (this nesting is not supported in the currently, but will be supported in a future version of API). If a Signature message is missing the "signature" field, then this is considered to be a null signature. That is useful in cases such as threshold signatures, where some of the signatures can be null.
* The definition of Key uses mutual recursion, so it allows nesting that is arbitrarily deep. But the current API only accepts Key messages up to 3 levels deep, such as a list of threshold keys, each of which is a list of primitive keys. Therefore, the matching Signature will have the same limitation. This restriction may be relaxed in future versions of the API, to allow deeper nesting.
- * This message is deprecated and succeeded by SignaturePair and SignatureMap messages.
+ * This message is deprecated and succeeded by SignaturePair and SignatureMap messages.
*/
message Signature {
option deprecated = true;
@@ -282,6 +328,9 @@ enum HederaFunctionality {
ScheduleDelete = 71; // Delete Scheduled Transaction
ScheduleSign = 72; // Sign Scheduled Transaction
ScheduleGetInfo = 73; // Get Scheduled Transaction Information
+ TokenGetAccountNftInfo = 74; // Get Token Account Nft Information
+ TokenGetNftInfo = 75; // Get Token Nft Information
+ TokenGetNftInfos = 76; // Get Token Nft List Information
}
/*
@@ -307,7 +356,9 @@ message TransactionFeeSchedule {
// A particular transaction or query
HederaFunctionality hederaFunctionality = 1;
// Resource price coefficients
- FeeData feeData = 2;
+ FeeData feeData = 2 [deprecated=true];
+ // Resource price coefficients. Supports subtype price definition.
+ repeated FeeData fees = 3;
}
/*
@@ -320,6 +371,8 @@ message FeeData {
FeeComponents networkdata = 2;
// Fee paid to the network for providing the service associated with the transaction; for instance, storing a file
FeeComponents servicedata = 3;
+ // SubType distinguishing between different types of FeeData, correlating to the same HederaFunctionality
+ SubType subType = 4;
}
/*
@@ -338,7 +391,7 @@ message CurrentAndNextFeeSchedule {
FeeSchedule nextFeeSchedule = 2; // Contains next Fee Schedule
}
-/*
+/*
Contains the IP address and the port representing a service endpoint of a Node in a network. Used to reach the Hedera API and submit transactions to the network.
*/
message ServiceEndpoint {
@@ -346,12 +399,12 @@ message ServiceEndpoint {
int32 port = 2; // The port of the node
}
-/*
-The data about a node, including its service endpoints and the Hedera account to be paid for services
-provided by the node (that is, queries answered and transactions submitted.)
+/*
+The data about a node, including its service endpoints and the Hedera account to be paid for services
+provided by the node (that is, queries answered and transactions submitted.)
If the serviceEndpoint list is not set, or empty, then the endpoint given by the (deprecated)
-ipAddress and portno fields should be used.
+ipAddress and portno fields should be used.
All fields are populated in the 0.0.102 address book file while only fields that start with # are populated in the 0.0.101 address book file.
*/
@@ -377,10 +430,15 @@ message NodeAddressBook {
repeated NodeAddress nodeAddress = 1; // Metadata of all nodes in the network
}
+/* Hedera follows semantic versioning (https://semver.org/) for both the HAPI protobufs and the Services software.
+This type allows the getVersionInfo query in the NetworkService to return the deployed versions
+of both protobufs and software on the node answering the query. */
message SemanticVersion {
- int32 major = 1; // Increases with incompatible API changes
- int32 minor = 2; // Increases with backwards-compatible new functionality
- int32 patch = 3; // Increases with backwards-compatible bug fixes
+ int32 major = 1; // Increases with incompatible API changes
+ int32 minor = 2; // Increases with backwards-compatible new functionality
+ int32 patch = 3; // Increases with backwards-compatible bug fixes
+ string pre = 4; // A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers (https://semver.org/#spec-item-9); so given a semver 0.14.0-alpha.1+21AF26D3, this field would contain 'alpha.1'
+ string build = 5; // Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version (https://semver.org/#spec-item-10); so given a semver 0.14.0-alpha.1+21AF26D3, this field would contain '21AF26D3'
}
message Setting {
@@ -397,7 +455,7 @@ message ServicesConfigurationList {
message TokenRelationship {
TokenID tokenId = 1; // The ID of the token
string symbol = 2; // The Symbol of the token
- uint64 balance = 3; // The balance that the Account holds in the smallest denomination
+ uint64 balance = 3; // For token of type FUNGIBLE_COMMON - the balance that the Account holds in the smallest denomination. For token of type NON_FUNGIBLE_UNIQUE - the number of NFTs held by the account
TokenKycStatus kycStatus = 4; // The KYC status of the account (KycNotApplicable, Granted or Revoked). If the token does not have KYC key, KycNotApplicable is returned
TokenFreezeStatus freezeStatus = 5; // The Freeze status of the account (FreezeNotApplicable, Frozen or Unfrozen). If the token does not have Freeze key, FreezeNotApplicable is returned
uint32 decimals = 6; // Tokens divide into 10decimals pieces
@@ -410,7 +468,7 @@ The transferable unit of a token is its smallest denomination, as given by the t
Transferable units are not directly comparable across different tokens. */
message TokenBalance {
TokenID tokenId = 1; // A unique token id
- uint64 balance = 2; // A number of transferable units of the identified token
+ uint64 balance = 2; // Number of transferable units of the identified token. For token of type FUNGIBLE_COMMON - balance in the smallest denomination. For token of type NON_FUNGIBLE_UNIQUE - the number of NFTs held by the account
uint32 decimals = 3; // Tokens divide into 10decimals pieces
}
diff --git a/services/CryptoGetInfo.proto b/services/CryptoGetInfo.proto
index a37cd9a4..4c7695da 100644
--- a/services/CryptoGetInfo.proto
+++ b/services/CryptoGetInfo.proto
@@ -60,6 +60,7 @@ message CryptoGetInfoResponse {
repeated LiveHash liveHashes = 14; // All of the livehashes attached to the account (each of which is a hash along with the keys that authorized it and can delete it)
repeated TokenRelationship tokenRelationships = 15; // All tokens related to this account
string memo = 16; // The memo associated with the account
+ int64 ownedNfts = 17; // The number of NFTs owned by this account
}
AccountInfo accountInfo = 2; // Info about the account (a state proof can be generated for this)
}
diff --git a/services/Query.proto b/services/Query.proto
index e5b8e150..e966f0dd 100644
--- a/services/Query.proto
+++ b/services/Query.proto
@@ -52,6 +52,10 @@ import "NetworkGetVersionInfo.proto";
import "TokenGetInfo.proto";
import "ScheduleGetInfo.proto";
+import "TokenGetAccountNftInfo.proto";
+import "TokenGetNftInfo.proto";
+import "TokenGetNftInfos.proto";
+
/* A single query, which is sent from the client to a node. This includes all possible queries. Each Query should not have more than 50 levels. */
message Query {
oneof query {
@@ -81,5 +85,9 @@ message Query {
TokenGetInfoQuery tokenGetInfo = 52; // Get all information about a token
ScheduleGetInfoQuery scheduleGetInfo = 53; // Get all information about a scheduled entity
+
+ TokenGetAccountNftInfoQuery tokenGetAccountNftInfo = 54; // Get a list of NFTs associated with the account
+ TokenGetNftInfoQuery tokenGetNftInfo = 55; // Get all information about a NFT
+ TokenGetNftInfosQuery tokenGetNftInfos = 56; // Get a list of NFTs for the token
}
}
diff --git a/services/Response.proto b/services/Response.proto
index afbacc76..8f7c8ef4 100644
--- a/services/Response.proto
+++ b/services/Response.proto
@@ -50,10 +50,14 @@ import "ConsensusGetTopicInfo.proto";
import "NetworkGetVersionInfo.proto";
+import "TokenGetAccountNftInfo.proto";
import "TokenGetInfo.proto";
+import "TokenGetNftInfo.proto";
+import "TokenGetNftInfos.proto";
import "ScheduleGetInfo.proto";
+
/* A single response, which is returned from the node to the client, after the client sent the node a query. This includes all responses. */
message Response {
oneof response {
@@ -85,5 +89,9 @@ message Response {
TokenGetInfoResponse tokenGetInfo = 152; // Get all information about a token
ScheduleGetInfoResponse scheduleGetInfo = 153; // Get all information about a schedule entity
+
+ TokenGetAccountNftInfoResponse tokenGetAccountNftInfo = 154; // A list of the NFTs associated with the account
+ TokenGetNftInfoResponse tokenGetNftInfo = 155; // All information about an NFT
+ TokenGetNftInfosResponse tokenGetNftInfos = 156; // A list of the NFTs for the token
}
}
diff --git a/services/ResponseCode.proto b/services/ResponseCode.proto
index 44e1d82d..5ccf28b8 100644
--- a/services/ResponseCode.proto
+++ b/services/ResponseCode.proto
@@ -230,4 +230,11 @@ enum ResponseCodeEnum {
SUCCESS_BUT_MISSING_EXPECTED_OPERATION = 220; // The throttle definitions file was updated, but some supported operations were not assigned a bucket
UNPARSEABLE_THROTTLE_DEFINITIONS = 221; // The new contents for the throttle definitions system file were not valid protobuf
INVALID_THROTTLE_DEFINITIONS = 222; // The new throttle definitions system file were invalid, and no more specific error could be divined
+ ACCOUNT_EXPIRED_AND_PENDING_REMOVAL = 223; // The transaction references an account which has passed its expiration without renewal funds available, and currently remains in the ledger only because of the grace period given to expired entities
+ INVALID_TOKEN_MAX_SUPPLY = 224; // Invalid token max supply
+ INVALID_TOKEN_NFT_SERIAL_NUMBER = 225; // Invalid token nft serial number
+ INVALID_NFT_ID = 226; // Invalid nft id
+ METADATA_TOO_LONG = 227; // Nft metadata is too long
+ BATCH_SIZE_LIMIT_EXCEEDED = 228; // Repeated operations count exceeds the limit
+ QUERY_RANGE_LIMIT_EXCEEDED = 229; // The range of data to be gathered exceeds the limit
}
diff --git a/services/TokenAssociate.proto b/services/TokenAssociate.proto
index 3fbf5699..51b4ef20 100644
--- a/services/TokenAssociate.proto
+++ b/services/TokenAssociate.proto
@@ -38,5 +38,5 @@ import "BasicTypes.proto";
*/
message TokenAssociateTransactionBody {
AccountID account = 1; // The account to be associated with the provided tokens
- repeated TokenID tokens = 2; // The tokens to be associated with the provided account
+ repeated TokenID tokens = 2; // The tokens to be associated with the provided account. In the case of NON_FUNGIBLE_UNIQUE Type, once an account is associated, it can hold any number of NFTs (serial numbers) of that token type
}
diff --git a/services/TokenBurn.proto b/services/TokenBurn.proto
index 0c723a38..320edc9b 100644
--- a/services/TokenBurn.proto
+++ b/services/TokenBurn.proto
@@ -35,5 +35,6 @@ Token A has 2 decimals. In order to burn 100 tokens, one must provide amount of
*/
message TokenBurnTransactionBody {
TokenID token = 1; // The token for which to burn tokens. If token does not exist, transaction results in INVALID_TOKEN_ID
- uint64 amount = 2; // The amount to burn from the Treasury Account. Amount must be a positive non-zero number, not bigger than the token balance of the treasury account (0; balance], represented in the lowest denomination.
+ uint64 amount = 2; // Applicable to tokens of type FUNGIBLE_COMMON. The amount to burn from the Treasury Account. Amount must be a positive non-zero number, not bigger than the token balance of the treasury account (0; balance], represented in the lowest denomination.
+ repeated int64 serialNumbers = 3; // Applicable to tokens of type NON_FUNGIBLE_UNIQUE. The list of serial numbers to be burned.
}
diff --git a/services/TokenCreate.proto b/services/TokenCreate.proto
index 92b78c21..fa4d4b28 100644
--- a/services/TokenCreate.proto
+++ b/services/TokenCreate.proto
@@ -44,9 +44,9 @@ Note that a created token is immutable if the adminKey is omitte
message TokenCreateTransactionBody {
string name = 1; // The publicly visible name of the token, limited to a UTF-8 encoding of length tokens.maxSymbolUtf8Bytes.
string symbol = 2; // The publicly visible token symbol, limited to a UTF-8 encoding of length tokens.maxTokenNameUtf8Bytes.
- uint32 decimals = 3; // The number of decimal places a token is divisible by. This field can never be changed!
- uint64 initialSupply = 4; // Specifies the initial supply of tokens to be put in circulation. The initial supply is sent to the Treasury Account. The supply is in the lowest denomination possible.
- AccountID treasury = 5; // The account which will act as a treasury for the token. This account will receive the specified initial supply
+ uint32 decimals = 3; // For tokens of type FUNGIBLE_COMMON - the number of decimal places a token is divisible by. For tokens of type NON_FUNGIBLE_UNIQUE - value must be 0
+ uint64 initialSupply = 4; // Specifies the initial supply of tokens to be put in circulation. The initial supply is sent to the Treasury Account. The supply is in the lowest denomination possible. In the case for NON_FUNGIBLE_UNIQUE Type the value must be 0
+ AccountID treasury = 5; // The account which will act as a treasury for the token. This account will receive the specified initial supply or the newly minted NFTs in the case for NON_FUNGIBLE_UNIQUE Type
Key adminKey = 6; // The key which can perform update/delete operations on the token. If empty, the token can be perceived as immutable (not being able to be updated/deleted)
Key kycKey = 7; // The key which can grant or revoke KYC of an account for the token's transactions. If empty, KYC is not required, and KYC grant or revoke operations are not possible.
Key freezeKey = 8; // The key which can sign to freeze or unfreeze an account for token transactions. If empty, freezing is not possible
@@ -57,4 +57,7 @@ message TokenCreateTransactionBody {
AccountID autoRenewAccount = 14; // An account which will be automatically charged to renew the token's expiration, at autoRenewPeriod interval
Duration autoRenewPeriod = 15; // The interval at which the auto-renew account will be charged to extend the token's expiry
string memo = 16; // The memo associated with the token (UTF-8 encoding max 100 bytes)
+ TokenType tokenType = 17; // IWA compatibility. Specifies the token type. Defaults to FUNGIBLE_COMMON
+ TokenSupplyType supplyType = 18; // IWA compatibility. Specified the token supply type. Defaults to INFINITE
+ int64 maxSupply = 19; // IWA Compatibility. Depends on TokenSupplyType. For tokens of type FUNGIBLE_COMMON - the maximum number of tokens that can be in circulation. For tokens of type NON_FUNGIBLE_UNIQUE - the maximum number of NFTs (serial numbers) that can be minted. This field can never be changed!
}
diff --git a/services/TokenGetAccountNftInfo.proto b/services/TokenGetAccountNftInfo.proto
new file mode 100644
index 00000000..9caf68de
--- /dev/null
+++ b/services/TokenGetAccountNftInfo.proto
@@ -0,0 +1,46 @@
+syntax = "proto3";
+
+package proto;
+
+/*-
+ *
+ * Hedera Network Services Protobuf
+ *
+ * Copyright (C) 2018 - 2021 Hedera Hashgraph, LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+option java_package = "com.hederahashgraph.api.proto.java";
+option java_multiple_files = true;
+
+import "BasicTypes.proto";
+import "TokenGetNftInfo.proto";
+import "QueryHeader.proto";
+import "ResponseHeader.proto";
+
+/* Applicable only to tokens of type NON_FUNGIBLE_UNIQUE. Gets info on NFTs N through M owned by the specified accountId.
+ * Example: If Account A owns 5 NFTs (might be of different Token Entity), having start=0 and end=5 will return all of the NFTs
+ */
+message TokenGetAccountNftInfoQuery {
+ QueryHeader header = 1; // Standard info sent from client to node, including the signed payment, and what kind of response is requested (cost, state proof, both, or neither).
+ AccountID accountID = 2; // The Account for which information is requested
+ int64 start = 3; // Specifies the start index (inclusive) of the range of NFTs to query for. Value must be in the range [0; ownedNFTs-1]
+ int64 end = 4; // Specifies the end index (exclusive) of the range of NFTs to query for. Value must be in the range (start; ownedNFTs]
+}
+
+message TokenGetAccountNftInfoResponse {
+ ResponseHeader header = 1; // Standard response from node to client, including the requested fields: cost, or state proof, or both, or neither
+ repeated TokenNftInfo nfts = 2; // List of NFTs associated to the account
+}
diff --git a/services/TokenGetInfo.proto b/services/TokenGetInfo.proto
index 397d172e..9f2e5736 100644
--- a/services/TokenGetInfo.proto
+++ b/services/TokenGetInfo.proto
@@ -42,8 +42,8 @@ message TokenInfo {
TokenID tokenId = 1; // ID of the token instance
string name = 2; // The name of the token. It is a string of ASCII only characters
string symbol = 3; // The symbol of the token. It is a UTF-8 capitalized alphabetical string
- uint32 decimals = 4; // The number of decimal places a token is divisible by
- uint64 totalSupply = 5; // The total supply of tokens that are currently in circulation
+ uint32 decimals = 4; // The number of decimal places a token is divisible by. Always 0 for tokens of type NON_FUNGIBLE_UNIQUE
+ uint64 totalSupply = 5; // For tokens of type FUNGIBLE_COMMON - the total supply of tokens that are currently in circulation. For tokens of type NON_FUNGIBLE_UNIQUE - the number of NFTs created of this token instance
AccountID treasury = 6; // The ID of the account which is set as Treasury
Key adminKey = 7; // The key which can perform update/delete operations on the token. If empty, the token can be perceived as immutable (not being able to be updated/deleted)
Key kycKey = 8; // The key which can grant or revoke KYC of an account for the token's transactions. If empty, KYC is not required, and KYC grant or revoke operations are not possible.
@@ -57,6 +57,9 @@ message TokenInfo {
Duration autoRenewPeriod = 16; // The interval at which the auto-renew account will be charged to extend the token's expiry
Timestamp expiry = 17; // The epoch second at which the token will expire
string memo = 18; // The memo associated with the token
+ TokenType tokenType = 19; // The token type
+ TokenSupplyType supplyType = 20; // The token supply type
+ int64 maxSupply = 21; // For tokens of type FUNGIBLE_COMMON - The Maximum number of fungible tokens that can be in circulation. For tokens of type NON_FUNGIBLE_UNIQUE - the maximum number of NFTs (serial numbers) that can be in circulation
}
/* Response when the client sends the node TokenGetInfoQuery */
diff --git a/services/TokenGetNftInfo.proto b/services/TokenGetNftInfo.proto
new file mode 100644
index 00000000..d7376d7f
--- /dev/null
+++ b/services/TokenGetNftInfo.proto
@@ -0,0 +1,55 @@
+syntax = "proto3";
+
+package proto;
+
+/*-
+ *
+ * Hedera Network Services Protobuf
+ *
+ * Copyright (C) 2018 - 2021 Hedera Hashgraph, LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+option java_package = "com.hederahashgraph.api.proto.java";
+option java_multiple_files = true;
+
+import "BasicTypes.proto";
+import "QueryHeader.proto";
+import "ResponseHeader.proto";
+import "Timestamp.proto";
+
+/* Represents an NFT on the Ledger */
+message NftID {
+ TokenID tokenID = 1; // The (non-fungible) token of which this NFT is an instance
+ int64 serialNumber = 2; // The unique identifier of this instance
+}
+
+/* Applicable only to tokens of type NON_FUNGIBLE_UNIQUE. Gets info on a NFT for a given TokenID (of type NON_FUNGIBLE_UNIQUE) and serial number */
+message TokenGetNftInfoQuery {
+ QueryHeader header = 1; // Standard info sent from client to node, including the signed payment, and what kind of response is requested (cost, state proof, both, or neither).
+ NftID nftID = 2; // The ID of the NFT
+}
+
+message TokenNftInfo {
+ NftID nftID = 1; // The ID of the NFT
+ AccountID accountID = 2; // The current owner of the NFT
+ Timestamp creationTime = 3; // The effective consensus timestamp at which the NFT was minted
+ bytes metadata = 4; // Represents the unique metadata of the NFT
+}
+
+message TokenGetNftInfoResponse {
+ ResponseHeader header = 1; // Standard response from node to client, including the requested fields: cost, or state proof, or both, or neither
+ TokenNftInfo nft = 2; // The information about this NFT
+}
diff --git a/services/TokenGetNftInfos.proto b/services/TokenGetNftInfos.proto
new file mode 100644
index 00000000..8cc438b9
--- /dev/null
+++ b/services/TokenGetNftInfos.proto
@@ -0,0 +1,47 @@
+syntax = "proto3";
+
+package proto;
+
+/*-
+ *
+ * Hedera Network Services Protobuf
+ *
+ * Copyright (C) 2018 - 2021 Hedera Hashgraph, LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+option java_package = "com.hederahashgraph.api.proto.java";
+option java_multiple_files = true;
+
+import "BasicTypes.proto";
+import "TokenGetNftInfo.proto";
+import "QueryHeader.proto";
+import "ResponseHeader.proto";
+
+/* Applicable only to tokens of type NON_FUNGIBLE_UNIQUE. Gets info on NFTs N through M on the list of NFTs associated with a given NON_FUNGIBLE_UNIQUE Token.
+ * Example: If there are 10 NFTs issued, having start=0 and end=5 will query for the first 5 NFTs. Querying +all 10 NFTs will require start=0 and end=10
+ */
+message TokenGetNftInfosQuery {
+ QueryHeader header = 1; // Standard info sent from client to node, including the signed payment, and what kind of response is requested (cost, state proof, both, or neither).
+ TokenID tokenID = 2; // The ID of the token for which information is requested
+ int64 start = 3; // Specifies the start index (inclusive) of the range of NFTs to query for. Value must be in the range [0; ownedNFTs-1]
+ int64 end = 4; // Specifies the end index (exclusive) of the range of NFTs to query for. Value must be in the range (start; ownedNFTs]
+}
+
+message TokenGetNftInfosResponse {
+ ResponseHeader header = 1; // Standard response from node to client, including the requested fields: cost, or state proof, or both, or neither
+ TokenID tokenID = 2; // The Token with type NON_FUNGIBLE that this record is for
+ repeated TokenNftInfo nfts = 3; // List of NFTs associated to the specified token
+}
diff --git a/services/TokenMint.proto b/services/TokenMint.proto
index 0211f664..756b7021 100644
--- a/services/TokenMint.proto
+++ b/services/TokenMint.proto
@@ -35,5 +35,6 @@ Token A has 2 decimals. In order to mint 100 tokens, one must provide amount of
*/
message TokenMintTransactionBody {
TokenID token = 1; // The token for which to mint tokens. If token does not exist, transaction results in INVALID_TOKEN_ID
- uint64 amount = 2; // The amount to mint to the Treasury Account. Amount must be a positive non-zero number represented in the lowest denomination of the token. The new supply must be lower than 2^63.
+ uint64 amount = 2; // Applicable to tokens of type FUNGIBLE_COMMON. The amount to mint to the Treasury Account. Amount must be a positive non-zero number represented in the lowest denomination of the token. The new supply must be lower than 2^63.
+ repeated bytes metadata = 3; // Applicable to tokens of type NON_FUNGIBLE_UNIQUE. A list of metadata that are being created. Maximum allowed size of each metadata is 100 bytes
}
diff --git a/services/TokenService.proto b/services/TokenService.proto
index 3a2f98fa..aa5ef7db 100644
--- a/services/TokenService.proto
+++ b/services/TokenService.proto
@@ -58,4 +58,10 @@ service TokenService {
// Retrieves the metadata of a token
rpc getTokenInfo (Query) returns (Response);
+ // Gets info on NFTs N through M on the list of NFTs associated with a given account
+ rpc getAccountNftInfo (Query) returns (Response);
+ // Retrieves the metadata of an NFT by TokenID and serial number
+ rpc getTokenNftInfo (Query) returns (Response);
+ // Gets info on NFTs N through M on the list of NFTs associated with a given Token of type NON_FUNGIBLE
+ rpc getTokenNftInfos (Query) returns (Response);
}
diff --git a/services/TokenWipeAccount.proto b/services/TokenWipeAccount.proto
index 444c1d14..7d7941f2 100644
--- a/services/TokenWipeAccount.proto
+++ b/services/TokenWipeAccount.proto
@@ -43,5 +43,6 @@ import "BasicTypes.proto";
message TokenWipeAccountTransactionBody {
TokenID token = 1; // The token for which the account will be wiped. If token does not exist, transaction results in INVALID_TOKEN_ID
AccountID account = 2; // The account to be wiped
- uint64 amount = 3; // The amount of tokens to wipe from the specified account. Amount must be a positive non-zero number in the lowest denomination possible, not bigger than the token balance of the account (0; balance]
+ uint64 amount = 3; // Applicable to tokens of type FUNGIBLE_COMMON. The amount of tokens to wipe from the specified account. Amount must be a positive non-zero number in the lowest denomination possible, not bigger than the token balance of the account (0; balance]
+ repeated int64 serialNumbers = 4; // Applicable to tokens of type NON_FUNGIBLE_UNIQUE. The list of serial numbers to be wiped.
}
diff --git a/services/TransactionReceipt.proto b/services/TransactionReceipt.proto
index 38e23c90..ebee2ad3 100644
--- a/services/TransactionReceipt.proto
+++ b/services/TransactionReceipt.proto
@@ -109,4 +109,7 @@ message TransactionReceipt {
// In the receipt of a ScheduleCreate or ScheduleSign that resolves to SUCCESS, the TransactionID that should be used to query for the receipt or record of the relevant scheduled transaction
TransactionID scheduledTransactionID = 13;
+
+ // In the receipt of a TokenMint for tokens of type NON_FUNGIBLE_UNIQUE, the serial numbers of the newly created NFTs
+ repeated int64 serialNumbers = 14;
}
diff --git a/streams/AccountBalanceFile.proto b/streams/AccountBalanceFile.proto
index ca29dee7..bc73f947 100644
--- a/streams/AccountBalanceFile.proto
+++ b/streams/AccountBalanceFile.proto
@@ -30,7 +30,7 @@ import "Timestamp.proto";
message TokenUnitBalance {
TokenID tokenId = 1; // A unique token id
- uint64 balance = 2; // A number of transferable units of the identified token
+ uint64 balance = 2; // Number of transferable units of the identified token. For token of type FUNGIBLE_COMMON - balance in the smallest denomination. For token of type NON_FUNGIBLE_UNIQUE - the number of NFTs held by the account
}
/* Includes all currency balances (both hbar and token) of a single account in the ledger. */