HIP-857: NFT Allowances REST API
Author | Mugdha Goel |
---|---|
Working Group | Steven Sheehy, Ashe Oro |
Requested By | Hashpack and Zuse Marketplace |
Discussions-To | https://github.com/hashgraph/hedera-improvement-proposal/discussions/858 |
Status | Final ⓘ |
Needs Council Approval | Yes ⓘ |
Review period ends ⓘ | Thu, 01 Feb 2024 07:00:00 +0000 |
Type | Standards Track ⓘ |
Category | Mirror ⓘ |
Created | 2023-12-07 |
Updated | 2024-05-14 |
Release | v0.106.0 |
Table of Contents
Abstract
Hedera customers have requested the ability to view their current NFT allowances. Hence, we propose adding a
new mirror node REST API /api/v1/accounts/{id}/allowances/nfts
to return this information.
Motivation
NFT marketplaces have requested the ability to view a NFT allowance’s details via an API.
Rationale
There have been requests to enable querying spending approvals for NFTs based on the owner ID. Additionally, there is a request to be able to query by the spender ID as well. It was also asked for the ability to know whether the approval was given via approveForAll
or not. This information was requested by HashPack and Zuse marketplace.
The API described below has been chosen to make the implementation easier for NFT explorers and marketplaces that wish to search NFT allowances based on the owner and spender. The decision to design one API for both use cases is aimed at reducing the number of APIs that essentially perform similar tasks. This API would also return the approveForAll
information.
User stories
- As a mirror node operator, I want to provide my API clients with the ability to list NFT allowances for an account that has granted allowance for a specific NFT serial number, as well as for those who have used
approveForAll
. - As a mirror node operator, I want to provide my API clients with the ability to list NFT allowances for a spender who has received an allowance for a single NFT serial number, as well as via
approveForAll
.
Specification
This is a HIP for adding the ability to query the allowances on NFTs from the mirror node.
Constraints
When designing the NFT allowances APIs, it is important to consider certain constraints on the number of allowances and tokens. These constraints may limit the ability to query unbounded information.
- An approval transaction can include a maximum of 20 allowance change operations.
- An account can have a maximum of 100 hbar, token, and approved for all NFT allowances.
- An account can have an unbounded number of individual NFT allowances.
- A non-fungible token can have an unbounded number of approved for all NFT allowances.
- A specific NFT can only have one explicit approval. The last one to be approved will take precedence.
- When an NFT is transferred by either the owner or a spender, it results in the individual spender’s allowance being cleared.
- A specific NFT can have an unbounded number of implicit approved for all NFT allowances.
Approved for all NFT Allowances API
This API accepts a path parameter that represents either the owner or spender, depending on a boolean flag provided as a query parameter called owner
. When the owner
value is true or omitted, the accountId
path parameter should specify the ID of the owner, and the API will retrieve the allowances that the owner has granted to different spenders. Conversely, when the owner
value is false, the accountId
path parameter should indicate the ID of the spender who has an allowance, and the API will instead provide the allowances granted to the spender by different owners of those tokens.
Following are example responses of the NFT allowance API:
GET /api/v1/accounts/0.0.1000/allowances/nfts?limit=3&owner=true
{
"allowances": [
{
"approved_for_all": true,
"owner": "0.0.1000",
"spender": "0.0.8488",
"token_id": "0.0.1033",
"timestamp": {
"from": "1633466229.96874612",
"to": null
}
},
{
"approved_for_all": false,
"owner": "0.0.1000",
"spender": "0.0.8489",
"token_id": "0.0.1034",
"timestamp": {
"from": "1633466229.96874618",
"to": null
}
},
{
"approved_for_all": true,
"owner": "0.0.1000",
"spender": "0.0.9857",
"token_id": "0.0.1032",
"timestamp": {
"from": "1633466229.96884615",
"to": null
}
}
],
"links": {
"next": "/api/v1/accounts/0.0.1000/allowances/nfts?limit=3&order=asc&account.id=gte:9857&token.id=gt:0.0.1032"
}
}
GET /api/v1/accounts/0.0.8488/allowances/nfts?limit=3&owner=false
{
"allowances": [
{
"approved_for_all": true,
"owner": "0.0.1000",
"spender": "0.0.8488",
"token_id": "0.0.1033",
"timestamp": {
"from": "1633466229.96874612",
"to": null
}
},
{
"approved_for_all": true,
"owner": "0.0.1000",
"spender": "0.0.8488",
"token_id": "0.0.1034",
"timestamp": {
"from": "1633466229.96874618",
"to": null
}
},
{
"approved_for_all": false,
"owner": "0.0.1001",
"spender": "0.0.8488",
"token_id": "0.0.1099",
"timestamp": {
"from": "1633466229.96875612",
"to": null
}
}
],
"links": {
"next": "/api/v1/accounts/0.0.8488/allowances/nfts?limit=3&order=asc&account.id=gte:1001&token.id=gt:0.0.1099"
}
}
Query Parameters:
account.id
: Filter by the spender account ID or owner account ID, depending on the owner flag.ne
operator is not supported. Only one occurrence is allowed.limit
: The maximum number of items to return. Defaults to 25 with a maximum of 100 allowed.order
: Order byaccount.id
thentoken.id
. Acceptsasc
ordesc
with a default ofasc
.owner
: Indicates whether the path parameteraccountId
is the owner or the spender ID. Accepts a boolean value oftrue
orfalse
with a default value set totrue
.token.id
: Filter by the token ID.ne
operator is not supported. Only one occurrence is allowed.
Pagination is important to implement because there are accounts that could have a large number of NFT allowances, making a non-paginated response impractical. This requires multi-column pagination, including owner, spender, and token IDs.
Ordering
The order is governed by a combination of the account ID and the token ID values, with the account ID being the parent column. The token ID value governs its order within the given account ID. The default order for this API is ascending.
Filtering
When filtering there are some restrictions enforced to ensure correctness and scalability.
The table below defines the restrictions and support for the endpoint.
Query Param | Comparison Operator | Support | Description | Example |
---|---|---|---|---|
account.id | eq | Y | Single occurrence only. | ?account.id=X |
ne | N | |||
lt(e) | Y | Single occurrence only. | ?account.id=lte:X | |
gt(e) | Y | Single occurrence only. | ?account.id=gte:X | |
token.id | eq | Y | Single occurrence only. Requires the presence of an account.id query parameter |
?account.id=X&token.id=eq:Y |
ne | N | |||
lt(e) | Y | Single occurrence only. Requires the presence of a lte or eq account.id query parameter |
?account.id=lte:X&token.id=lt:Y | |
gt(e) | Y | Single occurrence only. Requires the presence of a gte or eq account.id query parameter |
?account.id=gte:X&token.id=gt:Y |
Both filters must be a single occurrence of gt(e) or lt(e) which provide a lower and or upper boundary for search.
Serial level allowance information
To retrieve NFT serial number level allowance information for a specific token ID you can use the existing API:
GET /api/v1/tokens/{tokenId}/nfts
{
"nfts": [
{
"account_id": "0.0.123",
"created_timestamp": "1704827664.003435784",
"delegating_spender": null,
"deleted": false,
"metadata": "AA==",
"modified_timestamp": "1704827664.003435784",
"serial_number": 1,
"spender": null,
"token_id": "0.0.1000"
}
],
"links": {
"next": null
}
}
Backwards Compatibility
This HIP primarily adds new information that mirror node operators and other record stream consumers can simply ignore if they do not need it. However, NFT marketplaces using the Hedera mirror node could start using the new API.
Security Implications
There are no security implications for this HIP.
How to Teach This
The Hedera documentation and the OpenAPI specification will be updated to add this new API.
Reference Implementation
Please follow this issue for progress on the reference implementation.
Rejected Ideas
- We briefly considered adding serial number level information to
/api/v1/accounts/{id}/allowances/nft
in order for an NFT marketplace to view which spender hasapprovedForAll
for particular serial numbers. However, this idea was rejected due to the unbounded nature of the data. When a token has a very high number of serials and allowances, implementing this feature could become a performance concern. - There was a consideration to add
approve_for_all
to/api/v1/tokens/{id}/nfts/{id}
. This idea was rejected because it is possible to have an unbounded number ofapprove_for_all
allowances and it is not feasible to return this data in a single response payload. - There was a consideration to add
approve_for_all
to/api/v1/accounts/{id}/tokens
. This idea was rejected because it is possible to have an unbounded number ofapprove_for_all
allowances and it is not feasible to return this data in a single response payload.
Open Issues
No known open issues exist.
References
Copyright/license
This document is licensed under the Apache License, Version 2.0 – see LICENSE or (https://www.apache.org/licenses/LICENSE-2.0)
Citation
Please cite this document as: