fix: remove deprecated token endpoints (#1775)

* fix: remove deprecated token endpoints

* fix: broken import

* chore: remove FT tag from openapi [skip ci]
This commit is contained in:
Rafael Cárdenas
2023-12-15 11:48:19 -06:00
committed by GitHub
parent c2f95d33c1
commit 18f74b7b77
17 changed files with 23 additions and 943 deletions

View File

@@ -1,13 +0,0 @@
{
"limit": 20,
"offset": 0,
"total": 1,
"nft_events": [
{
"sender": "none",
"recipient": "ST1HB64MAJ1MBV4CQ80GF01DZS4T1DSMX20ADCRA4",
"asset_identifier": "some-asset",
"value": { "hex": "0x00", "repr": "0" }
}
]
}

View File

@@ -1,28 +0,0 @@
{
"type": "object",
"title": "AddressNftListResponse",
"additionalProperties": false,
"required": [
"limit",
"offset",
"total",
"nft_events"
],
"properties": {
"limit": {
"type": "integer"
},
"offset": {
"type": "integer"
},
"total": {
"type": "integer"
},
"nft_events": {
"type": "array",
"items": {
"$ref": "../../entities/nft-events/nft-event.schema.json"
}
}
}
}

View File

@@ -1,18 +0,0 @@
{
"limit": 1,
"offset": 0,
"total": 500,
"results": [
{
"token_uri": "https://heystack.xyz/token-metadata.json",
"name": "Heystack",
"description": "Heystack is a SIP-010-compliant fungible token on the Stacks Blockchain, used on the Heystack app",
"image_uri": "https://heystack.xyz/assets/Stacks128w.png",
"image_canonical_uri": "https://heystack.xyz/assets/Stacks128w.png",
"tx_id": "0xef2ac1126e16f46843228b1dk4830e19eb7599129e4jf392cab9e65ae83a45c0",
"sender_address": "ST399W7Z9WS0GMSNQGJGME5JAENKN56D65VGMGKGA",
"symbol": "HEY",
"decimals": 5
}
]
}

View File

@@ -1,33 +0,0 @@
{
"description": "List of fungible tokens metadata",
"title": "FungibleTokensMetadataList",
"type": "object",
"additionalProperties": false,
"required": [
"results",
"limit",
"offset",
"total"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 200,
"description": "The number of tokens metadata to return"
},
"offset": {
"type": "integer",
"description": "The number to tokens metadata to skip (starting at `0`)"
},
"total": {
"type": "integer",
"description": "The number of tokens metadata available"
},
"results": {
"type": "array",
"items": {
"$ref": "../../entities/tokens/fungible-token.schema.json"
}
}
}
}

View File

@@ -1,16 +0,0 @@
{
"limit": 1,
"offset": 0,
"total": 500,
"results": [
{
"token_uri": "https://pool.friedger.de/nft.json",
"name": "Friedger Pool",
"description": "Enjoying the stacking pool.",
"image_uri": "https://pool.friedger.de/nft.webp",
"image_canonical_uri": "https://pool.friedger.de/nft.webp",
"tx_id": "0xef2ac1126e16f46843228b1dk4830e19eb7599129e4jf392cab9e65ae83a45c0",
"sender_address": "ST399W7Z9WS0GMSNQGJGME5JAENKN56D65VGMGKGA"
}
]
}

View File

@@ -1,33 +0,0 @@
{
"description": "List of non fungible tokens metadata",
"title": "NonFungibleTokensMetadataList",
"additionalProperties": false,
"type": "object",
"required": [
"results",
"limit",
"offset",
"total"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 200,
"description": "The number of tokens metadata to return"
},
"offset": {
"type": "integer",
"description": "The number to tokens metadata to skip (starting at `0`)"
},
"total": {
"type": "integer",
"description": "The number of tokens metadata available"
},
"results": {
"type": "array",
"items": {
"$ref": "../../entities/tokens/non-fungible-token.schema.json"
}
}
}
}

View File

@@ -1,11 +0,0 @@
{
"token_uri": "https://heystack.xyz/token-metadata.json",
"name": "Heystack",
"description": "Heystack is a SIP-010-compliant fungible token on the Stacks Blockchain, used on the Heystack app",
"image_uri": "https://heystack.xyz/assets/Stacks128w.png",
"image_canonical_uri": "https://heystack.xyz/assets/Stacks128w.png",
"tx_id": "0xef2ac1126e16f46843228b1dk4830e19eb7599129e4jf392cab9e65ae83a45c0",
"sender_address": "ST399W7Z9WS0GMSNQGJGME5JAENKN56D65VGMGKGA",
"symbol": "HEY",
"decimals": 5
}

View File

@@ -1,54 +0,0 @@
{
"title": "FungibleTokenMetadata",
"type": "object",
"additionalProperties": false,
"required": [
"token_uri",
"name",
"description",
"image_uri",
"image_canonical_uri",
"symbol",
"decimals",
"tx_id",
"sender_address"
],
"properties": {
"token_uri": {
"type": "string",
"description": "An optional string that is a valid URI which resolves to this token's metadata. Can be empty."
},
"name": {
"type": "string",
"description": "Identifies the asset to which this token represents"
},
"description": {
"type": "string",
"description": "Describes the asset to which this token represents"
},
"image_uri": {
"type": "string",
"description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. The API may provide a URI to a cached resource, dependending on configuration. Otherwise, this can be the same value as the canonical image URI."
},
"image_canonical_uri": {
"type": "string",
"description": "The original image URI specified by the contract. A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."
},
"symbol": {
"type": "string",
"description": "A shorter representation of a token. This is sometimes referred to as a \"ticker\". Examples: \"STX\", \"COOL\", etc. Typically, a token could be referred to as $SYMBOL when referencing it in writing."
},
"decimals": {
"type": "number",
"description": "The number of decimal places in a token."
},
"tx_id": {
"type": "string",
"description": "Tx id that deployed the contract"
},
"sender_address": {
"type": "string",
"description": "principle that deployed the contract"
}
}
}

