docs: Added content to the API repo (#1483)

This commit is contained in:
Lavanya Kasturi
2022-12-09 13:50:06 -06:00
committed by GitHub
parent adb2e9df07
commit dce58478f3
27 changed files with 2777 additions and 0 deletions

34
content/faqs.md Normal file
View File

@@ -0,0 +1,34 @@
---
Title: FAQ's
---
# FAQ's
#### **I am attempting to receive the status from a local Stacks Blockchain node API and present to a user how close it is to being synced. I can retrieve the current height of the local node (`/v2/info`). Is there any way for me to retrieve the real current height from an API node that is not completely synced? I want to avoid going directly to the centrally-hosted node.**
Although the Stacks Blockchain API does not yet know when it is in sync mode vs normal "chain follower" mode, you may check the current height of the API by viewing the status endpoint (e.g. https://stacks-node-api.mainnet.stacks.co/extended/v1/status).
You may also review the following issues:
- [Feat/health check endpoint stacks-network/stacks-blockchain#2768](https://github.com/stacks-network/stacks-blockchain/pull/2768)
- [Update /extended/v1/status to "syncing" if more than X blocks are missing](https://github.com/hirosystems/stacks-blockchain-api/issues/1055) stacks-blockchain-api#1055
#### **[/extended/v1/tokens/nft/holdings/?limit=200&principal=SP3EQ7FQ8TFXB792P7VAGRXER0YNFMGM1Y8RS69RC](https://stacks-node-api.mainnet.stacks.co/extended/v1/tokens/nft/holdings/?limit=200&principal=SP3EQ7FQ8TFXB792P7VAGRXER0YNFMGM1Y8RS69RC) is only reporting 49 NFTs; however, the marketplace shows it has 133 NFTs: 92 NFTs for sale, and 41 NFTs are unlisted,. Why is `/holdings/` not returning all results?**
Many marketplace contracts are custodial; meaning, you do not actually own the NFT, but the marketplace contract does (but it has been marked to your address). This is why the NFT does not appear in `/holdings`.
#### **Are there any limits on the number of times I can continuously call the Stacks Blockchain API?**
The Stacks Blockchain API has a rate limit set to ensure all users can make queries to the API. If you exceed this rate limit, you will receive a 429 error. To avoid receiving this error, you may choose to run your own node and the Stacks Blockchain API, or use websockets.
The current rate limts for Stacks Blockchain API are listed in [this](feature-guides/rate-limiting.md) table.
#### **I noticed that the Stacks Blockchain API becomes "stuck" when it is at a certain block height. What can I do to fix this issue?**
If the Stacks Blockchain API becomes "stuck" and does not return a 200 status code from a node block message, causing the node to resend the same message over and over, simply try restarting the full API stack (postgres, API, stacks-blockchain node) with a known-good backup.
You may also file an issue in the [Stacks Blockchain API GitHub repository](https://github.com/hirosystems/stacks-blockchain-api).
#### **I am receiving the following message when attempting to process NFT metadata: "NFT metadata processing is not enabled on this server." Is this expected behavior on mainnet?**
You received this error because the NFT metadata was not standardized at the time the API tried to implement support. If you receive this error, please see the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service) repository for instructions on how to implement NFT metadata processing.

View File

@@ -0,0 +1,15 @@
---
title: Storing data with Gaia
---
# Gaia Storage
The Gaia storage system allows you to store private app data off the blockchain and still access it securely
with Stacks applications. Where possible, apps should only store critical transactional metadata directly to
the Stacks blockchain, while keeping app and user data in the Gaia storage system. For more information about
the Gaia storage system, see the [Gaia protocol reference](https://docs.stacks.co/build-apps/references/gaia).
A [Gaia hub](https://docs.stacks.co/build-apps/references/gaia#user-control-or-how-is-gaia-decentralized) consists of a service and a storage
resource, generally hosted on the same cloud compute provider. The hub service requires an authentication token from a
storage requester, and writes key-value pairs to the associated storage resource. Storage user can choose a Gaia
hub provider. This documentation provides an overview of how to set up and operate a Gaia hub.

View File

@@ -0,0 +1,38 @@
---
Title: Microblocks
---
# Microblocks
> **_NOTE:_**
> Please review the Microblocks API documentation carefully to ensure you are up-to-date on the latest implementation details for microblocks.
The Stacks Blockchain API enables you to query the most recently streamed microblocks when you run the following command:
```bash
# for mainnet, remove `.testnet`
curl 'https://stacks-node-api-microblocks.testnet.stacks.co/extended/v1/microblock'
```
```json
{
"limit": 20,
"offset": 0,
"total": 8766,
"results": [
{
"canonical": true,
"microblock_canonical": true,
"microblock_hash": "0xe6897aab881208185e3fb6ba58d9d9e35c43c68f13fbb892b20cebd39ac69567",
"microblock_sequence": 0,
"microblock_parent_hash": "0xe0d1e8d216a77526ae2ce40294fc77038798a179a6532bb8980d3c2183f58de6",
"parent_index_block_hash": "0x178cd9a37bf38f6b85d9f18e65588e60782753b1463ae080fb9865938b0898ea",
"block_height": 14461,
"parent_block_height": 14460,
"parent_block_hash": "0xe0d1e8d216a77526ae2ce40294fc77038798a179a6532bb8980d3c2183f58de6",
"block_hash": "0x17ceb3da5f36aab351d6b14f5aa77f85bb6b800b954b2f24c564579f80116d99",
"txs": ["0x0622e096dec7e2f6e8f7d95f732e04d238b7381aea8d0aecffae026c53e73e05"]
}
]
}
```

View File

@@ -0,0 +1,29 @@
---
Title: Nonce Handling
---
# Nonce handling
In order to prevent "stuck" transactions, you must track the next available nonce for principals issuing transactions. The
Stacks Blockchain API provides an endpoint to make nonce handling simpler when using the following command:
```bash
# for mainnet, remove `.testnet`
# replace <principal> with your STX address
curl 'https://stacks-node-api-microblocks.testnet.stacks.co/extended/v1/address/<principal>/nonces'
```
```json
{
"last_executed_tx_nonce": 5893,
"last_mempool_tx_nonce": null,
"possible_next_nonce": 5894,
"detected_missing_nonces": []
}
```
The `possible_next_nonce` property is the predicted nonce required for subsequent transactions, which is derived from inspecting the latest transaction nonces from both anchor blocks, microblocks, and mempool.
The `detected_missing_nonces` property finds any non-contiguous nonces after inspecting transactions from anchor blocks, microblocks, and the mempool. For example, if the latest anchor/microblock transaction nonce for an account is 5, but the next nonce in the mempool is 7, then it indicates that something likely went wrong with transaction with nonce 6 (either it was not created or broadcasted correctly by a client, or it was dropped for whatever reason). This is a strong indication that the mempool transaction with nonce 7 will never be mined since the previous nonce is missing.
Clients that continue to broadcast transactions with the `possible_next_nonce` property of 8, then 9, then 10, will likely result in all of their pending/mempool transactions never going through.

View File

@@ -0,0 +1,89 @@
---
Title: Open API Spec
---
# OpenAPI Spec
The Stacks API was designed using the [OpenAPI specification](https://swagger.io/specification/), making it compatible with a variety of developer tools.
The [OpenAPI specification file for Stacks](https://github.com/hirosystems/stacks-blockchain-api/blob/master/docs/openapi.yaml) is used to generate the TypeScript client library. You can use the specification file to generate client libraries for other programming languages using the [openapi-generator tool](https://github.com/OpenAPITools/openapi-generator)
## TypeScript client library
A Typescript client library is available for use of the Stacks API. The client library enables type-safe REST and WebSocket communication with the Stacks API endpoints.
The client is made up of three components:
1. Generated HTTP API client
2. Typescript definitions for [Clarity values](https://docs.stacks.co/docs/write-smart-contracts/values)
3. WebSocket client
The following sections demonstrate common usages of the TypeScript API client.
### HTTP API client sample
The Typescript client library requires you to specify the underlying HTTP request library to handle HTTP communication. The example below uses the universal fetch API [`cross-fetch`](https://github.com/lquixada/cross-fetch):
```js
import fetch from 'cross-fetch';
import { Configuration, AccountsApi } from '@stacks/blockchain-api-client';
(async () => {
const apiConfig = new Configuration({
fetchApi: fetch,
// for mainnet, replace `testnet` with `mainnet`
basePath: 'https://stacks-node-api.testnet.stacks.co', // defaults to http://localhost:3999
});
// initiate the /accounts API with the basepath and fetch library
const accountsApi = new AccountsApi(apiConfig);
// get transactions for a specific account
const txs = await accountsApi.getAccountTransactions({
principal: 'ST000000000000000000002AMW42H',
});
console.log(txs);
})().catch(console.error);
```
### TypeScript sample
The following sample shows how generated [TypeScript models](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client/src/generated/models) can be used for type-safety:
```ts
import fetch from 'cross-fetch';
import {
Configuration,
AccountsApi,
AccountsApiInterface,
AddressBalanceResponse,
AddressBalanceResponseStx,
} from '@stacks/blockchain-api-client';
(async () => {
const apiConfig: Configuration = new Configuration({
fetchApi: fetch,
// for mainnet, replace `testnet` with `mainnet`
basePath: 'https://stacks-node-api.testnet.stacks.co', // defaults to http://localhost:3999
});
const principal: string = 'ST000000000000000000002AMW42H';
// initiate the /accounts API with the basepath and fetch library
const accountsApi: AccountsApiInterface = new AccountsApi(apiConfig);
// get balance for a specific account
const balance: AddressBalanceResponse = await accountsApi.getAccountBalance({
principal,
});
// get STX balance details
const stxAmount: AddressBalanceResponseStx = balance.stx;
console.log(stxAmount);
})().catch(console.error);
```
### WebSocket sample
The WebSocket components enable you to subscribe to specific updates, providing a near real-time display of updates on transactions and accounts.
```js
import { connectWebSocketClient } from '@stacks/blockchain-api-client';
const client = await connectWebSocketClient('ws://stacks-node-api.blockstack.org/');
const sub = await client.subscribeAddressTransactions(contractCall.txId, event => {
console.log(event);
});
await sub.unsubscribe();
```

View File

@@ -0,0 +1,52 @@
---
Title: Pagination
---
# Pagination
To make API responses more compact, lists returned by the API are paginated. For lists, the response body includes:
- `limit`: the number of list items return per response
- `offset`: the number of elements to skip (starting from 0)
- `total`: the number of all available list items
- `results`: the array of list items (length of array equals the set limit)
Here is a sample response:
```json
{
"limit": 10,
"offset": 0,
"total": 101922,
"results": [{
"tx_id": "0x924e0a688664851f5f96b437fabaec19b7542cfcaaf92a97eae43384cacd83d0",
"nonce": 308,
"fee_rate": "0",
"sender_address": "ST39F7SA0AKH7RB363W3NE2DTHD3P32ZHNX2KE7J9",
"sponsored": false,
"post_condition_mode": "deny",
"post_conditions": [],
"anchor_mode": "on_chain_only",
"block_hash": "0x17ceb3da5f36aab351d6b14f5aa77f85bb6b800b954b2f24c564579f80116d99",
"parent_block_hash": "0xe0d1e8d216a77526ae2ce40294fc77038798a179a6532bb8980d3c2183f58de6",
"block_height": 14461,
"burn_block_time": 1622875042,
"burn_block_time_iso": "2021-06-05T06:37:22.000Z",
"canonical": true,
"tx_index": 0,
"tx_status": "success",
"tx_result": {},
"microblock_hash": "",
"microblock_sequence": 2147483647,
"microblock_canonical": true,
"event_count": 0,
"events": [],
"tx_type": "coinbase",
"coinbase_payload": {}
},
{}
]
}
```
Using the `limit` and `offset` properties, you can paginate through the entire list by increasing the offset by the limit until you reach the total.

View File

@@ -0,0 +1,22 @@
---
Title: Rate Limiting
---
# Rate Limiting
Rate limiting will be applied to all API endpoints and [faucet requests](https://docs.hiro.so/api#tag/Faucets), based on the requested token addresses.
You can refer to the rate limit for each endpoint in the table below:
| **Endpoint** | **Rate-Limit (RPM)** |
| ------------------------------------------------------------------------------------------- |-----------------------|
| stacks-node-api.mainnet.stacks.co/extended/ <br/> stacks-node-api.stacks.co/extended/ <br/> | <br/> 500 <br/> <br/> |
| stacks-node-api.mainnet.stacks.co/rosetta/ <br/> stacks-node-api.stacks.co/rosetta/<br/> | <br/> 200 <br/> <br/> |
| stacks-node-api.mainnet.stacks.co/v2/ <br/> stacks-node-api.stacks.co/v2/ <br/> | <br/> 100 <br/> <br/> |
| stacks-node-api.testnet.stacks.co/extended/ <br/> | 300 <br/> |
| stacks-node-api.testnet.stacks.co/v2/ <br/> | 100 <br/> |
| stacks-node-api.testnet.stacks.co/extended/v1/faucets/ <br/> | 1 <br/> |
## STX faucet
The Stacks faucet rate limits depend on the type of request. For stacking requests, there is a limit of **1 request per 2 days**. In case of regular Stacks faucet requests, the limits are set to **1 request per minute**.

View File

@@ -0,0 +1,11 @@
---
Title: Requesting proofs
---
# Requesting Proofs
Several endpoints will request the [MARF Merkel Proof](https://github.com/stacksgov/sips/blob/main/sips/sip-004/sip-004-materialized-view.md#marf-merkle-proofs) by default.
Provided with the proof, a client can verify the value, cumulative energy spent, and the number of confirmation for the response value provided by the API.
Requesting the proof requires more resources (computation time, response time, and response body size). To avoid the additional resources, in case verification is not required, API endpoints allow setting the request parameter: `proof=0`. The returned response object will not have any proof fields.

View File

@@ -0,0 +1,27 @@
---
Title: Rosetta support
---
# Rosetta Support
The Stacks Blockchain API supports [v1.4.6 of the Rosetta specification](https://www.rosetta-api.org/). This industry open standard makes it easy to integrate blockchain deployment and interaction.
# Testing the Rosetta APIs
To build and run the `stx-rosetta.Dockerfile` image, run the following command:
```docker build -t stx-rosetta:stable -f stx-rosetta.Dockerfile .
docker run -d -p 3999:3999 --mount source=rosetta-data,target=/data \
--name stx-rosetta stx-rosetta:stable```
By default, this will connect to the testnet. To run a local node, run the following command:
```docker run -d -p 3999:3999 --mount source=rosetta-data,target=/data \
--name stx-rosetta -e STACKS_NETWORK=mocknet stx-rosetta:stable```
To use a recent version of [rosetta-cli](https://github.com/coinbase/rosetta-cli) to test the endpoints, use the following command:
```rosetta-cli --configuration-file rosetta-cli-config/rosetta-config.json \
view:block 1
rosetta-cli --configuration-file rosetta-cli-config/rosetta-config.json \
check:data```
`rosetta-cli` will then sync with the blockchain until it reaches the tip, and then exit, displaying the test results.
Currently, account reconciliation is disabled; proper testing of that feature requires token transfer transactions while `rosetta-cli` is running.
Documentation for the Rosetta APIs can be found [here](https://hirosystems.github.io/stacks-blockchain-api/)
You may also review Data and Construction Rosetta endpoints [here](https://docs.hiro.so/api#tag/Rosetta)

View File

@@ -0,0 +1,9 @@
---
Title: Search Endpoint
---
# Search Endpoint
The Stacks Blockchain API provides a search endpoint ([`/extended/v1/search/{id}`](https://docs.hiro.so/api#operation/search_by_id)) that takes an identifier and responds with matching blocks, transactions, contracts, or accounts.
The search operation used by the endpoint (for example, `FROM txs WHERE tx_id = $1 LIMIT 1`) matches hashes **equal** to the provided identifier. Fuzzy search, incomplete identifiers, or wildcards will not return any matches.

View File

@@ -0,0 +1,607 @@
---
title: Transactions
---
# Transactions
Transactions are the fundamental unit of execution in the Stacks blockchain. Each transaction is originated from a [Stacks 2.0 account](https://docs.stacks.co/understand-stacks/accounts), and is retained in the Stacks blockchain history. This guide helps you understand Stacks 2.0 transactions.
## Lifecycle
Transactions go through phases before being finally confirmed, and available for all, on the Stacks 2.0 network.
- **Generate**: Transactions are assembled according to the encoding specification.
- **Validate and sign**: Transactions are validated to confirm they are well-formed. Required signatures are filled in.
- **Broadcast**: Transactions are sent to a node.
- **Register**: A miner receives transactions, verifies, and adds them to the ["mempool"](https://academy.binance.com/en/glossary/mempool), a holding area for all the pending transactions.
- **Process**: Miners review the mempool and select transactions for the next block to be mined. Depending on the transaction type, different actions can happen during this step. For example, post-conditions could be verified for a token transfer, smart-contract defined tokens could be minted, or an attempt to call an existing smart contract method could be made.
- **Confirm**: Miners successfully mine blocks with a set of transactions. The transactions inside are successfully propagated to the network.
:::info
A transaction can have one of three states once it is registered: `pending`, `success`, or `failed`.
:::
## Types
The Stacks 2.0 supports a set of different transaction types:
| **Type** | **Value** | **Description** |
| ----------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Coinbase | `coinbase` | The first transaction in a new block (an entity holding several transactions). Used to register for block rewards. These are not manually generated and broadcasted like other types of transactions. |
| Token transfer | `token_transfer` | Asset transfer from a sender to a recipient |
| Contract deploy | `smart_contract` | Contract instantiation |
| Contract call | `contract_call` | Contract call for a public, non read-only function |
| Poison Microblock | `poison_microblock` | Punish leaders who intentionally equivocate about the microblocks they package |
A sample of each transaction type can be found in the [Stacks Blockchain API response definition for transactions](https://docs.hiro.so/api#operation/get_transaction_by_id).
~> Read-only contract call calls do **not** require transactions. Read more about it in the [network guide](https://docs.stacks.co/understand-stacks/network#read-only-function-calls).
## Anchor mode
Transactions can be mined either in an anchor block or in a [microblock](https://docs.stacks.co/understand-stacks/microblocks). If microblocks
are selected, the transaction can be confirmed with a lower latency than the anchor block time.
The anchor mode enum has three options:
- `OnChainOnly` The transaction MUST be included in an anchored block
- `OffChainOnly`: The transaction MUST be included in a microblock
- `Any`: The leader can choose where to include the transaction
Here is an example where the transaction must be included in a microblock:
```js
import { AnchorMode, makeSTXTokenTransfer } from "@stacks/transactions";
import { StacksTestnet, StacksMainnet } from "@stacks/network";
const BigNum = require("bn.js");
const txOptions = {
recipient: "SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159",
amount: new BigNum(12345),
senderKey:
"b244296d5907de9864c0b0d51f98a13c52890be0404e83f273144cd5b9960eed01",
network: new StacksTestnet(), // for mainnet, use `StacksMainnet()`
anchorMode: AnchorMode.OffChainOnly, // must be included in a microblock
};
const transaction = await makeSTXTokenTransfer(txOptions);
```
## Post-conditions
Transaction post-conditions are a feature meant to limit the damage malicious smart contract developers and smart contract bugs can do in terms of destroying a user's assets. Post-conditions are executed whenever a contract is instantiated or a public method of an existing contract is executed. Whenever a post-condition fails, a transaction will be forced to abort.
Post-conditions are meant to be added by the user (or by the user's wallet software) at the moment they sign a transaction. For example, a user may append a post-condition saying that upon successful execution, their account's Stacks (STX) balance should have decreased by no more than 1 STX. If this is not the case, then the transaction would abort and the account would only pay the transaction fee of processing it.
### Attributes
Each transaction includes a field that describes zero or more post-conditions that must all be true when the transaction finishes running. The post-condition describes only properties of the owner of the asset before the transaction happened. For a transfer transaction, the post-condition is about the sender, for a burn transaction, the post-condition is about the previous owner. A post-condition includes the following information:
| **Attribute** | **Sample** | **Description** |
| -------------------------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| [Principal](https://docs.stacks.co/write-smart-contracts/principals) | `SP2ZD731ANQZT6J4K3F5N8A40ZXWXC1XFXHVVQFKE` | original owner of the asset, can be a Stacks address or a contract |
| Asset id | `STX` | Asset to apply conditions to (could be Stacks, fungible, or non-fungible tokens) |
| Comparator | `>=` | Compare operation to be applied (could define "how much" or "whether or not the asset is owned") |
| Literal | `1000000` | Integer or boolean value used to compare instances of the asset against via the condition |
### Evaluation modes
The Stacks blockchain supports an `allow` or `deny` mode for evaluating post-conditions:
- Allow: other asset transfers not covered by the post-conditions are permitted
- Deny: no other asset transfers are permitted besides those named in the post-conditions
## Authorization
Transactions can be authorized in two ways: _standard_ and _sponsored_. The authorization determines whether or not the originating account is also the paying account. In a transaction with a standard authorization, the origin and paying accounts are the same. In a transaction with a sponsored authorization, the origin and paying accounts are distinct, and both accounts must sign the transaction for it to be valid (first the origin, then the spender).
**Sponsored transactions** enable developers and/or infrastructure operators to pay for users to call into their smart contracts, even if users do not have the Stacks (STX) to do so.
The signing flow for sponsored transactions would be to have the user first sign the transaction with their origin account with the intent of it being sponsored (that is, the user must explicitly allow a sponsor to sign), and then have the sponsor sign with their paying account to pay for the user's transaction fee.
## Encoding
A transaction includes the following information. Multiple-byte fields are encoded as big-endian.
| **Type** | **Description** |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Version number | Network version. `0x80` for testnet, `0x0` for mainnet |
| Chain ID | Chain instance ID. `0x80000000` for testnet, `0x00000001` for mainnet |
| Authorization | Type of authorization (`0x04` for standard, `0x05` for sponsored) and [spending conditions](https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md#transaction-authorization) |
| Post-conditions | List of post-conditions, each including a [type ID and variable-length condition body](https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md#transaction-post-conditions-1) |
| Payload | Transaction type and variable-length [payload](https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md#transaction-payloads-1) |
## Construction
The easiest way to construct well-formed transactions is by [using the Stacks Transactions JS library](https://github.com/blockstack/stacks.js/tree/master/packages/transactions#post-conditions). You can construct the following transaction types:
- Stacks token transfer
- Smart contract deploy
- Smart contract function call
When constructing transactions, it is required to set the network the transaction is intended for. This can be either mainnet or testnet. At the moment of this writing, the only available option is the [testnet network](https://docs.stacks.co/understand-stacks/testnet).
:::info
Transactions can be constructed and serialized offline. However, it is required to know the nonce and estimated fees ahead of time. Once internet access is available, the transaction can be broadcasted to the network. Keep in mind that the nonce and fee might change during offline activity, making the transaction invalid.
:::
### Stacks Token transfer
```js
import { makeSTXTokenTransfer } from "@stacks/transactions";
import { StacksTestnet, StacksMainnet } from "@stacks/network";
const BigNum = require("bn.js");
const txOptions = {
recipient: "SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159",
amount: new BigNum(12345),
senderKey:
"b244296d5907de9864c0b0d51f98a13c52890be0404e83f273144cd5b9960eed01",
network: new StacksTestnet(), // for mainnet, use `StacksMainnet()`
memo: "test memo",
nonce: new BigNum(0), // set a nonce manually if you don't want builder to fetch from a Stacks node
fee: new BigNum(200), // set a tx fee if you don't want the builder to estimate
};
const transaction = await makeSTXTokenTransfer(txOptions);
```
:::info
Read more about [nonces](http://docs.stacks.co/understand-stacks/network#nonces) in the network guide
:::
### Smart contract deployment
```js
import { makeContractDeploy } from "@stacks/transactions";
import { StacksTestnet, StacksMainnet } from "@stacks/network";
const BigNum = require("bn.js");
const txOptions = {
contractName: "contract_name",
codeBody: fs.readFileSync("/path/to/contract.clar").toString(),
senderKey:
"b244296d5907de9864c0b0d51f98a13c52890be0404e83f273144cd5b9960eed01",
network: new StacksTestnet(), // for mainnet, use `StacksMainnet()`
};
const transaction = await makeContractDeploy(txOptions);
```
### Smart contract function call
```js
import { makeContractCall, BufferCV } from "@stacks/transactions";
import { StacksTestnet, StacksMainnet } from "@stacks/network";
const BigNum = require("bn.js");
const txOptions = {
contractAddress: "SPBMRFRPPGCDE3F384WCJPK8PQJGZ8K9QKK7F59X",
contractName: "contract_name",
functionName: "contract_function",
functionArgs: [bufferCVFromString("foo")],
senderKey:
"b244296d5907de9864c0b0d51f98a13c52890be0404e83f273144cd5b9960eed01",
// attempt to fetch this contracts interface and validate the provided functionArgs
validateWithAbi: true,
network: new StacksTestnet(), // for mainnet, use `StacksMainnet()`
};
const transaction = await makeContractCall(txOptions);
```
### Clarity value types
Building transactions that call functions in deployed clarity contracts requires you to construct valid Clarity Values to pass to the function as arguments. The [Clarity type system](https://github.com/stacksgov/sips/blob/main/sips/sip-002/sip-002-smart-contract-language.md#clarity-type-system) contains the following types:
| Type | Declaration | Description |
| ---------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Tuple | `(tuple (key-name-0 key-type-0) ...)` | Typed tuple with named fields |
| List | `(list max-len entry-type)` | List of maximum length max-len, with entries of type entry-type |
| Response | `(response ok-type err-type)` | Object used by public functions to commit their changes or abort. May be returned or used by other functions as well, however, only public functions have the commit/abort behavior |
| Optional | `(optional some-type)` | Option type for objects that can either be (some value) or none |
| Buffer | `(buff max-len)` | Byte buffer with maximum length `max-len` |
| Principal | `principal` | Object representing a principal (whether a contract principal or standard principal) |
| Boolean | `bool` | Boolean value ('true or 'false) |
| Signed Integer | `int` | Signed 128-bit integer |
| Unsigned Integer | `uint` | Unsigned 128-bit integer |
| ASCII String | `(define-data-var my-str (string-ascii 11) "hello world")` | String value encoded in ASCII |
| UTF-8 String | `(define-data-var my-str (string-utf8 7) u"hello \u{1234}")` | String value encoded in UTF-8 |
The Stacks Transactions JS library contains TypeScript types and classes that map to the Clarity types, in order to make it easy to construct well-typed Clarity values in JavaScript. These types all extend the abstract class `ClarityValue`.
Here are samples for Clarity value constructions using this library:
```js
// construct boolean clarity values
const t = trueCV();
const f = falseCV();
// construct optional clarity values
const nothing = noneCV();
const something = someCV(t);
// construct a buffer clarity value from an existing Buffer
const buffer = Buffer.from("foo");
const bufCV = bufferCV(buffer);
// construct signed and unsigned integer clarity values
const i = intCV(-10);
const u = uintCV(10);
// construct principal clarity values
const address = "SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B";
const contractName = "contract-name";
const spCV = standardPrincipalCV(address);
const cpCV = contractPrincipalCV(address, contractName);
// construct response clarity values
const errCV = responseErrorCV(trueCV());
const okCV = responseOkCV(falseCV());
// construct tuple clarity values
const tupCV = tupleCV({
a: intCV(1),
b: trueCV(),
c: falseCV(),
});
// construct list clarity values
const l = listCV([trueCV(), falseCV()]);
```
If you develop in Typescript, the type checker can help prevent you from creating wrongly typed Clarity values. For example, the following code won't compile since in Clarity lists are homogeneous, meaning they can only contain values of a single type. It is important to include the type variable `BooleanCV` in this example, otherwise the typescript type checker won't know which type the list is of and won't enforce homogeneity.
```js
const l = listCV < BooleanCV > [trueCV(), intCV(1)];
```
### Setting post-conditions
The Stacks Transactions JS library supports the construction of post conditions.
Here is an example of a post condition that ensures the account's balance will only decrease by no more than 1 STX:
```js
const account = 'SP2ZD731ANQZT6J4K3F5N8A40ZXWXC1XFXHVVQFKE';
const comparator = FungibleConditionCode.GreaterEqual;
// assuming the Stacks (STX) balance before the transaction is 12346
const amount = new BigNum(12345);
const standardSTXPostCondition = makeStandardSTXPostCondition(
account,
comparator,
amount
);
const txOptions = {
..., // other transaction options
postConditions: [standardSTXPostCondition]
}
const transaction = await makeContractCall(txOptions);
```
## Serialization
A well-formed transaction construct is encoded in [Recursive Length Prefix ("RLP")](https://eth.wiki/en/fundamentals/rlp). RLP encoding results in a variable-sized byte array.
In order to broadcast transactions to and between nodes on the network, RLP data is represented in hexadecimal string (also called the **raw format**).
To support an API-friendly and human-readable representation, the [Stacks Blockchain API](/get-started/stacks-blockchain-api) converts transactions into a JSON format.
=> [The Stacks Transactions JS library](https://github.com/blockstack/stacks.js) supports serialization of transactions.
### Raw format
Broadcasting transactions directly to the Stacks Blockchain API or Node RPC API requires the transaction to be serialized and in hexadecimal representation.
```js
// to see the raw serialized tx
const serializedTx = transaction.serialize().toString("hex");
console.log(serializedTx);
```
The preceding method returns the following string:
```bash
8080000000040015c31b8c1c11c515e244b75806bac48d1399c77500000000000000000000000000000000000127e88a68dce8689fc94ff4c186bf8966f8d544c5129ff84d95a2459b5e8e7c39430388f6c8f85cce8c9ce5e6ec1e157116ca4a67d65ab53768b25d5fb5831939030200000000000516df0ba3e79792be7be5e50a370289accfc8c9e03200000000000f424068656c6c6f20776f726c640000000000000000000000000000000000000000000000
```
-> Transaction IDs are generated by hashing the raw transaction with [sha512/256](https://eprint.iacr.org/2010/548.pdf)
### JSON format
When called the Stacks Blockchain API or Node RPC API, transactions returned will be serialized in a JSON format. Here is a token transfer transaction:
```js
{
"tx_id": "0x77cb1bf0804f09ad24b4c494a6c00d5b10bb0afbb94a0d646fa9640eff338e37",
"nonce": 5893,
"fee_rate": "180",
"sender_address": "STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6",
"sponsored": false,
"post_condition_mode": "deny",
"post_conditions": [],
"anchor_mode": "any",
"block_hash": "0xf1e54a3acd04232f1362c09d5096b095363158348303396ea5fc5092e1d8788f",
"parent_block_hash": "0x3de356eb5afa5d7b781f6a925d31d69d218b772ec995930b4e15d92bd15443f9",
"block_height": 13984,
"burn_block_time": 1622678407,
"burn_block_time_iso": "2021-06-03T00:00:07.000Z",
"canonical": true,
"tx_index": 2,
"tx_status": "success",
"tx_result": {
"hex": "0x0703",
"repr": "(ok true)"
},
"microblock_hash": "",
"microblock_sequence": 2147483647,
"microblock_canonical": true,
"event_count": 1,
"events": [],
"tx_type": "token_transfer",
"token_transfer": {
"recipient_address": "STZ4C5RT4WH4JGRQA5E0ZF5PPSQCVY1WRB6E2CGW",
"amount": "500000000",
"memo": "0x46617563657400000000000000000000000000000000000000000000000000000000"
}
}
```
### Deserializing
Serialized, raw transactions can be deserialized without access to the internet using [the Stacks Transactions JS library](https://github.com/blockstack/stacks.js/tree/master/packages/transactions):
```js
import { BufferReader, deserializeTransaction } from "@stacks/transactions";
// receive raw transaction
const serializedTx = "808000000...";
const bufferReader = new BufferReader(Buffer.from(serializedTx));
const deserializedTx = deserializeTransaction(bufferReader);
// print memo
console.log(deserializedTx.payload.memo.content);
```
## Signature and Verification
Every transaction contains verifiable signatures that certify its authenticity. These signatures are generated by signing the transaction hash with the origin's private key. The Elliptic Curve Digital Signature Algorithm (ECDSA) is used for signing, with the curve set to secp256k1. The internal structure that encapsulates the signature is the spending condition. Spending conditions include several parameters including the public key hash, nonce, fee rate and the recoverable ECDSA signature.
When constructing a transaction using the JS library, you can supply the private key and signing will be completed automatically. If you would like to sign the transaction manually, use the `TransactionSigner` class.
Below are the steps taken to generate the signature internal to the transaction library.
### Signing steps
Step 1: Generate a transaction hash for signing. This is the SHA512/256 digest of the serialized transaction before a signature is added.
Step 2: Append the authorization type, fee amount and nonce to the transaction hash to create the signature hash.
Step 3: Generate the SHA512/256 hash of the resulting string from the previous step.
Step 4: Sign the hash using ECDSA and the origin private key.
Step 5: Add the resulting recoverable ECDSA signature to the transaction spending condition.
### Single signature transaction
As the name implies a single signature transaction contains 1 signature from the origin account that authorizes a token spend or smart contract deploy/execution.
### Multi-signature transaction
For multi-sig accounts, multiple keys must sign the transaction for it to be valid.
### Sponsored transaction
A sponsored transaction is one where a second signer sets and pays the transaction fees. The origin must sign the transaction first before the sponsor signs.
## Broadcast
With a serialized transaction in the [raw format](#raw-format), it can be broadcast to the network using the [`POST /v2/transactions`](https://docs.hiro.so/api#operation/post_core_node_transactions) endpoint:
```bash
# for mainnet, replace `testnet` with `mainnet`
curl --location --request POST 'https://stacks-node-api.testnet.stacks.co/v2/transactions' \
--header 'Content-Type: application/octet-stream' \
--data-raw '<tx_raw_format>'
```
The API will respond with a `HTTP 200 - OK` if the transaction was successfully added to the mempool.
There is no explicit time constraint between the construction of a valid signed transaction and when it can be broadcast. There are, however, some constraints to be aware of. The following reasons can deem a transaction invalid after some period:
- Token transfer: Nonce changed in-between construction and broadcast
- Contract call or deploy: Block height is evaluated (with [`at-block`](https://docs.stacks.co/references/language-functions#at-block)) and changed in-between construction and broadcast
## Mempool
Once a transaction has been successfully broadcast to the network, the transaction is added to the mempool of the node
that received the broadcast. From the [Bitcoin wiki][]: "a node's memory pool contains all 0-confirmation transactions
across the entire network that that particular node knows about." So, the set of transactions in the mempool might be
different for each node in the network. For example, when you query the mempool endpoints on
`stacks-node-api.mainnet.stacks.co`, the response reflects the set of unconfirmed transactions known to the nodes that
service that API.
Miners can employ different heuristics and strategies for deciding which transactions to admit into the mempool and
which transactions to include from the mempool when mining a block. Some transactions may be rejected outright (for
example, if there are insufficient funds at an address) while others might be accepted into the mempool, but not mined
into a block indefinitely (for example if fees are too low). Transactions that are admitted in the mempool but not yet
mined are said to be "pending." The current implementation of [stacks-blockchain][] discards pending mempool
transactions after [256 blocks][].
### Best practices
- **Nonce:** it's crucial that transactions use the correct nonce. Using an incorrect nonce makes it less likely that
the transaction is mined in a timely manner. To determine the correct nonce, query the [`accounts`][] endpoint of
the node you intend to broadcast your transaction to. The value of the `nonce` field of the response is the next nonce
that the node expects to consume for that account. Nonce starts at `0`, so the first transaction from an account should
be set to `nonce=0`.
- **Transaction chaining:** even when using the correct nonce, transactions might arrive at a node out-of-order. For
instance, a transaction with `nonce=1` may arrive in the mempool before the `nonce=0` transaction. Stacks nodes admit
such out-of-order transactions in the mempool, but only up to a limit ([25 in the current implementation][]). So, you
should limit any chain of unconfirmed transactions from a single account to less than 25. Making this limit higher has
downsides, discussed in [this issue](https://github.com/blockstack/stacks-blockchain/issues/2384). If you need to send
more than 25 transactions per block, consider using multiple accounts or a smart-contract based approach. See
[this tool](https://www.npmjs.com/package/@stacks/send-many-stx-cli), for example, that allows up to 200 token
transfers in a single transaction.
## Querying
Transactions on the Stacks 2.0 network can be queried using the [Stacks Blockchain API](/get-started/stacks-blockchain-api). The API exposes two interfaces, a RESTful JSON API and a WebSockets API.
For convenience, a Postman Collection was created and published: [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa)
-> Note: The API can be easily consumed using a generated [JS client library](https://hirosystems.github.io/stacks-blockchain-api/client/index.html). The generator uses an OpenAPI specification and supports other languages and frameworks.
@include "stacks-api-pagination.md"
### Get recent transactions
Recent transactions can be obtained through the [`GET /extended/v1/tx`](https://docs.hiro.so/api#operation/get_transaction_list) endpoint:
```bash
# for mainnet, replace `testnet` with `mainnet`
curl 'https://stacks-node-api.testnet.stacks.co/extended/v1/tx'
```
Sample response:
```js
{
"limit": 10,
"offset": 0,
"total": 101922,
"results": [
{
"tx_id": "0x5e9f3933e358df6a73fec0d47ce3e1062c20812c129f5294e6f37a8d27c051d9",
"tx_status": "success",
"tx_type": "coinbase",
"fee_rate": "0",
"sender_address": "ST3WCQ6S0DFT7YHF53M8JPKGDS1N1GSSR91677XF1",
"sponsored": false,
"post_condition_mode": "deny",
"block_hash": "0x58412b50266debd0c35b1a20348ad9c0f17e5525fb155a97033256c83c9e2491",
"block_height": 3231,
"burn_block_time": 1594230455,
"canonical": true,
"tx_index": 0,
"coinbase_payload": {
"data": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
}
]
}
```
### Get mempool transactions
Mempool (registered, but not processed) transactions can be obtained using the [`GET /extended/v1/tx/mempool`](https://docs.hiro.so/api#operation/get_mempool_transaction_list) endpoint:
```bash
# for mainnet, replace `testnet` with `mainnet`
curl 'https://stacks-node-api.testnet.stacks.co/extended/v1/tx/mempool'
```
Sample response:
```js
{
"limit": 96,
"offset": 0,
"total": 5,
"results": [
{
"tx_id": "0xb31df5a363dad31723324cb5e0eefa04d491519fd30827a521cbc830114aa50c",
"tx_status": "pending",
"tx_type": "token_transfer",
"receipt_time": 1598288370,
"receipt_time_iso": "2020-08-24T16:59:30.000Z",
"fee_rate": "180",
"sender_address": "STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6",
"sponsored": false,
"post_condition_mode": "deny",
"token_transfer": {
"recipient_address": "ST1GY25DM8RZV4X15X07THRZ2C5NMWPGQWKFGV87F",
"amount": "500000",
"memo": "0x46617563657400000000000000000000000000000000000000000000000000000000"
}
}
]
}
```
-> The `memo` field is represented as a hexadecimal string of a byte buffer
#### Filter by type
Recent transactions can be filtered by [transaction type](#types) using the `type` query parameter:
```bash
# for mainnet, replace `testnet` with `mainnet`
curl 'https://stacks-node-api.testnet.stacks.co/extended/v1/tx/?type=contract_call'
```
### Get transaction by ID
A specific transaction can be obtained using the [`GET /extended/v1/tx/<tx_id>`](https://docs.hiro.so/api#operation/get_transaction_by_id) endpoint:
```bash
# for mainnet, replace `testnet` with `mainnet`
curl 'https://stacks-node-api.testnet.stacks.co/extended/v1/tx/<tx_id>'
```
Sample response:
```js
{
"limit": 96,
"offset": 0,
"total": 5,
"results": [
{
"tx_id": "0xb31df5a363dad31723324cb5e0eefa04d491519fd30827a521cbc830114aa50c",
"tx_status": "pending",
"tx_type": "token_transfer",
"receipt_time": 1598288370,
"receipt_time_iso": "2020-08-24T16:59:30.000Z",
"fee_rate": "180",
"sender_address": "STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6",
"sponsored": false,
"post_condition_mode": "deny",
"token_transfer": {
"recipient_address": "ST1GY25DM8RZV4X15X07THRZ2C5NMWPGQWKFGV87F",
"amount": "500000",
"memo": "0x46617563657400000000000000000000000000000000000000000000000000000000"
}
}
]
}
```
## Garbage Collection
Broadcast transactions stay in the mempool for 256 blocks (~42 hours). If a transaction is not confirmed within that time, it is removed from the mempool.
!> Most transactions stay in the mempool due to nonce issues. If you see a transaction pending for an unusual time, review the nonce of the account and the transaction.
If a transaction is removed from the mempool, the transaction was not processed and no changes were made to the blockchain state.
[bitcoin wiki]: https://en.bitcoin.it/wiki/Vocabulary#Memory_pool
[256 blocks]: https://github.com/blockstack/stacks-blockchain/blob/master/src/core/mempool.rs#L59
[stacks-blockchain]: https://github.com/blockstack/stacks-blockchain
[`accounts`]: https://docs.stacks.co/understand-stacks/accounts#get-stacks-stx-balance-and-nonce
[25 in the current implementation]: https://github.com/blockstack/stacks-blockchain/blob/08c4b9d61b48b99475c0197e7e7fea50c7fb0e29/src/core/mempool.rs#L66

View File

@@ -0,0 +1,54 @@
---
Title: Use Clarity Values
---
# Using Clarity Values
Some endpoints, like the [read-only function contract call](https://docs.hiro.so/api#operation/call_read_only_function), require input to a serialized [Clarity value](https://docs.stacks.co/docs/write-smart-contracts/values). Other endpoints return serialized values that need to be deserialized.
The example shown below illustrates Clarity value usage in combination with the API.
The `@stacks/transactions` library supports typed contract calls and makes [response value utilization much simpler](https://docs.stacks.co/docs/write-smart-contracts/values#utilizing-clarity-values-from-transaction-responses)
```ts
import {
Configuration,
SmartContractsApiInterface,
SmartContractsApi,
ReadOnlyFunctionSuccessResponse,
} from '@stacks/blockchain-api-client';
import { uintCV, UIntCV, cvToHex, hexToCV, ClarityType } from '@stacks/transactions';
(async () => {
const apiConfig: Configuration = new Configuration({
fetchApi: fetch,
// for mainnet, replace `testnet` with `mainnet`
basePath: 'https://stacks-node-api.testnet.stacks.co', // defaults to http://localhost:3999
});
const contractsApi: SmartContractsApiInterface = new SmartContractsApi(apiConfig);
const principal: string = 'ST000000000000000000002AMW42H';
// use most recent from: https://stacks-node-api.<mainnet/testnet>.stacks.co/v2/pox
const rewardCycle: UIntCV = uintCV(22);
// call a read-only function
const fnCall: ReadOnlyFunctionSuccessResponse = await contractsApi.callReadOnlyFunction({
contractAddress: principal,
contractName: 'pox',
functionName: 'is-pox-active',
readOnlyFunctionArgs: {
sender: principal,
arguments: [cvToHex(rewardCycle)],
},
});
console.log({
status: fnCall.okay,
result: fnCall.result,
representation: hexToCV(fnCall.result).type === ClarityType.BoolTrue,
});
})().catch(console.error);
```

View File

@@ -0,0 +1,33 @@
---
Title: Use Stacks Blockchain API
---
# Use Stacks Blockchain API
The RESTful JSON API can be used without any authorization. The base path for the API is:
```for mainnet, replace `testnet` with `mainnet
https://stacks-node-api.testnet.stacks.co/```
For more information about the Stacks Blockchain API, please refer to the [Stacks API reference](https://docs.hiro.so/api?_gl=1*1nvx6u*_ga*NTQ3NDA3NTIuMTY2MDA3MTQ1MA..*_ga_NB2VBT0KY2*MTY2MzkxNTIzNS4yMi4xLjE2NjM5MTY1OTMuMC4wLjA.) page.
The API is comprised of two parts: the Stacks Blockchain API and the Stacks Node RPC API. The Node RPC API is exposed by every running node. Stacks Blockchain API, however, introduces additional capabilities (for example, retrieving all transactions), while also running proxies calls directly to Stacks Node RPC API.
## Stacks node RPC API
The stacks-node implementation exposes JSON RPC endpoints.
All `/v2/` routes are routed through a proxy to a Hiro-hosted Stacks Node. For a trustless architecture, you should make these requests to a self-hosted node.
## Stacks blockchain API
All `/extended/` routes are provided by the Stacks 2.0 Blockchain API directly, and extend the Stacks Node API capabilities to make integration much easier.
## Running an API server
While Hiro provides a hosted API server of the Stacks Blockchain API, anyone can spin up their own version. Please [follow the instructions in this guide](/get-started/running-api-node) to start a Docker container with the API service running.
Once started, the API is available on `localhost:3999`
[microblocks_api]: https://docs.hiro.so/api#tag/Microblocks

View File

@@ -0,0 +1,26 @@
---
Title: Getting Started
---
# Getting Started
This page describes how you can start the API server and service dependencies.
## Prerequisites
Before you can start the API server and its dependencies, you must first ensure that Docker is already installed on your machine. If you do not aready have Docker installed, please install Docker.
## Starting the API Server
To start the API server:
1. Clone the [Stacks Blockchain API](https://github.com/hirosystems/stacks-blockchain-api) repository.
2. Install the related dependencies with the following command:
`npm install`
3. Start the API server and service dependencies by entering the following command in your terminal:
`Run npm run dev:integrated`
4. Verify the server has started successfully by going to http://localhost:3999/extended/v1/status.

View File

@@ -0,0 +1,13 @@
---
Title: Deploy Service Dependencies
---
# Deploy Service Dependencies
Now that you have installed Docker and started the API server, you should now deploy related service dependencies.
To deploy service dependencies, run the following npm command in your terminal window:
`npm run devenv:deploy`
This command uses `docker-compose` to deploy the service dependencies (for example, PostgreSQL, Stacks core node, etc).

View File

@@ -0,0 +1,29 @@
---
Title: Error Handling
---
# Error Handling
The API can respond with two different error types:
- For URLs that do not match any defined endpoint, an HTTP 404 response is returned. The body of the response lists the URL in reference (as a string)
- For invalid input values (URL/body parameters), an HTTP 400 response is returned. The body of the response is a JSON object with an `error` property. The object also includes stack trace (`stack`) and an error UUID (`errorTag`)
## Proxied Stacks Node RPC API endpoints
The Stacks 2.0 Blockchain API is centrally hosted. However, every running Stacks node exposes an RPC API, which allows you to interact with the underlying blockchain. Instead of using a centrally hosted API, you may directly access the RPC API of a locally hosted node.
**Note:** The Stacks Blockchain API proxies to Node RPC endpoints.
While the Node RPC API doe not provide the same functionality as the hosted Stacks 2.0 Blockchain API, you will have similar functionality in a way that is scoped to that specific node. The RPC API includes the following endpoints:
- [POST /v2/transactions](https://docs.hiro.so/api#operation/post_core_node_transactions)
- [GET /v2/contracts/interface/{contract_address}/{contract_name}](https://docs.hiro.so/api#operation/get_contract_interface)
- [POST /v2/map_entry/{contract_address}/{contract_name}/{map_name}](https://docs.hiro.so/api#operation/get_contract_data_map_entry)
- [GET /v2/contracts/source/{contract_address}/{contract_name}](https://docs.hiro.so/api#operation/get_contract_source)
- [GET /v2/accounts/{principal}](https://docs.hiro.so/api#operation/get_account_info)
- [POST /v2/contracts/call-read/{contract_address}/{contract_name}/{function_name}](https://docs.hiro.so/api#operation/call_read_only_function)
- [GET /v2/fees/transfer](https://docs.hiro.so/api#operation/get_fee_transfer)
- [GET /v2/info](https://docs.hiro.so/api#operation/get_core_api_info)
If you run a local node, the node exposes an HTTP server on port `20443`. The info endpoint would be `localhost:20443/v2/info`.

View File

@@ -0,0 +1,158 @@
---
title: How to install Stacks CLI
---
The Stacks CLI enables interactions with the Stacks 2.0 blockchain through a set of commands.
## Installation
First, ensure you have `npm` installed. Next, run the following command in your terminal:
`npm install -g @stacks/cli`
:::tip
The `-g` flag makes the CLI commands available globally
:::
## Network selection
By default, the CLI will attempt to interact with the mainnet of the Stacks 2.0 blockchain. However, it is possible to override the network and set it to the testnet:
```sh
stx <command> -t
```
:::info
For account usage, that means addresses generated will _only_ be available for the specific network. An account generated for the testnet cannot be used on the mainnet.
:::
Using the `-t` flag causes the CLI to connect to the testnet node at `http://stacks-node-api.blockstack.org:20443`. To specify a node to connect to, add the `-I` flag followed by the URL of the node:
```sh
stx <command> -I "http://localhost:20443"
```
## Account
This section describes how to use the CLI to manage an account.
:::caution
It is not recommended to use the CLI to handle accounts with real STX tokens on the mainnet. Using an appropriate wallet build to support secure token holding is recommended.
:::
### Creating an account
You can generate a new account for testnet by using the `make_keychain` command with the `-t` option:
```bash
stx make_keychain -t
```
Your response should look like this:
```json
{
"mnemonic": "private unhappy random runway boil scissors remove harvest fatigue inherit inquiry still before mountain pet tail mad accuse second milk client rebuild salt chase",
"keyInfo": {
"privateKey": "381314da39a45f43f45ffd33b5d8767d1a38db0da71fea50ed9508e048765cf301",
"address": "ST1BG7MHW2R524WMF7X8PGG3V45ZN040EB9EW0GQJ",
"btcAddress": "n4X37UmRZYk9HawtS1w4xRtqJWhByxiz3c",
"index": 0
}
}
```
The mnemonic is your 24 word seed phrase which you should back up securely if you want access to this account again in the future. Once lost, it cannot be recovered.
The Stacks address associated with the newly generated account is:
`ST1BG7MHW2R524WMF7X8PGG3V45ZN040EB9EW0GQJ`
:::note
The preceding address is a testnet address that can only be used on the testnet.
:::
It is best to store the response of the CLI somewhere. You will need the private key, for instance, to send tokens to others.
### Checking balance
You can check the balance of your account using the following command:
```bash
stx balance ST1BG7MHW2R524WMF7X8PGG3V45ZN040EB9EW0GQJ -t
```
The response should look like this:
```json
{
"balance": "10000",
"nonce": 0
}
```
:::tip
To receive testnet STX tokens, use the [faucet](https://explorer.stacks.co/sandbox/faucet?chain=testnet).
:::
Take note that the nonce for the account is `0`. Account nonce is important for transaction broadcasting.
## Transactions
This section describes how to use the CLI to generate and broadcast transactions.
### Sending tokens
In order to send tokens, the CLI command requires 5 parameters:
- **Recipient Address**: The Stacks address of the recipient
- **Amount**: The number of Stacks to send denoted in microstacks (1 STX = 1000000 microstacks)
- **Fee Rate**: The transaction fee rate for this transaction. You can safely set a fee rate of 200 for Testnet
- **Nonce**: The nonce is a number that needs to be incremented monotonically for each transaction from the account. This ensures transactions are not duplicated
- **Private Key**: This is the private key corresponding to your account that was generated when
The CLI command to use with these parameters is `send_tokens`:
```bash
stx send_tokens ST2KMMVJAB00W5Z6XWTFPH6B13JE9RJ2DCSHYX0S7 1000 200 0 381314da39a45f43f45ffd33b5d8767d1a38db0da71fea50ed9508e048765cf301 -t
```
```json
{
"txid": "0xd32de0d66b4a07e0d7eeca320c37a10111c8c703315e79e17df76de6950c622c",
"transaction": "https://explorer.stacks.co/txid/0xd32de0d66b4a07e0d7eeca320c37a10111c8c703315e79e17df76de6950c622c"
}
```
With this command were sending 1000 microstacks to the Stacks address `ST2KMMVJAB00W5Z6XWTFPH6B13JE9RJ2DCSHYX0S7`.
We set the fee rate to `200` microstacks. If you're not sure how much your transaction will cost.
:::tip
You can add the `-e` flag to estimate the transaction fee needed to get processed by the network, without broadcasting your transaction.
:::
The nonce is set to `0` for this transaction, since it will be the first transaction we send from this account. For subsequent transactions, you will need to increment this number by `1` each time. You can check the current nonce for the account using the `balance` command.
Finally, the last parameter is the private key for the account. `381314da39a45f43f45ffd33b5d8767d1a38db0da71fea50ed9508e048765cf301`
Once again, were using the `-t` option to indicate that this is a Testnet transaction, so it should be broadcasted to Testnet.
If valid, the transaction will be broadcasted to the network and the command will respond with a transaction ID.
:::tip
To obtain the raw, serialized transaction payload without broadcasting it, you can add the `-x` flag
:::

View File

@@ -0,0 +1,395 @@
---
title: How to query Stacks 2.0 blockchain
---
The Stacks 2.0 blockchain API allows you to query the Stacks 2.0 blockchain and interact with smart contracts. It was built to maintain paginated, materialized views of the Stacks 2.0 Blockchain.
:::caution
This API is hosted by Hiro. Using it requires you to trust the hosted server, but provides a faster development experience. Consider [running your own API instance](#running-an-api-server) to create a fully trustless architecture for your app.
:::
The RESTful JSON API can be used without any authorization. The base path for the API is:
```bash
# for mainnet, replace `testnet` with `mainnet`
https://stacks-node-api.testnet.stacks.co/
```
:::info
Review the [Stacks API reference](/api) for more details
:::
The API is comprised of two parts: the Stacks Blockchain API and the Stacks Node RPC API. The Node RPC API is exposed by every running node. Stacks Blockchain API, however, introduces additional capabilities (for example, retrieving all transactions). It also proxies calls directly to Stacks Node RPC API.
### Stacks node RPC API
The [stacks-node implementation](https://github.com/blockstack/stacks-blockchain/) exposes JSON RPC endpoints.
All `/v2/` routes are routed through a proxy to a Hiro-hosted Stacks Node. For a trustless architecture, you should make these requests to a self-hosted node.
### Stacks blockchain API
All `/extended/` routes are provided by the Stacks 2.0 Blockchain API directly. They extend the Stacks Node API capabilities to make it easier to integrate with.
## Using the API
Depending on your development environment, you can access the API through a variety of methods.
The easiest way to start interacting with the API is through the [Postman Collection](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) or [cURL](https://curl.haxx.se/).
:::info
Postman allows you to [generate sample code](https://learning.postman.com/docs/sending-requests/generate-code-snippets/) for API requests for various languages and libraries.
:::
## OpenAPI spec
The Stacks API was designed using the [OpenAPI specification](https://swagger.io/specification/), making it compatible with a variety of developer tools.
The [OpenAPI specification file for Stacks](https://github.com/hirosystems/stacks-blockchain-api/blob/master/docs/openapi.yaml) is used to generate the [TypeScript client library](#typescript-client-library). You can use the specification file to generate client libraries for other programming languages using the [openapi-generator tool](https://github.com/OpenAPITools/openapi-generator)
## TypeScript client library
A Typescript client library is available for use of the Stacks API. The client library enables type-safe REST and WebSocket communication with the Stacks API endpoints. [Review the client documentation for more details](https://hirosystems.github.io/stacks-blockchain-api/client/index.html).
The client is made up of three components:
1. Generated HTTP API client
2. Typescript definitions for [Clarity values](https://docs.stacks.co/docs/write-smart-contracts/values)
3. WebSocket client
The following sections demonstrate common usages of the TypeScript API client.
### HTTP API client sample
The Typescript client library requires you to specify the underlying HTTP request library to handle HTTP communication. The example below uses the universal fetch API [`cross-fetch`](https://github.com/lquixada/cross-fetch):
```js
import fetch from 'cross-fetch';
import { Configuration, AccountsApi } from '@stacks/blockchain-api-client';
(async () => {
const apiConfig = new Configuration({
fetchApi: fetch,
// for mainnet, replace `testnet` with `mainnet`
basePath: 'https://stacks-node-api.testnet.stacks.co', // defaults to http://localhost:3999
});
// initiate the /accounts API with the basepath and fetch library
const accountsApi = new AccountsApi(apiConfig);
// get transactions for a specific account
const txs = await accountsApi.getAccountTransactions({
principal: 'ST000000000000000000002AMW42H',
});
console.log(txs);
})().catch(console.error);
```
### TypeScript sample
The following sample demonstrate how generated [TypeScript models](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client/src/generated/models) can be used for type-safety:
```ts
import fetch from 'cross-fetch';
import {
Configuration,
AccountsApi,
AccountsApiInterface,
AddressBalanceResponse,
AddressBalanceResponseStx,
} from '@stacks/blockchain-api-client';
(async () => {
const apiConfig: Configuration = new Configuration({
fetchApi: fetch,
// for mainnet, replace `testnet` with `mainnet`
basePath: 'https://stacks-node-api.testnet.stacks.co', // defaults to http://localhost:3999
});
const principal: string = 'ST000000000000000000002AMW42H';
// initiate the /accounts API with the basepath and fetch library
const accountsApi: AccountsApiInterface = new AccountsApi(apiConfig);
// get balance for a specific account
const balance: AddressBalanceResponse = await accountsApi.getAccountBalance({
principal,
});
// get STX balance details
const stxAmount: AddressBalanceResponseStx = balance.stx;
console.log(stxAmount);
})().catch(console.error);
```
### WebSocket sample
The WebSocket components enabled you to subscribe to specific updates, enabling a near real-time display of updates on transactions and accounts.
```js
import { connectWebSocketClient } from '@stacks/blockchain-api-client';
const client = await connectWebSocketClient('ws://stacks-node-api.blockstack.org/');
const sub = await client.subscribeAddressTransactions(contractCall.txId, event => {
console.log(event);
});
await sub.unsubscribe();
```
## Rate limiting
Rate limiting is only applied to [faucet requests](https://docs.hiro.so/api#tag/Faucets) based on the requested token addresses.
You can refer to the rate limit for each endpoint in the table below:
| **Endpoint** | **Rate-Limit (RPM)** |
| ------------------------------------------------------------------------------------------- | --------------------- |
| stacks-node-api.mainnet.stacks.co/extended/ <br/> stacks-node-api.stacks.co/extended/ <br/> | <br/> 500 <br/> <br/> |
| stacks-node-api.mainnet.stacks.co/rosetta/ <br/> stacks-node-api.stacks.co/rosetta/<br/> | <br/> 200 <br/> <br/> |
| stacks-node-api.mainnet.stacks.co/v2/ <br/> stacks-node-api.stacks.co/v2/ <br/> | <br/> 100 <br/> <br/> |
| stacks-node-api.testnet.stacks.co/extended/ <br/> | 100 <br/> |
| stacks-node-api.testnet.stacks.co/v2/ <br/> | 100 <br/> |
| stacks-node-api.testnet.stacks.co/extended/v1/faucets/ <br/> | 1 <br/> |
### STX faucet
The Stacks faucet rate limits depend on the type of request. For stacking requests, a limitation of **1 request per 2 days**. In case of regular Stacks faucet requests, the limits are set to **1 request per minute**.
## Pagination
To make API responses more compact, lists returned by the API are paginated. For lists, the response body includes:
- `limit`: the number of list items return per response
- `offset`: the number of elements to skip (starting from 0)
- `total`: the number of all available list items
- `results`: the array of list items (length of array equals the set limit)
Here is a sample response:
```json
{
"limit": 10,
"offset": 0,
"total": 101922,
"results": [{
"tx_id": "0x924e0a688664851f5f96b437fabaec19b7542cfcaaf92a97eae43384cacd83d0",
"nonce": 308,
"fee_rate": "0",
"sender_address": "ST39F7SA0AKH7RB363W3NE2DTHD3P32ZHNX2KE7J9",
"sponsored": false,
"post_condition_mode": "deny",
"post_conditions": [],
"anchor_mode": "on_chain_only",
"block_hash": "0x17ceb3da5f36aab351d6b14f5aa77f85bb6b800b954b2f24c564579f80116d99",
"parent_block_hash": "0xe0d1e8d216a77526ae2ce40294fc77038798a179a6532bb8980d3c2183f58de6",
"block_height": 14461,
"burn_block_time": 1622875042,
"burn_block_time_iso": "2021-06-05T06:37:22.000Z",
"canonical": true,
"tx_index": 0,
"tx_status": "success",
"tx_result": { ... },
"microblock_hash": "",
"microblock_sequence": 2147483647,
"microblock_canonical": true,
"event_count": 0,
"events": [],
"tx_type": "coinbase",
"coinbase_payload": { ... }
},
{ ... }
]
}
```
Using the `limit` and `offset` properties, you can paginate through the entire list by increasing the offset by the limit until you reach the total.
## Requesting proofs
Several endpoints will by default request the [MARF Merkel Proof](https://github.com/stacksgov/sips/blob/main/sips/sip-004/sip-004-materialized-view.md#marf-merkle-proofs).
Provided with the proof, a client can verify the value, cumulative energy spent, and the number of confirmation for the response value provided by the API.
Requesting the proof requires more resources (computation time, response time, and response body size). To avoid the additional resources, in case verification is not required, API endpoints allow setting the request parameter: `proof=0`. The returned response object will not have any proof fields.
## Searching
The API provides a search endpoint ([`/extended/v1/search/{id}`](https://docs.hiro.so/api#operation/search_by_id)) that takes an identifier and responds with matching blocks, transactions, contracts, or accounts.
The search operation used by the endpoint (for example, `FROM txs WHERE tx_id = $1 LIMIT 1`) matches hashes **equal** to the provided identifier. Fuzzy search, incomplete identifiers, or wildcards will not return any matches.
## Using Clarity values
Some endpoints, like the [read-only function contract call](https://docs.hiro.so/api#operation/call_read_only_function), require input to as serialized [Clarity value](https://docs.stacks.co/docs/write-smart-contracts/values). Other endpoints return serialized values that need to be deserialized.
Below is an example for Clarity value usage in combination with the API.
:::info
The example below is for illustration only. The `@stacks/transactions` library supports typed contract calls and makes [response value utilization much simpler](https://docs.stacks.co/docs/write-smart-contracts/values#utilizing-clarity-values-from-transaction-responses)
:::
```ts
import {
Configuration,
SmartContractsApiInterface,
SmartContractsApi,
ReadOnlyFunctionSuccessResponse,
} from '@stacks/blockchain-api-client';
import { uintCV, UIntCV, cvToHex, hexToCV, ClarityType } from '@stacks/transactions';
(async () => {
const apiConfig: Configuration = new Configuration({
fetchApi: fetch,
// for mainnet, replace `testnet` with `mainnet`
basePath: 'https://stacks-node-api.testnet.stacks.co', // defaults to http://localhost:3999
});
const contractsApi: SmartContractsApiInterface = new SmartContractsApi(apiConfig);
const principal: string = 'ST000000000000000000002AMW42H';
// use most recent from: https://stacks-node-api.<mainnet/testnet>.stacks.co/v2/pox
const rewardCycle: UIntCV = uintCV(22);
// call a read-only function
const fnCall: ReadOnlyFunctionSuccessResponse = await contractsApi.callReadOnlyFunction({
contractAddress: principal,
contractName: 'pox',
functionName: 'is-pox-active',
readOnlyFunctionArgs: {
sender: principal,
arguments: [cvToHex(rewardCycle)],
},
});
console.log({
status: fnCall.okay,
result: fnCall.result,
representation: hexToCV(fnCall.result).type === ClarityType.BoolTrue,
});
})().catch(console.error);
```
## Error handling
The API can respond with two different error types:
- For URLs that don't match any defined endpoint, an HTTP 404 is returned. The body lists the URL in reference (as a string)
- For invalid input values (URL/body parameters), an HTTP 500 is returned. The body is a JSON object with an `error` property. The object also includes stack trace (`stack`) and an error UUID (`errorTag`)
## Proxied Stacks Node RPC API endpoints
The Stacks 2.0 Blockchain API is centrally hosted. However, every running Stacks node exposes an RPC API, which allows you to interact with the underlying blockchain. Instead of using a centrally hosted API, you can directly access the RPC API of a locally hosted Node.
:::note
The Stacks Blockchain API proxies to Node RPC endpoints
:::
While the Node RPC API doesn't give the same functionality as the hosted Stacks 2.0 Blockchain API, you get similar functionality in a way that is scoped to that specific node. The RPC API includes the following endpoints:
- [POST /v2/transactions](https://docs.hiro.so/api#operation/post_core_node_transactions)
- [GET /v2/contracts/interface/{contract_address}/{contract_name}](https://docs.hiro.so/api#operation/get_contract_interface)
- [POST /v2/map_entry/{contract_address}/{contract_name}/{map_name}](https://docs.hiro.so/api#operation/get_contract_data_map_entry)
- [GET /v2/contracts/source/{contract_address}/{contract_name}](https://docs.hiro.so/api#operation/get_contract_source)
- [GET /v2/accounts/{principal}](https://docs.hiro.so/api#operation/get_account_info)
- [POST /v2/contracts/call-read/{contract_address}/{contract_name}/{function_name}](https://docs.hiro.so/api#operation/call_read_only_function)
- [GET /v2/fees/transfer](https://docs.hiro.so/api#operation/get_fee_transfer)
- [GET /v2/info](https://docs.hiro.so/api#operation/get_core_api_info)
:::info
If you run a local node, it exposes an HTTP server on port `20443`. The info endpoint would be `localhost:20443/v2/info`.
:::
## Rosetta support
This API supports [v1.4.6 of the Rosetta specification](https://www.rosetta-api.org/). This industry open standard makes it simple to integrate blockchain deployment and interaction.
:::info
Find all Data and Construction Rosetta endpoints [here](https://docs.hiro.so/api#tag/Rosetta)
:::
## Microblocks support
!> API support for microblocks is a work-in-progress. Review the [API documentation][microblocks_api] carefully to
ensure that you are up-to-date on the latest implementation details for microblocks.
The API allows querying the most recently streamed microblocks:
```bash
# for mainnet, remove `.testnet`
curl 'https://stacks-node-api-microblocks.testnet.stacks.co/extended/v1/microblock'
```
```json
{
"limit": 20,
"offset": 0,
"total": 8766,
"results": [
{
"canonical": true,
"microblock_canonical": true,
"microblock_hash": "0xe6897aab881208185e3fb6ba58d9d9e35c43c68f13fbb892b20cebd39ac69567",
"microblock_sequence": 0,
"microblock_parent_hash": "0xe0d1e8d216a77526ae2ce40294fc77038798a179a6532bb8980d3c2183f58de6",
"parent_index_block_hash": "0x178cd9a37bf38f6b85d9f18e65588e60782753b1463ae080fb9865938b0898ea",
"block_height": 14461,
"parent_block_height": 14460,
"parent_block_hash": "0xe0d1e8d216a77526ae2ce40294fc77038798a179a6532bb8980d3c2183f58de6",
"block_hash": "0x17ceb3da5f36aab351d6b14f5aa77f85bb6b800b954b2f24c564579f80116d99",
"txs": ["0x0622e096dec7e2f6e8f7d95f732e04d238b7381aea8d0aecffae026c53e73e05"]
}
]
}
```
## Nonce handling
In order to prevent stuck transactions, you must track the next available nonce for principals issuing transactions. The
API provides an endpoint to make nonce handling simpler:
```bash
# for mainnet, remove `.testnet`
# replace <principal> with your STX address
curl 'https://stacks-node-api-microblocks.testnet.stacks.co/extended/v1/address/<principal>/nonces'
```
```json
{
"last_executed_tx_nonce": 5893,
"last_mempool_tx_nonce": null,
"possible_next_nonce": 5894,
"detected_missing_nonces": []
}
```
You can use the `possible_next_nonce` property as the nonce for your next transaction.
## Running an API server
While Hiro provides a hosted API server of the Stacks Blockchain API, anyone can spin up their own version. Please [follow the instructions in this guide](/get-started/running-api-node) to start a Docker container with the API service running.
:::info
Once started, the API is available on `localhost:3999`
:::
[microblocks_api]: https://docs.hiro.so/api#tag/Microblocks

View File

@@ -0,0 +1,304 @@
---
title: How to run API node
---
This procedure demonstrates how to run a local API node using Docker images. There are several components that must be
configured and run in a specific order for the local API node to work.
For this procedure, the order in which the services are brought up is very important. In order to start the API node
successfully, you need to bring up the services in the following order:
1. `postgres`
2. `stacks-blockchain-api`
3. `stacks-blockchain`
When bringing down the API node, you should bring the services down in the exact reverse order in which they were
brought up, to avoid losing data.
:::note
This procedure focuses on Unix-like operating systems (Linux and MacOS). This procedure has not been tested on
Windows.
:::
## Prerequisites
Running a node has no specialized hardware requirements. Users have been successful in running nodes on Raspberry Pi
boards and other system-on-chip architectures. In order to complete this procedure, you must have the following software
installed on the node host machine:
- [Docker](https://docs.docker.com/get-docker/)
- [curl](https://curl.se/download.html)
- [psql](http://postgresguide.com/utilities/psql.html) (_installed locally_)
- [jq](https://stedolan.github.io/jq/download/)
### Firewall configuration
In order for the API node services to work correctly, you must configure any network firewall rules to allow traffic on
the ports discussed in this section. The details of network and firewall configuration are highly specific to your
machine and network, so a detailed example isn't provided.
The following ports must open on the host machine:
Ingress:
- postgres (open to `localhost` only):
- `5432 TCP`
- stacks-blockchain-api
- `3999 TCP`
- stacks-blockchain (open to `0.0.0.0/0`):
- `20443 TCP`
- `20444 TCP`
Egress:
- `8332`
- `8333`
- `20443-20444`
These egress ports are for syncing [`stacks-blockchain`][] and Bitcoin headers. If they're not open, the sync will fail.
## Step 1: Initial setup
In order to run the API node, you must download the Docker images and create a directory structure to hold the
persistent data from the services. Download and configure the Docker images with the following commands:
```sh
docker pull blockstack/stacks-blockchain-api && docker pull blockstack/stacks-blockchain && docker pull postgres:alpine
docker network create stacks-blockchain > /dev/null 2>&1
```
Create a directory structure for the service data with the following command:
```sh
mkdir -p ./stacks-node/{persistent-data/postgres,persistent-data/stacks-blockchain,bns,config} && cd stacks-node
```
## Step 2: Running Postgres
The `postgres:alpine` Docker container can be run with default settings. You must set the password for the user to
`postgres` with the `POSTGRES_PASSWORD` environment variable. The following command starts the image:
```sh
docker run -d --rm \
--name postgres \
--net=stacks-blockchain \
-e POSTGRES_PASSWORD=postgres \
-v $(pwd)/persistent-data/postgres:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:alpine
```
You can verify the running Postgres instance on port `5432` with the command
```sh
docker ps --filter name=postgres
```
## Step 3: Running Stacks blockchain API
The [`stacks-blockchain-api`][] image requires several environment variables to be set. To reduce the complexity of the
run command, you should create a new `.env` file and add the following to it using a text editor:
```
NODE_ENV=production
GIT_TAG=master
PG_HOST=postgres
PG_PORT=5432
PG_USER=postgres
PG_PASSWORD=postgres
PG_DATABASE=postgres
STACKS_CHAIN_ID=0x00000001
V2_POX_MIN_AMOUNT_USTX=90000000260
STACKS_CORE_EVENT_PORT=3700
STACKS_CORE_EVENT_HOST=0.0.0.0
STACKS_BLOCKCHAIN_API_PORT=3999
STACKS_BLOCKCHAIN_API_HOST=0.0.0.0
STACKS_BLOCKCHAIN_API_DB=pg
STACKS_CORE_RPC_HOST=stacks-blockchain
STACKS_CORE_RPC_PORT=20443
BNS_IMPORT_DIR=/bns-data
```
:::info
This guide configures the API to import BNS data with the `BNS_IMPORT_DIR` variable. To turn off this import, comment
the line out by placing a `#` at the beginning of the line. If you leave the BNS import enabled, it may take several
minutes for the container to start while it imports the data.
:::
The `PG_HOST` and `STACKS_CORE_RPC_HOST` variables define the container names for `postgres` and `stacks-blockchain`.
You may wish to alter those values if you have named those containers differently than this guide.
Start the [`stacks-blockchain-api`][] image with the following command:
```sh
docker run -d --rm \
--name stacks-blockchain-api \
--net=stacks-blockchain \
--env-file $(pwd)/.env \
-v $(pwd)/bns:/bns-data \
-p 3700:3700 \
-p 3999:3999 \
blockstack/stacks-blockchain-api
```
You can verify the running `stacks-blockchain-api` container with the command:
```sh
docker ps --filter name=stacks-blockchain-api
```
## Step 4: Running Stacks blockchain
In order for the API to be functional, the [`stacks-blockchain-api`][] container must have data from a running
[`stacks-blockchain`][] instance. First create the `./config/Config.toml` file and add the following content to the
file using a text editor:
```toml
[node]
working_dir = "/root/stacks-node/data"
rpc_bind = "0.0.0.0:20443"
p2p_bind = "0.0.0.0:20444"
bootstrap_node = "02da7a464ac770ae8337a343670778b93410f2f3fef6bea98dd1c3e9224459d36b@seed-0.mainnet.stacks.co:20444,02afeae522aab5f8c99a00ddf75fbcb4a641e052dd48836408d9cf437344b63516@seed-1.mainnet.stacks.co:20444,03652212ea76be0ed4cd83a25c06e57819993029a7b9999f7d63c36340b34a4e62@seed-2.mainnet.stacks.co:20444"
wait_time_for_microblocks = 10000
[[events_observer]]
endpoint = "stacks-blockchain-api:3700"
retry_count = 255
events_keys = ["*"]
[burnchain]
chain = "bitcoin"
mode = "mainnet"
peer_host = "bitcoin.blockstack.com"
username = "blockstack"
password = "blockstacksystem"
rpc_port = 8332
peer_port = 8333
[connection_options]
read_only_call_limit_write_length = 0
read_only_call_limit_read_length = 100000
read_only_call_limit_write_count = 0
read_only_call_limit_read_count = 30
read_only_call_limit_runtime = 1000000000
```
The `[[events_observer]]` block configures the instance to send blockchain events to the API container that you
started previously.
Start the [`stacks-blockchain`][] container with the following command:
```sh
docker run -d --rm \
--name stacks-blockchain \
--net=stacks-blockchain \
-v $(pwd)/persistent-data/stacks-blockchain:/root/stacks-node/data \
-v $(pwd)/config:/src/stacks-node \
-p 20443:20443 \
-p 20444:20444 \
blockstack/stacks-blockchain \
/bin/stacks-node start --config /src/stacks-node/Config.toml
```
You can verify the running [`stacks-blockchain`][] container with the command:
```sh
docker ps --filter name=stacks-blockchain
```
## Step 5: Verifying the services
You can now verify that each of the services is running and talking to the others.
To verify the database is ready:
1. Connect to the Postgres instance with the command `psql -h localhost -U postgres`. Use the password from the
`POSTGRES_PASSWORD` environment variable you set when running the container.
2. List current databases with the command `\l`
3. Disconnect from the database with the command `\q`
To verify the [`stacks-blockchain`][] tip height is progressing use the following command:
```sh
curl -sL localhost:20443/v2/info | jq
```
If the instance is running you should receive terminal output similar to the following:
```json
{
"peer_version": 402653184,
"pox_consensus": "89d752034e73ed10d3b97e6bcf3cff53367b4166",
"burn_block_height": 666143,
"stable_pox_consensus": "707f26d9d0d1b4c62881a093c99f9232bc74e744",
"stable_burn_block_height": 666136,
"server_version": "stacks-node 2.0.11.1.0-rc1 (master:67dccdf, release build, linux [x86_64])",
"network_id": 1,
"parent_network_id": 3652501241,
"stacks_tip_height": 61,
"stacks_tip": "e08b2fe3dce36fd6d015c2a839c8eb0885cbe29119c1e2a581f75bc5814bce6f",
"stacks_tip_consensus_hash": "ad9f4cb6155a5b4f5dcb719d0f6bee043038bc63",
"genesis_chainstate_hash": "74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b",
"unanchored_tip": "74d172df8f8934b468c5b0af2efdefe938e9848772d69bcaeffcfe1d6c6ef041",
"unanchored_seq": 0,
"exit_at_block_height": null
}
```
Verify the [`stacks-blockchain-api`][] is receiving data from the [`stacks-blockchain`][] with the following command:
```sh
curl -sL localhost:3999/v2/info | jq
```
If the instance is configured correctly, you should receive terminal output similar to the following:
```json
{
"peer_version": 402653184,
"pox_consensus": "e472cadc17dcf3bc1afafc6aa595899e55f25b72",
"burn_block_height": 666144,
"stable_pox_consensus": "6a6fb0aa75a8acd4919f56c9c4c81ce5bc42cac1",
"stable_burn_block_height": 666137,
"server_version": "stacks-node 2.0.11.1.0-rc1 (master:67dccdf, release build, linux [x86_64])",
"network_id": 1,
"parent_network_id": 3652501241,
"stacks_tip_height": 61,
"stacks_tip": "e08b2fe3dce36fd6d015c2a839c8eb0885cbe29119c1e2a581f75bc5814bce6f",
"stacks_tip_consensus_hash": "ad9f4cb6155a5b4f5dcb719d0f6bee043038bc63",
"genesis_chainstate_hash": "74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b",
"unanchored_tip": "74d172df8f8934b468c5b0af2efdefe938e9848772d69bcaeffcfe1d6c6ef041",
"unanchored_seq": 0,
"exit_at_block_height": null
}
```
Once the API is running, you can use it to [interact with other API endpoints][`stacks-blockchain-api`].
## Stopping the API node
As discussed previously, if you want to bring down your API node, you must stop the services in the reverse order that
you started them. Performing the shutdown in this order ensures that you don't lose any data while shutting down
the node.
Use the following commands to stop the local API node:
```sh
docker stop stacks-blockchain
docker stop stacks-blockchain-api
docker stop postgres
```
## Additional reading
- [Running an API instance with Docker][] in the `stacks-blockchain-api` repository
- [Running an API instance from source][] in the `stacks-blockchain-api` repository
[running an api instance with docker]: https://github.com/hirosystems/stacks-blockchain-api/blob/master/running_an_api.md
[running an api instance from source]: https://github.com/hirosystems/stacks-blockchain-api/blob/master/running_api_from_source.md
[`stacks-blockchain`]: https://github.com/blockstack/stacks-blockchain
[`stacks-blockchain-api`]: https://github.com/hirosystems/stacks-blockchain-api

View File

@@ -0,0 +1,174 @@
---
title: How to run mainnet node
---
This procedure demonstrates how to run a local mainnet node using Docker images.
:::note
This procedure focuses on Unix-like operating systems (Linux and MacOS). This procedure has not been tested on
Windows.
:::
## Prerequisites
Running a node has no specialized hardware requirements. Users have been successful in running nodes on Raspberry Pi
boards and other system-on-chip architectures. In order to complete this procedure, you must have the following software
installed on the node host machine:
- [Docker](https://docs.docker.com/get-docker/)
- [curl](https://curl.se/download.html)
- [jq](https://stedolan.github.io/jq/download/)
### Firewall configuration
In order for the API node services to work correctly, you must configure any network firewall rules to allow traffic on
the ports discussed in this section. The details of network and firewall configuration are highly specific to your
machine and network, so a detailed example isn't provided.
The following ports must open on the host machine:
Ingress:
- stacks-blockchain (open to `0.0.0.0/0`):
- `20443 TCP`
- `20444 TCP`
Egress:
- `8332`
- `8333`
- `20443-20444`
These egress ports are for syncing [`stacks-blockchain`][] and Bitcoin headers. If they're not open, the sync will fail.
## Step 1: Initial setup
In order to run the mainnet node, you must download the Docker images and create a directory structure to hold the
persistent data from the services. Download and configure the Docker images with the following commands:
```sh
docker pull blockstack/stacks-blockchain
```
Create a directory structure for the service data with the following command:
```sh
mkdir -p ./stacks-node/{persistent-data/stacks-blockchain/mainnet,config/mainnet} && cd stacks-node
```
## Step 2: Running Stacks blockchain
First, create the `./config/Config.toml` file and add the following content to the
file using a text editor:
```toml
[node]
working_dir = "/root/stacks-node/data"
rpc_bind = "0.0.0.0:20443"
p2p_bind = "0.0.0.0:20444"
bootstrap_node = "02da7a464ac770ae8337a343670778b93410f2f3fef6bea98dd1c3e9224459d36b@seed-0.mainnet.stacks.co:20444,02afeae522aab5f8c99a00ddf75fbcb4a641e052dd48836408d9cf437344b63516@seed-1.mainnet.stacks.co:20444,03652212ea76be0ed4cd83a25c06e57819993029a7b9999f7d63c36340b34a4e62@seed-2.mainnet.stacks.co:20444"
wait_time_for_microblocks = 10000
[burnchain]
chain = "bitcoin"
mode = "mainnet"
peer_host = "bitcoin.blockstack.com"
username = "blockstack"
password = "blockstacksystem"
rpc_port = 8332
peer_port = 8333
[connection_options]
read_only_call_limit_write_length = 0
read_only_call_limit_read_length = 100000
read_only_call_limit_write_count = 0
read_only_call_limit_read_count = 30
read_only_call_limit_runtime = 1000000000
```
Start the [`stacks-blockchain`][] container with the following command:
```sh
docker run -d --rm \
--name stacks-blockchain \
-v $(pwd)/persistent-data/stacks-blockchain/mainnet:/root/stacks-node/data \
-v $(pwd)/config/mainnet:/src/stacks-node \
-p 20443:20443 \
-p 20444:20444 \
blockstack/stacks-blockchain \
/bin/stacks-node start --config /src/stacks-node/Config.toml
```
You can verify the running [`stacks-blockchain`][] container with the command:
```sh
docker ps --filter name=stacks-blockchain
```
## Step 3: Verifying the services
:::info
The initial header sync can take several minutes, until this is done the following commands will not work.
:::
To verify the [`stacks-blockchain`][] burn chain header sync progress:
```sh
docker logs stacks-blockchain
```
The output should be similar to the following:
```
INFO [1626290705.886954] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitcoin headers: 1.2% (8000 out of 691034)
INFO [1626290748.103291] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitcoin headers: 1.4% (10000 out of 691034)
INFO [1626290776.956535] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitcoin headers: 1.7% (12000 out of 691034)
```
To verify the [`stacks-blockchain`][] tip height is progressing use the following command:
```sh
curl -sL localhost:20443/v2/info | jq
```
If the instance is running you should receive terminal output similar to the following:
```json
{
"peer_version": 402653184,
"pox_consensus": "89d752034e73ed10d3b97e6bcf3cff53367b4166",
"burn_block_height": 666143,
"stable_pox_consensus": "707f26d9d0d1b4c62881a093c99f9232bc74e744",
"stable_burn_block_height": 666136,
"server_version": "stacks-node 2.0.11.1.0-rc1 (master:67dccdf, release build, linux [x86_64])",
"network_id": 1,
"parent_network_id": 3652501241,
"stacks_tip_height": 61,
"stacks_tip": "e08b2fe3dce36fd6d015c2a839c8eb0885cbe29119c1e2a581f75bc5814bce6f",
"stacks_tip_consensus_hash": "ad9f4cb6155a5b4f5dcb719d0f6bee043038bc63",
"genesis_chainstate_hash": "74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b",
"unanchored_tip": "74d172df8f8934b468c5b0af2efdefe938e9848772d69bcaeffcfe1d6c6ef041",
"unanchored_seq": 0,
"exit_at_block_height": null
}
```
## Stopping the mainnet node
Use the following commands to stop the local mainnet node:
```sh
docker stop stacks-blockchain
```
## Additional reading
- [Running an API instance with Docker][]
[running a testnet node with docker]: /get-started/running-testnet-node
[running an api instance with docker]: /get-started/running-api-node
[`stacks-blockchain`]: https://github.com/blockstack/stacks-blockchain

View File

@@ -0,0 +1,328 @@
---
Title: Run a Stacks Blockchain API instance with Docker
---
# Run a Stacks Blockchain API instance with Docker
On this page, you will learn how to run a [stacks-blockchain-api](https://github.com/hirosystems/stacks-blockchain-api) instance. There are several components involved here to have a working setup, and descriptions will be given for each of these components.
This page will also focus on the **easy** path to get the services running, which is currently Docker.
Please note that the following guide is meant for a Unix-like OS (Linux/MacOS). The commands *may* work on Windows but will likely need some adjustments.
- [Run a Stacks Blockchain API instance with Docker](#run-a-stacks-blockchain-api-instance-with-docker)
- [Requirements](#requirements)
- [Firewalling](#firewalling)
- [Initial Setup](#initial-setup)
- [Postgres](#postgres)
- [Starting postgres](#starting-postgres)
- [Stopping Postgres](#stopping-postgres)
- [Stacks Blockchain API](#stacks-blockchain-api)
- [Starting stacks-blockchain-api](#starting-stacks-blockchain-api)
- [Stopping stacks-blockchain-api](#stopping-stacks-blockchain-api)
- [Stacks Blockchain](#stacks-blockchain)
- [Starting stacks-blockchain](#starting-stacks-blockchain)
- [Stopping stacks-blockchain](#stopping-stacks-blockchain)
- [Verify Everything is running correctly](#verify-everything-is-running-correctly)
- [Postgres testing](#postgres-testing)
- [stacks-blockchain testing](#stacks-blockchain-testing)
- [stacks-blockchain-api testing](#stacks-blockchain-api-testing)
## Requirements
1. [Docker](https://docs.docker.com/engine/install/)
2. `bash` or some other Unix-like shell (i.e. `zsh`)
3. `curl` binary
**Note:** The order of operations here is important.
Essentially, to start the API successfully you will want to perform the following steps **in order**:
1. [start postgres](#starting-postgres)
2. [start stacks-blockchain-api](#starting-stacks-blockchain-api)
3. [start stacks-blockchain](#starting-stacks-blockchain)
Conversely, to bring down the API and *NOT* lose any data, perform the same steps **in Reverse**:
1. [stop stacks-blockchain](#stopping-stacks-blockchain)
2. [stop stacks-blockchain-api](#stopping-stacks-blockchain-api)
3. [stop postgres](#stopping-postgres)
### Firewalling
In order for the services to work correctly, the host will need some ports open.
**Default Ingress Ports**:
- postgres (*open to `localhost` only*):
- `5432 TCP`
- stacks-blockchain (*open to `0.0.0.0/0`*):
- `20443 TCP`
- `20444 TCP`
- stacks-blockchain-api (*open to where you want to access the api from*):
- `3999 TCP`
**Default Egress Ports**:
The only egress ports you will need (outside of what you need normally to install/update packages) are:
- `8332`
- `8333`
- `20443-20444`
These are the ports used to sync the stacks-blockchain and the bitcoin headers. If they are not open, the sync **will** fail.
### Initial Setup
Since you will need to create some files/dirs for persistent data, you must first create a base directory structure and download the docker images.
You should use the following command:
```bash
$ mkdir -p ./stacks-node/{persistent-data/postgres,persistent-data/stacks-blockchain,config}
$ docker pull blockstack/stacks-blockchain-api \
&& docker pull blockstack/stacks-blockchain \
&& docker pull postgres:alpine
$ docker network create stacks-blockchain > /dev/null 2>&1
$ cd ./stacks-node
```
## Postgres
The `postgres:alpine` image can be run with default settings, the only requirement is that a password Environment
Variable is set for the `postgres` user: `POSTGRES_PASSWORD=postgres`
### Starting postgres
```bash
docker run -d --rm \
--name postgres \
--net=stacks-blockchain \
-e POSTGRES_PASSWORD=postgres \
-v $(pwd)/persistent-data/postgres:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:alpine
```
There should now be a running postgres instance running on port `5432`:
```bash
$ docker ps --filter name=postgres
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f835f3a8cfd4 postgres:alpine "docker-entrypoint.s…" 1 minute ago Up 1 minute 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp postgres
```
### Stopping Postgres
To stop the postgres service (this will also remove the container, but not the data), run the following command:
```bash
$ docker stop postgres
```
## Stacks Blockchain API
The Stacks Blockchain API requires you to set several environment variables in order to run properly.
To reduce complexity, create a `.env` file that you will use for these environment variables.
Create a new file: `./.env` with the following content:
```none
NODE_ENV=production
GIT_TAG=master
PG_HOST=postgres
PG_PORT=5432
PG_USER=postgres
PG_PASSWORD=postgres
PG_DATABASE=postgres
STACKS_CHAIN_ID=0x00000001
V2_POX_MIN_AMOUNT_USTX=90000000260
STACKS_CORE_EVENT_PORT=3700
STACKS_CORE_EVENT_HOST=0.0.0.0
STACKS_BLOCKCHAIN_API_PORT=3999
STACKS_BLOCKCHAIN_API_HOST=0.0.0.0
STACKS_CORE_RPC_HOST=stacks-blockchain
STACKS_CORE_RPC_PORT=20443
API_DOCS_URL=https://docs.hiro.so/api
```
The other environment variables to pay attention to are:
- `PG_HOST`: Set this to your **postgres** instance. In this guide, we'll be using a container named `postgres`.
- `STACKS_CORE_RPC_HOST`: Set this to your **stacks blockchain** node. In this guide, we'll be using a container named `stacks-blockchain`.
- `API_DOCS_URL`: Set this to enable your docs API http://localhost:3999/doc.
### Starting stacks-blockchain-api
Run the following command to run Stacks Blockchain API:
```bash
docker run -d --rm \
--name stacks-blockchain-api \
--net=stacks-blockchain \
--env-file $(pwd)/.env \
-p 3700:3700 \
-p 3999:3999 \
blockstack/stacks-blockchain-api
```
You shoudl now have a running stacks-blockchain-api instance running on ports `3999` and `3700`:
```bash
e$ docker ps --filter name=stacks-blockchain-api
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a86a26da6c5a blockstack/stacks-blockchain-api "docker-entrypoint.s…" 1 minute ago Up 1 minute 0.0.0.0:3700->3700/tcp, :::3700->3700/tcp, 0.0.0.0:3999->3999/tcp, :::3999->3999/tcp stacks-blockchain-api
```
> **_NOTE:_**
>
> On initial sync, it will take several minutes for port `3999` to become available.
### Stopping stacks-blockchain-api
To stop the stacks-blockchain-api service (this will also remove the container), run the following command:
```bash
$ docker stop stacks-blockchain-api
```
## Stacks Blockchain
In order to have a **usable** API instance, you need to have data from a running [stacks-blockchain](https://github.com/blockstack/stacks-blockchain) instance.
Because the focus is on running the API with Docker, it also makes things easier if you also run the stacks-blockchain instance the same way.
With that in mind, you will need to have the following configuration in your `Config.toml`. This configuration block will send blockchain events to the API instance that was previously started:
```toml
[[events_observer]]
endpoint = "<fqdn>:3700"
retry_count = 255
events_keys = ["*"]
```
Here is an example `Config.toml` that you can use - create this file as `./config/mainnet/Config.toml`:
```toml
[node]
working_dir = "/root/stacks-node/data"
rpc_bind = "0.0.0.0:20443"
p2p_bind = "0.0.0.0:20444"
bootstrap_node = "02da7a464ac770ae8337a343670778b93410f2f3fef6bea98dd1c3e9224459d36b@seed-0.mainnet.stacks.co:20444,02afeae522aab5f8c99a00ddf75fbcb4a641e052dd48836408d9cf437344b63516@seed-1.mainnet.stacks.co:20444,03652212ea76be0ed4cd83a25c06e57819993029a7b9999f7d63c36340b34a4e62@seed-2.mainnet.stacks.co:20444"
wait_time_for_microblocks = 10000
[[events_observer]]
endpoint = "stacks-blockchain-api:3700"
retry_count = 255
events_keys = ["*"]
[burnchain]
chain = "bitcoin"
mode = "mainnet"
peer_host = "bitcoin.blockstack.com"
username = "blockstack"
password = "blockstacksystem"
rpc_port = 8332
peer_port = 8333
[connection_options]
read_only_call_limit_write_length = 0
read_only_call_limit_read_length = 100000
read_only_call_limit_write_count = 0
read_only_call_limit_read_count = 30
read_only_call_limit_runtime = 1000000000
```
### Starting stacks-blockchain
```bash
docker run -d --rm \
--name stacks-blockchain \
--net=stacks-blockchain \
-v $(pwd)/persistent-data/stacks-blockchain:/root/stacks-node/data \
-v $(pwd)/config:/src/stacks-node \
-p 20443:20443 \
-p 20444:20444 \
blockstack/stacks-blockchain \
/bin/stacks-node start --config /src/stacks-node/Config.toml
```
You should now see a running stacks-blockchain instance running on ports `20443-20444`:
```bash
$ docker ps --filter name=stacks-blockchain$
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
199e37a324f1 blockstack/stacks-blockchain "/bin/stacks-node st…" 1 minute ago Up 1 minute 0.0.0.0:20443-20444->20443-20444/tcp, :::20443-20444->20443-20444/tcp stacks-blockchain
```
### Stopping stacks-blockchain
To stop the stacks-blockchain service (this will also remove the container, but not the data), run the following command:
```bash
$ docker stop stacks-blockchain
```
## Verify Everything is running correctly
### Postgres testing
To verfiy the database is ready:
1. Connect to the DB instance: `psql -h localhost -U postgres`
- *this will require a locally installed postgresql client*
- use the password from the [Environment Variable](#postgres) `POSTGRES_PASSWORD`
2. List current databases: `\l`
3. Disconnect from the DB : `\q`
### stacks-blockchain testing
Verify the stacks-blockchain tip height is progressing:
```bash
$ curl -sL localhost:20443/v2/info | jq
{
"peer_version": 402653184,
"pox_consensus": "89d752034e73ed10d3b97e6bcf3cff53367b4166",
"burn_block_height": 666143,
"stable_pox_consensus": "707f26d9d0d1b4c62881a093c99f9232bc74e744",
"stable_burn_block_height": 666136,
"server_version": "stacks-node 2.0.11.1.0-rc1 (master:67dccdf, release build, linux [x86_64])",
"network_id": 1,
"parent_network_id": 3652501241,
"stacks_tip_height": 61,
"stacks_tip": "e08b2fe3dce36fd6d015c2a839c8eb0885cbe29119c1e2a581f75bc5814bce6f",
"stacks_tip_consensus_hash": "ad9f4cb6155a5b4f5dcb719d0f6bee043038bc63",
"genesis_chainstate_hash": "74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b",
"unanchored_tip": "74d172df8f8934b468c5b0af2efdefe938e9848772d69bcaeffcfe1d6c6ef041",
"unanchored_seq": 0,
"exit_at_block_height": null
}
```
### stacks-blockchain-api testing
Verify the stacks-blockchain-api is receiving data from the stacks-blockchain:
```bash
$ curl -sL localhost:3999/v2/info | jq
{
"peer_version": 402653184,
"pox_consensus": "e472cadc17dcf3bc1afafc6aa595899e55f25b72",
"burn_block_height": 666144,
"stable_pox_consensus": "6a6fb0aa75a8acd4919f56c9c4c81ce5bc42cac1",
"stable_burn_block_height": 666137,
"server_version": "stacks-node 2.0.11.1.0-rc1 (master:67dccdf, release build, linux [x86_64])",
"network_id": 1,
"parent_network_id": 3652501241,
"stacks_tip_height": 61,
"stacks_tip": "e08b2fe3dce36fd6d015c2a839c8eb0885cbe29119c1e2a581f75bc5814bce6f",
"stacks_tip_consensus_hash": "ad9f4cb6155a5b4f5dcb719d0f6bee043038bc63",
"genesis_chainstate_hash": "74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b",
"unanchored_tip": "74d172df8f8934b468c5b0af2efdefe938e9848772d69bcaeffcfe1d6c6ef041",
"unanchored_seq": 0,
"exit_at_block_height": null
}
```
Now that everything is running, you can [try some of these other API endpoints](https://hirosystems.github.io/stacks-blockchain-api/)

View File

@@ -0,0 +1,145 @@
---
title: How to run testnet node
---
This procedure demonstrates how to run a local testnet node using Docker images.
:::note
This procedure focuses on Unix-like operating systems (Linux and MacOS). This procedure has not been tested on
Windows.
:::
## Prerequisites
Running a node has no specialized hardware requirements. Users have been successful in running nodes on Raspberry Pi
boards and other system-on-chip architectures. In order to complete this procedure, you must have the following software
installed on the node host machine:
- [Docker](https://docs.docker.com/get-docker/)
- [curl](https://curl.se/download.html)
- [jq](https://stedolan.github.io/jq/download/)
### Firewall configuration
In order for the API node services to work correctly, you must configure any network firewall rules to allow traffic on
the ports discussed in this section. The details of network and firewall configuration are highly specific to your
machine and network, so a detailed example isn't provided.
The following ports must open on the host machine:
Ingress:
- stacks-blockchain (open to `0.0.0.0/0`):
- `20443 TCP`
- `20444 TCP`
Egress:
- `18332`
- `18333`
- `20443-20444`
These egress ports are for syncing [`stacks-blockchain`][] and Bitcoin headers. If they're not open, the sync will fail.
## Step 1: Initial setup
In order to run the testnet node, you must download the Docker images and create a directory structure to hold the
persistent data from the services. Download and configure the Docker images with the following commands:
```sh
docker pull blockstack/stacks-blockchain
```
Create a directory structure for the service data with the following command:
```sh
mkdir -p ./stacks-node/persistent-data/stacks-blockchain/testnet && cd stacks-node
```
## Step 2: Running Stacks blockchain
Start the [`stacks-blockchain`][] container with the following command:
```sh
docker run -d --rm \
--name stacks-blockchain \
-v $(pwd)/persistent-data/stacks-blockchain/testnet:/root/stacks-node/data \
-p 20443:20443 \
-p 20444:20444 \
blockstack/stacks-blockchain \
/bin/stacks-node xenon
```
You can verify that the container [`stacks-blockchain`][] is running with the command:
```sh
docker ps --filter name=stacks-blockchain
```
## Step 3: Verifying the services
:::info
The initial header sync can take several minutes, until this is done the following commands will not work.
:::
To verify the [`stacks-blockchain`][] burn chain header sync progress:
```sh
docker logs stacks-blockchain
```
The output should be similar to the following:
```
INFO [1626290705.886954] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitcoin headers: 1.2% (8000 out of 2034380)
INFO [1626290748.103291] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitcoin headers: 1.4% (10000 out of 2034380)
INFO [1626290776.956535] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitcoin headers: 1.7% (12000 out of 2034380)
```
To verify the [`stacks-blockchain`][] tip height is progressing use the following command:
```sh
curl -sL localhost:20443/v2/info | jq
```
If the instance is running you should receive terminal output similar to the following:
```json
{
"peer_version": 4207599105,
"pox_consensus": "12f7fa85e5099755a00b7eaecded1aa27af61748",
"burn_block_height": 2034380,
"stable_pox_consensus": "5cc4e0403ff6a1a4bd17dae9600c7c13d0b10bdf",
"stable_burn_block_height": 2034373,
"server_version": "stacks-node 2.0.11.2.0-rc1 (develop:7b6d3ee+, release build, linux [x86_64])",
"network_id": 2147483648,
"parent_network_id": 118034699,
"stacks_tip_height": 509,
"stacks_tip": "e0ee952e9891709d196080ca638ad07e6146d4c362e6afe4bb46f42d5fe584e8",
"stacks_tip_consensus_hash": "12f7fa85e5099755a00b7eaecded1aa27af61748",
"genesis_chainstate_hash": "74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b",
"unanchored_tip": "32bc86590f11504f17904ee7f5cb05bcf71a68a35f0bb3bc2d31aca726090842",
"unanchored_seq": 0,
"exit_at_block_height": null
}
```
## Stopping the testnet node
Use the following command to stop the local testnet node:
```sh
docker stop stacks-blockchain
```
## Additional reading
- [Running an API instance with Docker][]
[running a mainnet node with docker]: /get-started/running-mainnet-node
[running an api instance with docker]: /get-started/running-api-node
[`stacks-blockchain`]: https://github.com/blockstack/stacks-blockchain

View File

@@ -0,0 +1,80 @@
---
Title: Upgrade Stacks Blockchain API version
---
# Upgrade Stacks Blockchain API version
Over time, the Stacks Blockchain API may be updated to a newer version, providing you additonal features and benefits not available in previous versions. When a new API version is released, you may want to upgrade the Stacks Blockchain API version to this new, stable version.
The process to upgrade the API version is descibed below.
# Upgrading the API Version
> **_NOTE:_**
>
> If you choose to upgrade the Stacks Blockchain API to a new major version (for example, 3.0.0 to 4.0.0), then the Postgres database from the previous version will not be compatible and the upgrade process will fail to start.
When upgrading the API version, you must use Event Replay. Failure to do so will require wiping both the Stacks Blockchain chainstate data and the API Postgres database, and then re-syncing from scratch.
## Event Replay
The stacks-node is only able to emit events live as they happen. This poses a problem in the scenario where the stacks-blockchain-api needs to be upgraded and its database cannot be migrated to a new schema. One way to handle this upgrade is to wipe the stacks-blockchain-api's database and stacks-node working directory, and re-sync from scratch.
Alternatively, an event-replay feature is available where the API records the HTTP `POST` requests from the stacks-node event emitter, then streams these events back to itself. This essentially simulaties a wipe and full re-sync, although this is much faster.
The Event Replay feature can be used via program args. For example, if there are breaking changes in the API's SQL schema, such as adding a new column which requires events to be re-played, the steps described below can be run.
### Event Replay Instructions
#### V1 BNS Data
This process is optional, but recommended. If you want to retrieve the V1 BNS data, there will be a few extra steps you need to perform.
1. Download BNS data using the command below.
`curl -L https://storage.googleapis.com/blockstack-v1-migration-data/export-data.tar.gz -o /stacks-node/bns/export-data.tar.gz`
2. Extract the data by entering the command below.
`tar -xzvf ./bns/export-data.tar.gz -C /stacks-node/bns/`
3. Each file in `./bns` will have a corresponding sha256 value. To verify the sha256 sum value, run the following script:
```for file in `ls /stacks-node/bns/* | grep -v sha256 | grep -v .tar.gz`; do
if [ $(sha256sum $file | awk {'print $1'}) == $(cat ${file}.sha256 ) ]; then
echo "sha256 Matched $file"
else
echo "sha256 Mismatch $file"
fi
done```
4. Set the data's location as the value of `BNS_IMPORT_DIR` in your `.env` file.
#### Export and Import
To export and/or import event data, follow the steps listed below.
1. Ensure the API process is not running. When stopping the API, let the process exit gracefully so that any in-progress SQL writes can finish.
2. Export event data to disk with the export-events command:
`node ./lib/index.js export-events --file /tmp/stacks-node-events.tsv`
3. Update the API version to the new stacks-blockchain-api version.
4. Perform the event playback using the `import-events` command.
**WARNING**: This action will drop all tables from the configured Postgres database, including any tables not automatically added by the API.
`node ./lib/index.js import-events --file /tmp/stacks-node-events.tsv --wipe-db --force`
This command has two modes of operation, specified by the `--mode` option:
- **archival (default)**: The process will import and ingest all blockchain events that have happened since the first block.
- **pruned**: The import process will ignore some prunable events (mempool, microblocks) until the import block height has reached `chain tip - 256` blocks. This saves a considerable amount of time during import, but sacrifices some historical data. You can use this mode if you are mostly interested in running an API version that prioritizes real-time information.
Alternatively, instead of performing the `export-events` command in step 1, an environmental variable can be set which enables events to be streamed to a file as they are received, while the application is running normally. To enable this feature, set the `STACKS_EXPORT_EVENTS_FILE` environment variable to the file path where events should be appended.
For example:
`STACKS_EXPORT_EVENTS_FILE=/tmp/stacks-node-events.tsv`

View File

@@ -0,0 +1,21 @@
---
Title: How-to use Docker with Stacks Blockchain API
---
# How-to use Docker with Stacks Blockchain API
A self-contained Docker image is provided, which will start a Stacks 2.05 blockchain and API instance.
# Installing Docker
To install Docker so you can use it with a Stacks Blockchain API:
1. Ensure Docker is installed, then run the command:
`docker run -p 3999:3999 hirosystems/stacks-blockchain-api-standalone`
2. Similarly, you can start a a "mocknet" instance, which will run a local node, isolated from the testnet/mainnet by running the following command:
`docker run -p 3999:3999 -e STACKS_NETWORK=mocknet hirosystems/stacks-blockchain-api-standalone`
3. Once the blockchain has synced with network, the API will be available at the following location: http://localhost:3999

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

52
content/overview.md Normal file
View File

@@ -0,0 +1,52 @@
---
Title: Overview
---
# Overview
The Stacks blockchain API allows you to query the Stacks blockchain and interact with smart contracts. It was built to maintain paginated, materialized views of the Stacks Blockchain.
The Stacks Blockchain API is hosted by Hiro. Using it requires you to trust the hosted server, but this API also provides a faster development experience. You may wish to consider running your own API instance to create a fully trustless architecture for your app.
## Architecture
![API architecture!](images/api-architecture.png)
* The `stacks-node` has it's own minimal set of http endpoints referred to as `RPC endpoints`
* The `stacks-blockchain-api` allows clients to access these endpoints by proxying them through to a load-balanced pool of `stacks-nodes`.
* See: https://github.com/blockstack/stacks-blockchain/blob/master/docs/rpc-endpoints.md -- some common ones:
* `POST /v2/transactions` - broadcast a tx.
* `GET /v2/pox` - get current PoX-relevant information.
* `POST /v2/contracts/call-read/<contract>/<function>` - evaluates and returns the result of calling a Clarity function.
* `POST /v2/fees/transaction` - evaluates a given transaction and returns tx fee estimation data.
* `GET /v2/accounts/<address>` - used to get the current `nonce` required for creating transactions.
* The endpoints implemented by `stacks-blockchain-api` provide data that the `stacks-node` can't due to various constraints.
* Typically this is either data that the `stacks-node` doesn't persist, or data that it cannot efficiently serve to many clients.
For example, the `stacks-node` can return the current STX balance of an account, but it can't return a history of account transactions.
* The API also implements the Rosetta spec created by Coinbase -- "an open standard designed to simplify blockchain deployment and interaction."
* See: https://www.rosetta-api.org/
* The API also implements the BNS (Blockchain Naming System) endpoints.
* See https://docs.stacks.co/build-apps/references/bns
* See `/src/api/routes` for the Express.js routes.
* The API creates an "event observer" http server which listens for events from a `stacks-node` "event emitter"
* These events are http POST requests that contain things like blocks, transactions, byproducts of executed transactions.
* Transaction "byproducts" are things like asset transfers, smart-contract log data, execution cost data.
* The API processes and stores these as relational data in postgres.
* See `/src/event-stream` for the "event observer" code.
* All http endpoints and responses are defined in OpenAPI and JSON Schema.
* See `/docs/openapi.yaml`
* These are used to auto generate the docs at https://hirosystems.github.io/stacks-blockchain-api/
* The JSON Schemas are converted into Typescript interfaces, which are used internally by the db controller module to transform SQL query results into the correct object shapes.
* ALSO the OpenAPI + JSONSchemas are used to generate a standalone `@stacks/blockchain-api-client`.
* The easiest/quickest way to develop in this repo is using the vscode debugger. It uses docker-compose to setup a `stacks-node` and postgres instance.
* Alternatively, you can run `npm run dev:integrated` which does the same thing but without a debugger.

View File

@@ -0,0 +1,32 @@
---
Title: Troubleshooting
---
# Troubleshooting
## I need help retrieving the requested information from an API endpoint.
As a first step, examine the HTTP response codes returned by the API call. The following are the classification groups:
- HTTP 2xx - Typically expected behavior ie; the API is responding as expected. Consider caching all or part of the response to reduce retrieval times in the future.
- HTTP 3xx - Redirecting; In this case, the client should be programmed to retry the call with the redirected URL or terminate the execution.
- HTTP 4xx - Client errors; This usually signifies a malformed request (for example - attempting to access a resource that has access restrictions or does not exist)
- HTTP 5xx - Server error; These typically signal an issue with the backend infrastructure.
In all cases, ensure that you log any erroneous debugging responses. Your application may be attempting to utilize deprecated endpoints, which can lead to the failure of the request. You must update these operations to use a different endpoint as soon as possible. To stay updated with deprecation events, subscribe to the [developer newsletter](https://www.hiro.so/updates).
Additionally, [Discord](https://discord.gg/pPwMzMx9k8) and [StackOverflow](https://stackoverflow.com/questions/tagged/stacks-blockchain+or+clarity-lang) are great resources for sharing knowledge and getting your questions addressed through the community.
## I'm hitting rate limits with API Calls
Hiro's Public Stacks API calls [are rate-limited](https://docs.hiro.so/stacks-blockchain-api/feature-guides/rate-limiting) to ensure high availability of the API and prevent abuse by a single or specific group of clients.
While increasing limits may only be feasible to be fair to some users, clients can employ various techniques to adapt to the rate limit. One example is using an [exponential back-off strategy](https://learn.microsoft.com/en-us/azure/architecture/patterns/retry), which repeatedly retries the operation when hitting a rate limit. However, the time between each retry increases exponentially so that over a more extended period, the rate of requests adapts to the rate limit.
Caching API responses can also be handy, as not all information is updated frequently and can be stored locally to reduce API traffic. Depending on the use case, there may be multiple options to achieve this. For example, a client-side cache can be created/refreshed based on a combination of the following:
- Weight - Retain an item longer the more frequently it is accessed.
- Time - Let the cached item expire after a specific time interval - call the API the next time this item is required.
- On-Chain Events - If your application tracks on-chain events, some additional ways to build the cache would be based on block height, successful execution of a function/contract, etc.
Finally, more mature development projects can consider [running their own instances of the API](https://docs.hiro.so/get-started/running-api-node).