View File

@@ -1,9 +0,0 @@
{
"token_uri": "https://pool.friedger.de/nft.json",
"name": "Friedger Pool",
"description": "Enjoying the stacking pool.",
"image_uri": "https://pool.friedger.de/nft.webp",
"image_canonical_uri": "https://pool.friedger.de/nft.webp",
"tx_id": "0xef2ac1126e16f46843228b1dk4830e19eb7599129e4jf392cab9e65ae83a45c0",
"sender_address": "ST399W7Z9WS0GMSNQGJGME5JAENKN56D65VGMGKGA"
}

View File

@@ -1,44 +0,0 @@
{
"title": "NonFungibleTokenMetadata",
"type": "object",
"additionalProperties": false,
"required": [
"token_uri",
"name",
"description",
"image_uri",
"image_canonical_uri",
"tx_id",
"sender_address"
],
"properties": {
"token_uri": {
"type": "string",
"description": "An optional string that is a valid URI which resolves to this token's metadata. Can be empty."
},
"name": {
"type": "string",
"description": "Identifies the asset to which this token represents"
},
"description": {
"type": "string",
"description": "Describes the asset to which this token represents"
},
"image_uri": {
"type": "string",
"description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. The API may provide a URI to a cached resource, dependending on configuration. Otherwise, this can be the same value as the canonical image URI."
},
"image_canonical_uri": {
"type": "string",
"description": "The original image URI specified by the contract. A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."
},
"tx_id": {
"type": "string",
"description": "Tx id that deployed the contract"
},
"sender_address": {
"type": "string",
"description": "principle that deployed the contract"
}
}
}

161
docs/generated.d.ts vendored
View File

@@ -7,7 +7,6 @@
export type SchemaMergeRootStub = export type SchemaMergeRootStub =
| AddressAssetsListResponse | AddressAssetsListResponse
| AddressBalanceResponse | AddressBalanceResponse
| AddressNftListResponse
| AddressStxBalanceResponse | AddressStxBalanceResponse
| AddressStxInboundListResponse | AddressStxInboundListResponse
| AddressTransactionsWithTransfersListResponse | AddressTransactionsWithTransfersListResponse
@@ -97,11 +96,9 @@ export type SchemaMergeRootStub =
| { | {
[k: string]: unknown | undefined; [k: string]: unknown | undefined;
} }
| FungibleTokensMetadataList
| NonFungibleTokenHistoryEventList | NonFungibleTokenHistoryEventList
| NonFungibleTokenHoldingsList | NonFungibleTokenHoldingsList
| NonFungibleTokenMintList | NonFungibleTokenMintList
| NonFungibleTokensMetadataList
| MempoolTransactionStatsResponse | MempoolTransactionStatsResponse
| MempoolTransactionListResponse | MempoolTransactionListResponse
| GetRawTransactionResult | GetRawTransactionResult
@@ -180,7 +177,6 @@ export type SchemaMergeRootStub =
| TransactionIdentifier | TransactionIdentifier
| RosettaTransaction | RosettaTransaction
| PoolDelegation | PoolDelegation
| FungibleTokenMetadata
| NonFungibleTokenHistoryEventWithTxId | NonFungibleTokenHistoryEventWithTxId
| NonFungibleTokenHistoryEventWithTxMetadata | NonFungibleTokenHistoryEventWithTxMetadata
| NonFungibleTokenHistoryEvent | NonFungibleTokenHistoryEvent
@@ -190,7 +186,6 @@ export type SchemaMergeRootStub =
| NonFungibleTokenMintWithTxId | NonFungibleTokenMintWithTxId
| NonFungibleTokenMintWithTxMetadata | NonFungibleTokenMintWithTxMetadata
| NonFungibleTokenMint | NonFungibleTokenMint
| NonFungibleTokenMetadata
| AbstractTransactionEvent | AbstractTransactionEvent
| TransactionEventAssetType | TransactionEventAssetType
| TransactionEventAsset | TransactionEventAsset
@@ -849,35 +844,6 @@ export interface AddressUnlockSchedule {
amount: string; amount: string;
block_height: number; block_height: number;
} }
export interface AddressNftListResponse {
limit: number;
offset: number;
total: number;
nft_events: NftEvent[];
}
export interface NftEvent {
sender?: string;
recipient?: string;
asset_identifier: string;
asset_event_type: string;
/**
* Identifier of the NFT
*/
value: {
/**
* Hex string representing the identifier of the NFT
*/
hex: string;
/**
* Readable string of the NFT identifier
*/
repr: string;
};
tx_id: string;
tx_index: number;
block_height: number;
event_index: number;
}
/** /**
* GET request that returns a list of inbound STX transfers with a memo * GET request that returns a list of inbound STX transfers with a memo
*/ */
@@ -3106,62 +3072,6 @@ export interface PoolDelegation {
*/ */
tx_id: string; tx_id: string;
} }
/**
* List of fungible tokens metadata
*/
export interface FungibleTokensMetadataList {
/**
* The number of tokens metadata to return
*/
limit: number;
/**
* The number to tokens metadata to skip (starting at `0`)
*/
offset: number;
/**
* The number of tokens metadata available
*/
total: number;
results: FungibleTokenMetadata[];
}
export interface FungibleTokenMetadata {
/**
* An optional string that is a valid URI which resolves to this token's metadata. Can be empty.
*/
token_uri: string;
/**
* Identifies the asset to which this token represents
*/
name: string;
/**
* Describes the asset to which this token represents
*/
description: string;
/**
* A URI pointing to a resource with mime type image/* representing the asset to which this token represents. The API may provide a URI to a cached resource, dependending on configuration. Otherwise, this can be the same value as the canonical image URI.
*/
image_uri: string;
/**
* The original image URI specified by the contract. A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.
*/
image_canonical_uri: string;
/**
* A shorter representation of a token. This is sometimes referred to as a "ticker". Examples: "STX", "COOL", etc. Typically, a token could be referred to as $SYMBOL when referencing it in writing.
*/
symbol: string;
/**
* The number of decimal places in a token.
*/
decimals: number;
/**
* Tx id that deployed the contract
*/
tx_id: string;
/**
* principle that deployed the contract
*/
sender_address: string;
}
/** /**
* List of Non-Fungible Token history events * List of Non-Fungible Token history events
*/ */
@@ -3320,54 +3230,6 @@ export interface NonFungibleTokenMintWithTxMetadata {
}; };
tx: Transaction; tx: Transaction;
} }
/**
* List of non fungible tokens metadata
*/
export interface NonFungibleTokensMetadataList {
/**
* The number of tokens metadata to return
*/
limit: number;
/**
* The number to tokens metadata to skip (starting at `0`)
*/
offset: number;
/**
* The number of tokens metadata available
*/
total: number;
results: NonFungibleTokenMetadata[];
}
export interface NonFungibleTokenMetadata {
/**
* An optional string that is a valid URI which resolves to this token's metadata. Can be empty.
*/
token_uri: string;
/**
* Identifies the asset to which this token represents
*/
name: string;
/**
* Describes the asset to which this token represents
*/
description: string;
/**
* A URI pointing to a resource with mime type image/* representing the asset to which this token represents. The API may provide a URI to a cached resource, dependending on configuration. Otherwise, this can be the same value as the canonical image URI.
*/
image_uri: string;
/**
* The original image URI specified by the contract. A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.
*/
image_canonical_uri: string;
/**
* Tx id that deployed the contract
*/
tx_id: string;
/**
* principle that deployed the contract
*/
sender_address: string;
}
/** /**
* GET request that returns stats on mempool transactions * GET request that returns stats on mempool transactions
*/ */
@@ -3587,6 +3449,29 @@ export interface ReadOnlyFunctionArgs {
*/ */
arguments: string[]; arguments: string[];
} }
export interface NftEvent {
sender?: string;
recipient?: string;
asset_identifier: string;
asset_event_type: string;
/**
* Identifier of the NFT
*/
value: {
/**
* Hex string representing the identifier of the NFT
*/
hex: string;
/**
* Readable string of the NFT identifier
*/
repr: string;
};
tx_id: string;
tx_index: number;
block_height: number;
event_index: number;
}
/** /**
* Instead of utilizing HTTP status codes to describe node errors (which often do not have a good analog), rich errors are returned using this object. Both the code and message fields can be individually used to correctly identify an error. Implementations MUST use unique values for both fields. * Instead of utilizing HTTP status codes to describe node errors (which often do not have a good analog), rich errors are returned using this object. Both the code and message fields can be individually used to correctly identify an error. Implementations MUST use unique values for both fields.
*/ */

View File

@@ -25,11 +25,6 @@ tags:
description: Endpoints to request STX or BTC tokens (not possible on Mainnet) description: Endpoints to request STX or BTC tokens (not possible on Mainnet)
- name: Fees - name: Fees
description: Read-only endpoints to obtain fee details description: Read-only endpoints to obtain fee details
- name: Fungible Tokens
description: Read-only endpoints to obtain fungible token details
externalDocs:
description: Stacks Documentation - Tokens
url: https://docs.stacks.co/write-smart-contracts/tokens
- name: Info - name: Info
description: Read-only endpoints to obtain network, Proof-of-Transfer, Stacking, STX token, and node information description: Read-only endpoints to obtain network, Proof-of-Transfer, Stacking, STX token, and node information
- name: Microblocks - name: Microblocks
@@ -1815,63 +1810,6 @@ paths:
example: example:
$ref: ./api/address/get-address-stx-inbound.example.json $ref: ./api/address/get-address-stx-inbound.example.json
/extended/v1/address/{principal}/nft_events:
get:
summary: Get nft events
deprecated: true
description: |
**NOTE:** This endpoint is deprecated in favor of [Non-Fungible Token holdings](#operation/get_nft_holdings).
Retrieves a list of all nfts owned by an address, contains the clarity value of the identifier of the nft.
tags:
- Accounts
operationId: get_account_nft
parameters:
- name: principal
in: path
description: Stacks address or a Contract identifier
required: true
schema:
type: string
example: "SP31DA6FTSJX2WGTZ69SFY11BH51NZMB0ZW97B5P0"
- name: limit
in: query
description: number of items to return
required: false
schema:
type: integer
- name: offset
in: query
description: number of items to skip
required: false
schema:
type: integer
example: 42000
- name: unanchored
in: query
description: Include transaction data from unanchored (i.e. unconfirmed) microblocks
required: false
schema:
type: boolean
example: true
default: false
- name: until_block
in: query
description: returned data representing the state up until that point in time, rather than the current block. Note - Use either of the query parameters but not both at a time.
required: false
schema:
type: string
example: 60000
responses:
200:
description: Success
content:
application/json:
schema:
$ref: ./api/address/get-address-nft-events.schema.json
example:
$ref: ./api/address/get-address-nft-events.example.json
/v2/accounts/{principal}: /v2/accounts/{principal}:
get: get:
summary: Get account info summary: Get account info
@@ -3145,43 +3083,6 @@ paths:
example: example:
$ref: ./api/transaction/get-mempool-transactions.example.json $ref: ./api/transaction/get-mempool-transactions.example.json
/extended/v1/tokens/ft/metadata:
get:
operationId: get_ft_metadata_list
summary: Fungible tokens metadata list
deprecated: true
description: |
**NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service).
Retrieves list of fungible tokens with their metadata. More information on Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#fungible-tokens).
tags:
- Fungible Tokens
parameters:
- name: limit
in: query
description: max number of tokens to fetch.
required: false
schema:
type: integer
example: 100
maximum: 200
- name: offset
in: query
description: index of first tokens to fetch
required: false
schema:
type: integer
example: 42000
responses:
200:
description: List of fungible tokens metadata
content:
application/json:
schema:
$ref: ./api/tokens/get-fungible-tokens-metadata-list.schema.json
example:
$ref: ./api/tokens/get-fungible-tokens-metadata-list.example.schema.json
/extended/v1/tokens/nft/holdings: /extended/v1/tokens/nft/holdings:
get: get:
operationId: get_nft_holdings operationId: get_nft_holdings
@@ -3388,99 +3289,6 @@ paths:
value: value:
$ref: ./api/tokens/get-non-fungible-token-mints-tx-metadata.example.schema.json $ref: ./api/tokens/get-non-fungible-token-mints-tx-metadata.example.schema.json
/extended/v1/tokens/nft/metadata:
get:
operationId: get_nft_metadata_list
summary: Non fungible tokens metadata list
deprecated: true
description: |
**NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service).
Retrieves a list of non fungible tokens with their metadata. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts).
tags:
- Non-Fungible Tokens
parameters:
- name: limit
in: query
description: max number of tokens to fetch
required: false
schema:
type: integer
example: 1
- name: offset
in: query
description: index of first tokens to fetch
required: false
schema:
type: integer
example: 42000
responses:
200:
description: List of non fungible tokens metadata
content:
application/json:
schema:
$ref: ./api/tokens/get-non-fungible-tokens-metadata-list.schema.json
example:
$ref: ./api/tokens/get-non-fungible-tokens-metadata-list.example.schema.json
/extended/v1/tokens/{contractId}/nft/metadata:
get:
operationId: get_contract_nft_metadata
summary: Non fungible tokens metadata for contract ID
deprecated: true
description: |
**NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service).
Retrieves metadata for non fungible tokens for a given contract id. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts).
tags:
- Non-Fungible Tokens
parameters:
- name: contractId
in: path
description: token's contract id
required: true
schema:
type: string
responses:
200:
description: Non fungible tokens metadata for contract id
content:
application/json:
schema:
$ref: ./entities/tokens/non-fungible-token.schema.json
example:
$ref: ./entities/tokens/non-fungible-token.schema.example.json
/extended/v1/tokens/{contractId}/ft/metadata:
get:
operationId: get_contract_ft_metadata
summary: Fungible tokens metadata for contract id
deprecated: true
description: |
**NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service).
Retrieves the metadata for fungible tokens for a given contract id
tags:
- Fungible Tokens
parameters:
- name: contractId
in: path
description: token's contract id
required: true
schema:
type: string
example: "SPSCWDV3RKV5ZRN1FQD84YE1NQFEDJ9R1F4DYQ11.newyorkcitycoin-token-v2"
responses:
200:
description: Fungible tokens metadata for contract id
content:
application/json:
schema:
$ref: ./entities/tokens/fungible-token.schema.json
example:
$ref: ./entities/tokens/fungible-token.schema.example.json
/extended/v1/fee_rate: /extended/v1/fee_rate:
post: post:
operationId: fetch_fee_rate operationId: fetch_fee_rate

View File

@@ -11,7 +11,6 @@ import {
} from '../query-helpers'; } from '../query-helpers';
import { ChainID, formatMapToObject, getSendManyContract, isValidPrincipal } from '../../helpers'; import { ChainID, formatMapToObject, getSendManyContract, isValidPrincipal } from '../../helpers';
import { import {
getAssetEventTypeString,
getTxFromDataStore, getTxFromDataStore,
parseDbEvent, parseDbEvent,
parseDbMempoolTx, parseDbMempoolTx,
@@ -25,12 +24,10 @@ import {
AddressStxBalanceResponse, AddressStxBalanceResponse,
AddressStxInboundListResponse, AddressStxInboundListResponse,
InboundStxTransfer, InboundStxTransfer,
AddressNftListResponse,
MempoolTransactionListResponse, MempoolTransactionListResponse,
AddressTransactionWithTransfers, AddressTransactionWithTransfers,
AddressTransactionsWithTransfersListResponse, AddressTransactionsWithTransfersListResponse,
AddressNonces, AddressNonces,
NftEvent,
} from '@stacks/stacks-blockchain-api-types'; } from '@stacks/stacks-blockchain-api-types';
import { decodeClarityValueToRepr } from 'stacks-encoding-native-js'; import { decodeClarityValueToRepr } from 'stacks-encoding-native-js';
import { validate } from '../validate'; import { validate } from '../validate';
@@ -472,63 +469,6 @@ export function createAddressRouter(db: PgStore, chainId: ChainID): express.Rout
}) })
); );
/**
* @deprecated Use `/extended/v1/tokens/nft/holdings` instead.
*/
router.get(
'/:stx_address/nft_events',
cacheHandler,
asyncHandler(async (req, res, next) => {
// get recent asset event associated with address
const stxAddress = req.params['stx_address'];
validatePrincipal(stxAddress);
const limit = getPagingQueryLimit(ResourceType.Event, req.query.limit);
const offset = parsePagingQueryInput(req.query.offset ?? 0);
const includeUnanchored = isUnanchoredRequest(req, res, next);
const untilBlock = parseUntilBlockQuery(req, res, next);
const nftListResponse = await db.sqlTransaction(async sql => {
const blockHeight = await getBlockHeight(untilBlock, req, res, next, db);
const response = await db.getAddressNFTEvent({
stxAddress,
limit,
offset,
blockHeight,
includeUnanchored,
});
const nft_events = response.results.map(row => {
const parsedClarityValue = decodeClarityValueToRepr(row.value);
const r: NftEvent = {
sender: row.sender,
recipient: row.recipient,
asset_identifier: row.asset_identifier,
value: {
hex: row.value,
repr: parsedClarityValue,
},
tx_id: row.tx_id,
block_height: row.block_height,
event_index: row.event_index,
asset_event_type: getAssetEventTypeString(row.asset_event_type_id),
tx_index: row.tx_index,
};
return r;
});
const nftListResponse: AddressNftListResponse = {
nft_events: nft_events,
total: response.total,
limit: limit,
offset: offset,
};
return nftListResponse;
});
setETagCacheHeaders(res);
res.json(nftListResponse);
})
);
router.get( router.get(
'/:address/mempool', '/:address/mempool',
mempoolCacheHandler, mempoolCacheHandler,

View File

@@ -3540,56 +3540,6 @@ export class PgStore extends BasePgStore {
return { found: true, result: result[0] } as const; return { found: true, result: result[0] } as const;
} }
/**
* @deprecated Use `getNftHoldings` instead.
*/
async getAddressNFTEvent(args: {
stxAddress: string;
limit: number;
offset: number;
blockHeight: number;
includeUnanchored: boolean;
}): Promise<{ results: AddressNftEventIdentifier[]; total: number }> {
// Join against `nft_custody` materialized view only if we're looking for canonical results.
const result = await this.sql<(AddressNftEventIdentifier & { count: number })[]>`
WITH address_transfers AS (
SELECT asset_identifier, value, sender, recipient, block_height, microblock_sequence, tx_index, event_index, tx_id, asset_event_type_id
FROM nft_events
WHERE canonical = true AND microblock_canonical = true
AND recipient = ${args.stxAddress} AND block_height <= ${args.blockHeight}
),
last_nft_transfers AS (
SELECT DISTINCT ON(asset_identifier, value) asset_identifier, value, recipient
FROM nft_events
WHERE canonical = true AND microblock_canonical = true
AND block_height <= ${args.blockHeight}
ORDER BY asset_identifier, value, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC
)
SELECT sender, recipient, asset_identifier, value, at.event_index, asset_event_type_id, at.block_height, at.tx_id, (COUNT(*) OVER())::INTEGER AS count
FROM address_transfers AS at
INNER JOIN ${args.includeUnanchored ? this.sql`last_nft_transfers` : this.sql`nft_custody`}
USING (asset_identifier, value, recipient)
ORDER BY at.block_height DESC, at.microblock_sequence DESC, at.tx_index DESC, event_index DESC
LIMIT ${args.limit} OFFSET ${args.offset}
`;
const count = result.length > 0 ? result[0].count : 0;
const nftEvents = result.map(row => ({
sender: row.sender,
recipient: row.recipient,
asset_identifier: row.asset_identifier,
value: row.value,
block_height: row.block_height,
tx_id: row.tx_id,
event_index: row.event_index,
asset_event_type_id: row.asset_event_type_id,
tx_index: row.tx_index,
}));
return { results: nftEvents, total: count };
}
async getTxListDetails({ async getTxListDetails({
txIds, txIds,
includeUnanchored, includeUnanchored,

View File

@@ -1,6 +1,5 @@
import { import {
ContractCallTransaction, ContractCallTransaction,
FungibleTokenMetadata,
RosettaAccountIdentifier, RosettaAccountIdentifier,
RosettaCurrency, RosettaCurrency,
RosettaOperation, RosettaOperation,

View File

@@ -2268,7 +2268,6 @@ describe('address tests', () => {
'/transactions_with_transfers', '/transactions_with_transfers',
'/assets', '/assets',
'/stx_inbound', '/stx_inbound',
'/nft_events',
]; ];
//check for mutually exclusive unachored and and until_block //check for mutually exclusive unachored and and until_block
@@ -2290,239 +2289,6 @@ describe('address tests', () => {
} }
}); });
test('Success: nft events for address', async () => {
const addr1 = 'ST3J8EVYHVKH6XXPD61EE8XEHW4Y2K83861225AB1';
const addr2 = 'ST1HB64MAJ1MBV4CQ80GF01DZS4T1DSMX20ADCRA4';
const dbBlock: DbBlock = {
block_hash: '0xff',
index_block_hash: '0x1234',
parent_index_block_hash: '0x5678',
parent_block_hash: '0x5678',
parent_microblock_hash: '',
parent_microblock_sequence: 0,
block_height: 1,
burn_block_time: 1594647995,
burn_block_hash: '0x1234',
burn_block_height: 123,
miner_txid: '0x4321',
canonical: true,
execution_cost_read_count: 0,
execution_cost_read_length: 0,
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
};
const stxTx: DbTxRaw = {
tx_id: '0x1111000000000000000000000000000000000000000000000000000000000000',
tx_index: 0,
anchor_mode: 3,
nonce: 0,
raw_tx: '0x',
index_block_hash: dbBlock.index_block_hash,
block_hash: dbBlock.block_hash,
block_height: dbBlock.block_height,
burn_block_time: dbBlock.burn_block_time,
parent_burn_block_time: 1626122935,
type_id: DbTxTypeId.TokenTransfer,
token_transfer_amount: 1n,
token_transfer_memo: bufferToHex(Buffer.from('hi')),
token_transfer_recipient_address: 'none',
status: 1,
raw_result: '0x0100000000000000000000000000000001', // u1
canonical: true,
microblock_canonical: true,
microblock_sequence: I32_MAX,
microblock_hash: '',
parent_index_block_hash: dbBlock.parent_index_block_hash,
parent_block_hash: dbBlock.parent_block_hash,
post_conditions: '0x01f5',
fee_rate: 1234n,
sponsored: false,
sponsor_address: undefined,
sender_address: addr1,
origin_hash_mode: 1,
event_count: 10,
execution_cost_read_count: 0,
execution_cost_read_length: 0,
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
};
const nftEvents: DbNftEvent[] = [];
for (let i = 0; i < 10; i++) {
nftEvents.push({
canonical: true,
event_type: DbEventTypeId.NonFungibleTokenAsset,
asset_event_type_id: DbAssetEventTypeId.Transfer,
event_index: 0,
tx_id: stxTx.tx_id,
tx_index: 1,
block_height: dbBlock.block_height,
asset_identifier: 'some-asset',
value: '0x0000000000000000000000000000000000',
recipient: addr1,
sender: 'none',
});
}
await db.update({
block: dbBlock,
microblocks: [],
minerRewards: [],
txs: [
{
tx: stxTx,
stxLockEvents: [],
stxEvents: [],
ftEvents: [],
nftEvents: nftEvents,
contractLogEvents: [],
smartContracts: [],
names: [],
namespaces: [],
pox2Events: [],
pox3Events: [],
pox4Events: [],
},
],
});
const limit = 2;
const offset = 0;
// test nft for given addresses
const result = await supertest(api.server).get(
`/extended/v1/address/${addr1}/nft_events?limit=${limit}&offset=${offset}`
);
expect(result.status).toBe(200);
expect(result.type).toBe('application/json');
expect(result.body.total).toEqual(10);
expect(result.body.nft_events.length).toEqual(2);
expect(result.body.nft_events[0].recipient).toBe(addr1);
expect(result.body.nft_events[0].tx_id).toBe(
'0x1111000000000000000000000000000000000000000000000000000000000000'
);
expect(result.body.nft_events[0].block_height).toBe(1);
expect(result.body.nft_events[0].value.repr).toBe('0');
const dbBlock2: DbBlock = {
block_hash: '0xffff',
index_block_hash: '0x123466',
parent_index_block_hash: '0x1234',
parent_block_hash: '0xff',
parent_microblock_hash: '',
parent_microblock_sequence: 0,
block_height: 2,
burn_block_time: 1594649995,
burn_block_hash: '0x123456',
burn_block_height: 124,
miner_txid: '0x4321',
canonical: true,
execution_cost_read_count: 0,
execution_cost_read_length: 0,
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
};
const stxTx1: DbTxRaw = {
tx_id: '0x1111100000000000000000000000000000000000000000000000000000000001',
tx_index: 0,
anchor_mode: 3,
nonce: 0,
raw_tx: '0x',
index_block_hash: dbBlock2.index_block_hash,
block_hash: dbBlock2.block_hash,
block_height: dbBlock2.block_height,
burn_block_time: dbBlock2.burn_block_time,
parent_burn_block_time: 1626124935,
type_id: DbTxTypeId.TokenTransfer,
token_transfer_amount: 1n,
token_transfer_memo: bufferToHex(Buffer.from('hi')),
token_transfer_recipient_address: 'none',
status: 1,
raw_result: '0x0100000000000000000000000000000001', // u1
canonical: true,
microblock_canonical: true,
microblock_sequence: I32_MAX,
microblock_hash: '',
parent_index_block_hash: dbBlock2.parent_index_block_hash,
parent_block_hash: dbBlock2.parent_block_hash,
post_conditions: '0x01f5',
fee_rate: 1234n,
sponsored: false,
sponsor_address: undefined,
sender_address: addr2,
origin_hash_mode: 1,
event_count: 1,
execution_cost_read_count: 0,
execution_cost_read_length: 0,
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
};
const nftEvent2: DbNftEvent = {
canonical: true,
event_type: DbEventTypeId.NonFungibleTokenAsset,
asset_event_type_id: DbAssetEventTypeId.Transfer,
event_index: 1,
tx_id: stxTx1.tx_id,
tx_index: 2,
block_height: dbBlock2.block_height,
asset_identifier: 'some-asset',
value: '0x0000000000000000000000000000000000',
recipient: addr2,
sender: 'none',
};
await db.update({
block: dbBlock2,
microblocks: [],
minerRewards: [],
txs: [
{
tx: stxTx1,
stxLockEvents: [],
stxEvents: [],
ftEvents: [],
nftEvents: [nftEvent2],
contractLogEvents: [],
smartContracts: [],
names: [],
namespaces: [],
pox2Events: [],
pox3Events: [],
pox4Events: [],
},
],
});
const result1 = await supertest(api.server).get(`/extended/v1/address/${addr2}/nft_events`);
expect(result1.status).toBe(200);
expect(result1.type).toBe('application/json');
expect(result1.body.total).toEqual(1);
expect(result1.body.nft_events.length).toEqual(1);
expect(result1.body.nft_events[0].recipient).toBe(addr2);
expect(result1.body.nft_events[0].tx_id).toBe(
'0x1111100000000000000000000000000000000000000000000000000000000001'
);
expect(result1.body.nft_events[0].block_height).toBe(2);
expect(result.body.nft_events[0].value.repr).toBe('0');
//check ownership for addr
const result2 = await supertest(api.server).get(`/extended/v1/address/${addr1}/nft_events`);
expect(result2.status).toBe(200);
expect(result2.type).toBe('application/json');
expect(result2.body.nft_events.length).toEqual(0);
expect(result2.body.total).toEqual(0);
});
test('nft invalid address', async () => {
const result = await supertest(api.server).get(
`/extended/v1/address/invalid-address/nft_events`
);
expect(result.status).toBe(400);
expect(result.type).toBe('application/json');
});
test('/transactions materialized view separates anchored and unanchored counts correctly', async () => { test('/transactions materialized view separates anchored and unanchored counts correctly', async () => {
const contractId = 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft'; const contractId = 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft';

View File

@@ -2,7 +2,6 @@
/extended/v1/address/SP2ZSTSSE61NZTRGWVB18MEQ26AMQ0Z7R70Z2ND36/transactions_with_transfers?limit=50&unanchored=true /extended/v1/address/SP2ZSTSSE61NZTRGWVB18MEQ26AMQ0Z7R70Z2ND36/transactions_with_transfers?limit=50&unanchored=true
/extended/v1/address/SP2Y4WPD4JDQ9A9HCADNTNTE6NTEKCCNDBA373XHY/transactions_with_transfers?limit=50&unanchored=true /extended/v1/address/SP2Y4WPD4JDQ9A9HCADNTNTE6NTEKCCNDBA373XHY/transactions_with_transfers?limit=50&unanchored=true
/extended/v1/block/0x10bc1ba06366077c85b096bfa7b0e4f2f9df1fe3182e1cec8ffa7ee79a11bf92?unanchored=true /extended/v1/block/0x10bc1ba06366077c85b096bfa7b0e4f2f9df1fe3182e1cec8ffa7ee79a11bf92?unanchored=true
/extended/v1/address/SP1TA84JTP4YRFWBK7PYKBA33H3YB60XP654RAR7M/nft_events?limit=50&offset=0
/extended/v1/tx/0x0429af694679c329ba6a7ec0e0c540148b99e720db286589df2b07844c459e62?unanchored=true /extended/v1/tx/0x0429af694679c329ba6a7ec0e0c540148b99e720db286589df2b07844c459e62?unanchored=true
/extended/v1/tx/0xcacb7888089d814974cfdc8ee65ca639f65e7911eeb7f26f05bd4139797be390?event_offset=0&event_limit=200 /extended/v1/tx/0xcacb7888089d814974cfdc8ee65ca639f65e7911eeb7f26f05bd4139797be390?event_offset=0&event_limit=200
/extended/v1/tx/0x2632ee0489174c5e2900b33f0c40dda2c1abcf6f41bb0aa91441e678c4478ea3?unanchored=true /extended/v1/tx/0x2632ee0489174c5e2900b33f0c40dda2c1abcf6f41bb0aa91441e678c4478ea3?unanchored=true
@@ -169,7 +168,6 @@
/extended/v1/block/0x983157ca681cfc98fcb3f655e2bbef2805977fc9a869495da5a71e98ad8b544e?unanchored=true /extended/v1/block/0x983157ca681cfc98fcb3f655e2bbef2805977fc9a869495da5a71e98ad8b544e?unanchored=true
/extended/v1/address/SP374RMXRCP8SZCWYT21KX7ETY3V2WSQPNGEZ7GF8/balances /extended/v1/address/SP374RMXRCP8SZCWYT21KX7ETY3V2WSQPNGEZ7GF8/balances
/extended/v1/address/SP3W3F6SS0G0BSFE1AWA1S7C66EY744W1BJMNT96M/balances /extended/v1/address/SP3W3F6SS0G0BSFE1AWA1S7C66EY744W1BJMNT96M/balances
/extended/v1/tokens/ft/metadata?unanchored=true
/extended/v1/address/SP1QDGYS3D54VK3QX7E0TB11BS6M5JRHGDQJVX01X/balances /extended/v1/address/SP1QDGYS3D54VK3QX7E0TB11BS6M5JRHGDQJVX01X/balances
/extended/v1/tx/0x2cab8e5fe2ec4457a1dbb21bfb351d8342e02b2c7123cf1290ebb817fd531e93?unanchored=true /extended/v1/tx/0x2cab8e5fe2ec4457a1dbb21bfb351d8342e02b2c7123cf1290ebb817fd531e93?unanchored=true
/extended/v1/address/SP1Y56N007J3H18CA2N5T5E4XY3K4V5WD030H0NXC/stx?unanchored=true /extended/v1/address/SP1Y56N007J3H18CA2N5T5E4XY3K4V5WD030H0NXC/stx?unanchored=true
@@ -436,7 +434,6 @@
/extended/v1/address/SP1G9JDXSSWM0EHP2FNMEB5GQ06WA54TMDVM1CNMG/stx /extended/v1/address/SP1G9JDXSSWM0EHP2FNMEB5GQ06WA54TMDVM1CNMG/stx
/extended/v1/address/SP1FEAD66PAAYHQRZG4G6FV0RY1RWBA7SJV6NFXVD/stx?unanchored=true /extended/v1/address/SP1FEAD66PAAYHQRZG4G6FV0RY1RWBA7SJV6NFXVD/stx?unanchored=true
/extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft /extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft
/extended/v1/tokens/ft/metadata?unanchored=true
/extended/v1/address/SP3H3X8ZPY9XJE7Q7DREH7F0RXJJH3EFWBMC8ETFY/transactions_with_transfers?limit=50&unanchored=true /extended/v1/address/SP3H3X8ZPY9XJE7Q7DREH7F0RXJJH3EFWBMC8ETFY/transactions_with_transfers?limit=50&unanchored=true
/extended/v1/tx/mempool?limit=200&address=SP7383KRJA9AQAY9WS1AKAPG4KAR9ERQM3586AZ3&unanchored=true /extended/v1/tx/mempool?limit=200&address=SP7383KRJA9AQAY9WS1AKAPG4KAR9ERQM3586AZ3&unanchored=true
/extended/v1/contract/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-v2-1?unanchored=true /extended/v1/contract/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-v2-1?unanchored=true
@@ -766,7 +763,6 @@
/extended/v1/address/SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft/transactions?limit=30&offset=0&unanchored=true /extended/v1/address/SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft/transactions?limit=30&offset=0&unanchored=true
/extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft /extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft
/extended/v1/tx/0x07f603ca4b210e0a17bd31b56a27f7a98502e1e4db8873ca65574660b0fb15e9?event_offset=0&event_limit=200 /extended/v1/tx/0x07f603ca4b210e0a17bd31b56a27f7a98502e1e4db8873ca65574660b0fb15e9?event_offset=0&event_limit=200
/extended/v1/tokens/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-token-xbtc-usda/ft/metadata?unanchored=true
/extended/v1/address/SP15BBZH3TSP1KT7RNNJ86566WD2K8GT8AH93V3V7/transactions?limit=50 /extended/v1/address/SP15BBZH3TSP1KT7RNNJ86566WD2K8GT8AH93V3V7/transactions?limit=50
/extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft /extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft
/extended/v1/tx/0x8fb7bee09eff178935d1e174ac565ae75a47d074baa2f19f6386ec8daf478bb3?event_offset=0&event_limit=200 /extended/v1/tx/0x8fb7bee09eff178935d1e174ac565ae75a47d074baa2f19f6386ec8daf478bb3?event_offset=0&event_limit=200
@@ -813,9 +809,7 @@
/extended/v1/address/SP2XZ5NT9R6W7PAD9Z72MZA8RRDD168AP28N9CNMV/stx?unanchored=true /extended/v1/address/SP2XZ5NT9R6W7PAD9Z72MZA8RRDD168AP28N9CNMV/stx?unanchored=true
/extended/v1/address/SP2XZ5NT9R6W7PAD9Z72MZA8RRDD168AP28N9CNMV/transactions_with_transfers?limit=50&unanchored=true /extended/v1/address/SP2XZ5NT9R6W7PAD9Z72MZA8RRDD168AP28N9CNMV/transactions_with_transfers?limit=50&unanchored=true
/extended/v1/tx/mempool?limit=30&offset=0&unanchored=true /extended/v1/tx/mempool?limit=30&offset=0&unanchored=true
/extended/v1/tokens/ft/metadata?unanchored=true
/extended/v1/address/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-v2-1/balances?unanchored=true /extended/v1/address/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-v2-1/balances?unanchored=true
/extended/v1/tokens/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.wrapped-stx-token/ft/metadata?unanchored=true
/extended/v1/address/SPJW1XE278YMCEYMXB8ZFGJMH8ZVAAEDP2S2PJYG.stacks-art-market-v2/transactions?limit=30&offset=0&unanchored=true /extended/v1/address/SPJW1XE278YMCEYMXB8ZFGJMH8ZVAAEDP2S2PJYG.stacks-art-market-v2/transactions?limit=30&offset=0&unanchored=true
/extended/v1/tx/mempool?limit=30&offset=0&unanchored=true /extended/v1/tx/mempool?limit=30&offset=0&unanchored=true
/extended/v1/tx/0xc259761a2c7435388a283d15d989f4ec5e8dac7994d0599862009ae95d988fc4?unanchored=true /extended/v1/tx/0xc259761a2c7435388a283d15d989f4ec5e8dac7994d0599862009ae95d988fc4?unanchored=true
@@ -823,7 +817,6 @@
/extended/v1/tx/0x76901f23e486881a855d44c58ea2e9632066d93742e0b63de0b7b6aebfb78c58?unanchored=true /extended/v1/tx/0x76901f23e486881a855d44c58ea2e9632066d93742e0b63de0b7b6aebfb78c58?unanchored=true
/extended/v1/block/0x112d73352fbc27ef4f75bd2b1023d0b16e03ce6d3c169ed8e233fac64c9e5c4b?unanchored=true /extended/v1/block/0x112d73352fbc27ef4f75bd2b1023d0b16e03ce6d3c169ed8e233fac64c9e5c4b?unanchored=true
/extended/v1/address/SP3YK7KWMYRCDMV5M4792T0T7DERQXHJJGGEPV1N8/balances?unanchored=true /extended/v1/address/SP3YK7KWMYRCDMV5M4792T0T7DERQXHJJGGEPV1N8/balances?unanchored=true
/extended/v1/tokens/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-token-wstx-diko/ft/metadata?unanchored=true
/extended/v1/address/SP15BBZH3TSP1KT7RNNJ86566WD2K8GT8AH93V3V7/balances /extended/v1/address/SP15BBZH3TSP1KT7RNNJ86566WD2K8GT8AH93V3V7/balances
/extended/v1/tx/0x350a207e00756a50527216c19682540d46318785efedcec07804ebbd1b28c8ba?unanchored=true /extended/v1/tx/0x350a207e00756a50527216c19682540d46318785efedcec07804ebbd1b28c8ba?unanchored=true
/extended/v1/contract/SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft?unanchored=true /extended/v1/contract/SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft?unanchored=true
@@ -959,11 +952,9 @@
/extended/v1/tx/mempool?limit=200&address=SP1WGEZBR8BCXRA9X6QS3X24X8HPVPF9P1Q8MYTEB /extended/v1/tx/mempool?limit=200&address=SP1WGEZBR8BCXRA9X6QS3X24X8HPVPF9P1Q8MYTEB
/extended/v1/tx/0xc9517fc98a26de0498a4dce5e14007cd200da97acf8ee80f55ace095af87f5b5?unanchored=true /extended/v1/tx/0xc9517fc98a26de0498a4dce5e14007cd200da97acf8ee80f55ace095af87f5b5?unanchored=true
/extended/v1/address/SP37G983VM8T3RPSSQTVA798Y3GPJEXEJK8FJ7M03/transactions_with_transfers?limit=50&unanchored=true /extended/v1/address/SP37G983VM8T3RPSSQTVA798Y3GPJEXEJK8FJ7M03/transactions_with_transfers?limit=50&unanchored=true
/extended/v1/tokens/ft/metadata?unanchored=true
/extended/v1/address/SPV6J95VNA11FAQ3ATFV8JTP78SFGRS6V2EB0SWN/transactions?limit=30&unanchored=true /extended/v1/address/SPV6J95VNA11FAQ3ATFV8JTP78SFGRS6V2EB0SWN/transactions?limit=30&unanchored=true
/extended/v1/address/SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft/transactions?limit=30&offset=0&unanchored=true /extended/v1/address/SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft/transactions?limit=30&offset=0&unanchored=true
/extended/v1/block/0xdbf829d5d1a3f17b35faf0ff0336587e7ac10a8b21a2e001eae539a592351a65?unanchored=true /extended/v1/block/0xdbf829d5d1a3f17b35faf0ff0336587e7ac10a8b21a2e001eae539a592351a65?unanchored=true
/extended/v1/tokens/SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token/ft/metadata?unanchored=true
/extended/v1/address/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-stake-registry-v1-1/transactions?limit=30&offset=0&unanchored=true /extended/v1/address/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-stake-registry-v1-1/transactions?limit=30&offset=0&unanchored=true
/extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft /extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft
/extended/v1/address/SP14V9BXQR5A6M32REYYFDBQQE7FA0Q2R41GD90NK/balances?unanchored=true /extended/v1/address/SP14V9BXQR5A6M32REYYFDBQQE7FA0Q2R41GD90NK/balances?unanchored=true