mirror of https://github.com/lukechilds/docs.git
4 changed files with 439 additions and 152 deletions
@ -1,151 +0,0 @@ |
|||
--- |
|||
title: Broadcasting transactions |
|||
description: Learn how to generate and broadcast Stacks 2.0 transactions |
|||
icon: TestnetIcon |
|||
duration: 30 minutes |
|||
experience: beginners |
|||
tags: |
|||
- tutorial |
|||
images: |
|||
large: /images/pages/testnet.svg |
|||
sm: /images/pages/testnet-sm.svg |
|||
--- |
|||
|
|||
## Introduction |
|||
|
|||
This tutorial will walk you through the following steps: |
|||
|
|||
- Generating a private key |
|||
- Generating a token transfer transaction |
|||
- Broadcasting the transaction to the network |
|||
|
|||
## Requirements |
|||
|
|||
You will need [NodeJS](https://nodejs.org/en/download/) `8.12.0` or higher to complete this tutorial. You can verify your installation by opening up your terminal and run the following command: |
|||
|
|||
```bash |
|||
node --version |
|||
``` |
|||
|
|||
## Step 1: Installing libraries |
|||
|
|||
First install the stacks transactions library and a JavaScript [BigNum](https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic) implementation in your project using npm or yarn: |
|||
|
|||
```shell |
|||
|
|||
# using npm |
|||
npm install @blockstack/stacks-transactions bn.js |
|||
|
|||
# using yarn |
|||
yarn add @blockstack/stacks-transactions bn.js |
|||
``` |
|||
|
|||
## Step 2: Generating private key |
|||
|
|||
In order to build and sign transactions, you will need a Stacks private key: |
|||
|
|||
```js |
|||
import { BigNum } from 'bn.js'; |
|||
const { |
|||
makeRandomPrivKey, |
|||
makeSTXTokenTransfer, |
|||
createStacksPrivateKey, |
|||
broadcastTransaction, |
|||
estimateTransfer, |
|||
getNonce, |
|||
StacksMainnet, |
|||
StacksTestnet, |
|||
} = require('@blockstack/stacks-transactions'); |
|||
|
|||
var secretKey = makeRandomPrivKey(); |
|||
``` |
|||
|
|||
The code above imports required methods from the packages we just installed. The method `makeRandomPrivKey()` generates a new, random private Stacks 2.0 key. |
|||
|
|||
Alternatively, in case you already have a private key from an existing Stacks 2.0 wallet, you can also also instantiate the key object from an private key string: |
|||
|
|||
```js |
|||
var key = 'edf9aee84d9b7abc145504dde6726c64f369d37ee34ded868fabd876c26570bc01'; |
|||
var secretKey = createStacksPrivateKey(key); |
|||
``` |
|||
|
|||
## Step 3: Generating token transfer transaction |
|||
|
|||
To generate a token transfer transaction, we will be using the `makeSTXTokenTransfer()` transaction builder function. This method will need a few more pieces of information: |
|||
|
|||
| Parameter | Description | Optional | |
|||
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------- | -------- | |
|||
| `recipientAddress` | The recipient Stacks address in c32check format | | |
|||
| `amount` | The amount of Stacks tokens to send denominated in microstacks | | |
|||
| `feeRate` | The fee that the sender is willing to pay for miners to process the transaction. Denominated in microstacks | Yes | |
|||
| `nonce` | A nonce is an integer that needs to be incremented by 1 for each sequential transaction from the same account. Nonces start at 0 | Yes | |
|||
| `secretKey` | A private key object | Yes | |
|||
| `network` | Specifies whether the transaction is meant for Stacks Mainnet or Testnet | Yes | |
|||
| `memo` | A memo string to attach additional information to the transaction. This data is limited to 33 bytes | Yes | |
|||
|
|||
Here is a sample code generating a new transaction object: |
|||
|
|||
```js |
|||
var recipientAddress = 'SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159'; |
|||
|
|||
// amount of Stacks tokens to send (in microstacks). 1,000,000 microstacks are worth 1 STX token |
|||
var amount = BigNum(1000000); |
|||
|
|||
// skip automatic fee estimation |
|||
var feeRate = BigNum(0); |
|||
|
|||
// skip automatic nonce lookup |
|||
var nonce = BigNum(0); |
|||
|
|||
// override default setting to broadcast to the Testnet network |
|||
var network = new StacksTestnet(); |
|||
|
|||
var memo = 'hello world'; |
|||
|
|||
var txOptions = { |
|||
recipientAddress, |
|||
amount, |
|||
feeRate, |
|||
nonce, |
|||
secretKey, // generated in the previous step |
|||
network, |
|||
memo, |
|||
}; |
|||
var transaction = makeSTXTokenTransfer(txOptions); |
|||
``` |
|||
|
|||
### Estimating fees |
|||
|
|||
If not specified, the transaction builder will automatically estimate the fee. Estimated fee rate is supplied by a Stacks node so network access is required. The fee is calculated based on the estimate fee rate and the size of the transaction in bytes. |
|||
|
|||
Another way to estimate the fee is to use the `estimateTransfer()` function after you have constructed a transaction: |
|||
|
|||
```js |
|||
estimateTransfer(transaction); |
|||
``` |
|||
|
|||
> Note: By setting a fee in the transaction builder function, the automatic fee estimation step will be skipped. |
|||
|
|||
### Handling nonces |
|||
|
|||
If not specified, the transaction builder will automatically lookup the latest nonce for the sender account. Automatic nonce handling also requires network access. The nonce should be tracked locally when creating multiple sequential transactions from the same account. A Stacks node only updates the nonce once a transaction has been mined. |
|||
|
|||
The updated nonce for each account can be retrieved manually using the `getNonce()` function: |
|||
|
|||
```js |
|||
getNonce(senderAddress); |
|||
``` |
|||
|
|||
## Step 4: Broadcasting transaction |
|||
|
|||
Next, we will broadcast the transaction to the Testnetm using the `network` object we created earlier: |
|||
|
|||
```js |
|||
broadcastTransaction(transaction, testnet); |
|||
``` |
|||
|
|||
In case you would like to inspect the raw serialized transaction, you can call the `serialize()` method: |
|||
|
|||
```js |
|||
var serializedTx = transaction.serialize().toString('hex'); |
|||
``` |
@ -0,0 +1,230 @@ |
|||
--- |
|||
title: Managing accounts |
|||
description: Learn how to generate and review Stacks 2.0 accounts |
|||
icon: TestnetIcon |
|||
duration: 15 minutes |
|||
experience: beginners |
|||
tags: |
|||
- tutorial |
|||
images: |
|||
large: /images/pages/testnet.svg |
|||
sm: /images/pages/testnet-sm.svg |
|||
--- |
|||
|
|||
## Introduction |
|||
|
|||
This tutorial will walk you through the following steps: |
|||
|
|||
- Generating an account |
|||
- Reviewing account info |
|||
- Reviewing account history |
|||
- Getting account balances |
|||
|
|||
## Requirements |
|||
|
|||
You will need [NodeJS](https://nodejs.org/en/download/) `8.12.0` or higher to complete this tutorial. You can verify your installation by opening up your terminal and run the following command: |
|||
|
|||
```bash |
|||
node --version |
|||
``` |
|||
|
|||
## Step 1: Installing libraries |
|||
|
|||
First install the stacks transactions library and an API client for the [Stacks 2.0 Blockchain API](/references/stacks-blockchain): |
|||
|
|||
```shell |
|||
npm install --save @blockstack/stacks-transactions@0.6.0 @stacks/blockchain-api-client |
|||
``` |
|||
|
|||
## Step 2: Generating an account |
|||
|
|||
To get started, let's generate a new, random Stacks 2.0 private key: |
|||
|
|||
```js |
|||
const { |
|||
makeRandomPrivKey, |
|||
privateKeyToString, |
|||
getAddressFromPrivateKey, |
|||
TransactionVersion, |
|||
} = require('@blockstack/stacks-transactions'); |
|||
const { AccountsApi, FaucetsApi, Configuration } = require('@stacks/blockchain-api-client'); |
|||
|
|||
const apiConfig = new Configuration({ |
|||
fetchApi: fetch, |
|||
basePath: 'https://stacks-node-api-latest.argon.blockstack.xyz', |
|||
}); |
|||
|
|||
const privateKey = makeRandomPrivKey(); |
|||
``` |
|||
|
|||
> Note: The code above also imports methods required for the next steps, including API configuration for the client library usage. |
|||
|
|||
## Step 3: Reviewing account info |
|||
|
|||
With the private key, you can review account details. First, we need to derive the Stacks address from the private key. Then, we can use the `AccountsApi` class to get the account details: |
|||
|
|||
```js |
|||
const stacksAddress = getAddressFromPrivateKey( |
|||
privateKeyToString(privateKey), |
|||
TransactionVersion.Testnet // remove for Mainnet addresses |
|||
); |
|||
|
|||
... |
|||
|
|||
const accounts = new AccountsApi(apiConfig); |
|||
|
|||
const accountInfo = await accounts.getAccountInfo({ |
|||
principal: stacksAddress |
|||
}); |
|||
|
|||
console.log(accountInfo); |
|||
``` |
|||
|
|||
> Note: A "principal" is any entity that can have a token balance. Find more details in the [Princials guide](/smart-contracts/principals). |
|||
|
|||
The API will respond with a balance, nonce (starting at zero), and respective proofs: |
|||
|
|||
```js |
|||
{ |
|||
balance: '0x00000000000000000000000000000000', |
|||
nonce: 0, |
|||
balance_proof: '', |
|||
nonce_proof: '' |
|||
} |
|||
``` |
|||
|
|||
The `balance` property represents the Stacks token balance, as hex-encoded string of an unsigned 128-bit integer (big-endian). It is not easy to consume the `balance` property in this format. To simplify that, and to obtain all balances for all tokens (Stacks, fungible, and non-fungible), check out [step 5](#step-5-getting-account-balances). |
|||
|
|||
### Disabling proofs |
|||
|
|||
Proofs, provided as hex-encoded strings, can be removed from the responses by setting the `proof` parameter: |
|||
|
|||
```js |
|||
const accountInfo = await accounts.getAccountInfo({ |
|||
principal: stacksAddress, |
|||
proof: 0, |
|||
}); |
|||
``` |
|||
|
|||
## Step 4: Reviewing account history |
|||
|
|||
The following step make requires associated accounts transactions. For simplicity, let's run the faucet for the new account: |
|||
|
|||
```js |
|||
const faucets = new FaucetsApi(apiConfig); |
|||
|
|||
const faucetTx = await faucets.runFaucetStx({ |
|||
address: stacksAddress, |
|||
}); |
|||
|
|||
console.log(faucetTx); |
|||
``` |
|||
|
|||
The API will respond with a new transaction ID and confirmation that the faucet run was successful: |
|||
|
|||
```js |
|||
{ |
|||
success: true, |
|||
txId: '0x5b3d9b47c8f0a3c161868c37d94977b3b0a507558a542fd9499b597bfc799d11', |
|||
txRaw: '80800000000400164247d6f2b425ac5771423ae6c80c754f717...' |
|||
} |
|||
``` |
|||
|
|||
> Note: Wait a few minutes for the transaction to complete. You can review the status using the Explorer, by navigating to the following URL: `https://testnet-explorer.blockstack.org/txid/<txid>`. |
|||
|
|||
Assumping the faucet transaction was successfully processed, you can review the account history. We are expecting at least one transactions to show up in the account history. |
|||
|
|||
```js |
|||
const history = await accounts.getAccountTransactions({ |
|||
principal: stacksAddress, |
|||
}); |
|||
|
|||
console.log(history); |
|||
``` |
|||
|
|||
The API will respond with a paginatable list of transactions associated with the account: |
|||
|
|||
```js |
|||
{ |
|||
limit: 20, |
|||
offset: 0, |
|||
total: 1, |
|||
results: [ |
|||
{ |
|||
tx_id: '0x89ee63c0', |
|||
tx_type: 'token_transfer', |
|||
fee_rate: '180', |
|||
sender_address: 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6', |
|||
sponsored: false, |
|||
post_condition_mode: 'deny', |
|||
tx_status: 'success', |
|||
block_hash: '0x167662a4e', |
|||
block_height: 2951, |
|||
burn_block_time: 1598910912, |
|||
burn_block_time_iso: '2020-08-31T21:55:12.000Z', |
|||
canonical: true, |
|||
tx_index: 1, |
|||
tx_result: {"hex":"0x03","repr":"true"}, |
|||
token_transfer: { |
|||
recipient_address:"STW617CAFYNFQG6G470DNWW4V56XAY7125S3Z6RK", |
|||
amount:"500000", |
|||
memo:"0x466175636574000000" |
|||
}, |
|||
events: [{ ... }] |
|||
} |
|||
] |
|||
} |
|||
``` |
|||
|
|||
Please review the [API reference](https://blockstack.github.io/stacks-blockchain-api/#operation/get_account_transactions) for property definitions and details. |
|||
|
|||
### Handling pagination |
|||
|
|||
To make API responses more compact, lists returned by the API are paginated. For lists, the response body includes: |
|||
|
|||
| Parameter | Description | Default | |
|||
| --------- | ---------------------------------------------------------- | ------- | |
|||
| `limit` | The number of list items returned | 20 | |
|||
| `offset` | The number of elements skipped | 0 | |
|||
| `total` | The number of all available list items | 0 | |
|||
| `results` | Array of list items (length of array equals the set limit) | [] | |
|||
|
|||
In order to paginate throughout the full result set, we can use the `limit` and `offset` request properties. Here is an example where we request transactions 50-100 for an account: |
|||
|
|||
```js |
|||
const history = await accounts.getAccountTransactions({ |
|||
principal: stacksAddress, |
|||
limit: 50, |
|||
offset: 50, |
|||
}); |
|||
``` |
|||
|
|||
## Step 5: Getting account balances |
|||
|
|||
As mentioned above, any Stacks address can have a variety of tokens and associated balances. In order to get balances for all Stacks, fungible, and non-fungible tokens, we can use the `getAccountBalance` method: |
|||
|
|||
```js |
|||
const balances = await accounts.getAccountBalance({ |
|||
principal: stacksAddress, |
|||
}); |
|||
|
|||
console.log(balances); |
|||
``` |
|||
|
|||
The API will respond with the following breakdown of token balances: |
|||
|
|||
```js |
|||
{ |
|||
stx: { |
|||
balance: '500000', |
|||
total_sent: '0', |
|||
total_received: '500000' |
|||
}, |
|||
fungible_tokens: {}, |
|||
non_fungible_tokens: {} |
|||
} |
|||
``` |
|||
|
|||
> Note: The `balance` field does **not** represent full Stacks token, but microstacks. 1,000,000 microstacks are worth 1 Stacks token. |
|||
|
|||
We can see that the current Stacks balance is `500000` microstacks, or `0.5` Stacks token. |
@ -0,0 +1,207 @@ |
|||
--- |
|||
title: Sending tokens |
|||
description: Learn how to generate and broadcast Stacks 2.0 token transfers |
|||
icon: TestnetIcon |
|||
duration: 15 minutes |
|||
experience: beginners |
|||
tags: |
|||
- tutorial |
|||
images: |
|||
large: /images/pages/testnet.svg |
|||
sm: /images/pages/testnet-sm.svg |
|||
--- |
|||
|
|||
## Introduction |
|||
|
|||
This tutorial will walk you through the following steps: |
|||
|
|||
- Specifying a sender key |
|||
- Generating a token transfer transaction |
|||
- Broadcasting the transaction to the network |
|||
- Checking transaction completion |
|||
- Confirming updates account balances (optional) |
|||
|
|||
## Requirements |
|||
|
|||
You will need [NodeJS](https://nodejs.org/en/download/) `8.12.0` or higher to complete this tutorial. You can verify your installation by opening up your terminal and run the following command: |
|||
|
|||
```bash |
|||
node --version |
|||
``` |
|||
|
|||
You should also complete the [Managing accounts tutorial](/stacks-blockchain/managing-accounts). The following steps assume we have access to an exsiting Stacks 2.0 account. |
|||
|
|||
## Step 1: Installing libraries |
|||
|
|||
First install the stacks transactions library, a JavaScript [BigNum](https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic) implementation, and the API client for the [Stacks 2.0 Blockchain API](/references/stacks-blockchain): |
|||
|
|||
```shell |
|||
npm install --save @blockstack/stacks-transactions@0.6.0 bn.js @stacks/blockchain-api-client |
|||
``` |
|||
|
|||
## Step 2: Specifying a sender |
|||
|
|||
In order to build and sign transactions, you will need a Stacks privat key. You can easily generate a new, random Stacks 2.0 sender key (see ["Generating an account" from the previous tutorial](http://localhost:3000/stacks-blockchain/managing-accounts#step-2-generating-an-account)). |
|||
|
|||
For this tutorial, we will use an existing Stacks account and instantiate the key object from a private key string: |
|||
|
|||
```js |
|||
const BN = require('bn.js'); |
|||
const { |
|||
makeSTXTokenTransfer, |
|||
createStacksPrivateKey, |
|||
broadcastTransaction, |
|||
estimateTransfer, |
|||
getNonce, |
|||
StacksTestnet, |
|||
privateKeyToString, |
|||
} = require('@blockstack/stacks-transactions'); |
|||
const { TransactionsApi, Configuration } = require('@stacks/blockchain-api-client'); |
|||
|
|||
const apiConfig = new Configuration({ |
|||
fetchApi: fetch, |
|||
basePath: 'https://stacks-node-api-latest.argon.blockstack.xyz', |
|||
}); |
|||
|
|||
const key = 'edf9aee84d9b7abc145504dde6726c64f369d37ee34ded868fabd876c26570bc01'; |
|||
const senderKey = createStacksPrivateKey(key); |
|||
``` |
|||
|
|||
> Note: The code above also imports methods required for the next steps, including API configuration for the client library usage. |
|||
|
|||
## Step 3: Generating transaction |
|||
|
|||
To generate a token transfer transaction, we will be using the `makeSTXTokenTransfer()` transaction builder function: |
|||
|
|||
```js |
|||
const recipientAddress = 'SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159'; |
|||
|
|||
// amount of Stacks tokens to send (in microstacks). 1,000,000 microstacks are worth 1 STX token |
|||
const amount = new BN(1000000); |
|||
|
|||
// skip automatic fee estimation |
|||
const fee = new BN(0); |
|||
|
|||
// skip automatic nonce lookup |
|||
const nonce = new BN(0); |
|||
|
|||
// override default setting to broadcast to the Testnet network |
|||
const network = new StacksTestnet(); |
|||
|
|||
const memo = 'hello world'; |
|||
|
|||
const txOptions = { |
|||
recipientAddress, |
|||
amount, |
|||
fee, |
|||
nonce, |
|||
senderKey: privateKeyToString(senderKey), |
|||
network, |
|||
memo, |
|||
}; |
|||
|
|||
... |
|||
|
|||
const transaction = await makeSTXTokenTransfer(txOptions); |
|||
``` |
|||
|
|||
The generation method will need a few more pieces of information, as specified in the `txOptions` object: |
|||
|
|||
| Parameter | Description | Optional | |
|||
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------- | -------- | |
|||
| `recipientAddress` | The recipient Stacks address in c32check format | **No** | |
|||
| `amount` | The amount of Stacks tokens to send denominated in microstacks | **No** | |
|||
| `fee` | The fee that the sender is willing to pay for miners to process the transaction. Denominated in microstacks | Yes | |
|||
| `nonce` | A nonce is an integer that needs to be incremented by 1 for each sequential transaction from the same account. Nonces start at 0 | Yes | |
|||
| `senderKey` | A private key object | Yes | |
|||
| `network` | Specifies whether the transaction is meant for Stacks Mainnet or Testnet | Yes | |
|||
| `memo` | A memo string to attach additional information to the transaction. This data is limited to 33 bytes | Yes | |
|||
|
|||
### Estimating fees |
|||
|
|||
If not specified, the transaction builder will automatically estimate the fee. Estimated fee rate is supplied by a Stacks node so network access is required. The fee is calculated based on the estimate fee rate and the size of the transaction in bytes. |
|||
|
|||
Another way to estimate the fee is to use the `estimateTransfer()` function after you have constructed a transaction: |
|||
|
|||
```js |
|||
estimateTransfer(transaction); |
|||
``` |
|||
|
|||
> Note: By setting a fee in the transaction builder function, the automatic fee estimation step will be skipped. |
|||
|
|||
### Handling nonces |
|||
|
|||
If not specified, the transaction builder will automatically lookup the latest nonce for the sender account. Automatic nonce handling also requires network access. The nonce should be tracked locally when creating multiple sequential transactions from the same account. A Stacks node only updates the nonce once a transaction has been mined. |
|||
|
|||
The updated nonce for each account can be retrieved manually using the `getNonce()` function: |
|||
|
|||
```js |
|||
getNonce(senderAddress); |
|||
``` |
|||
|
|||
## Step 4: Broadcasting transaction |
|||
|
|||
Next, we will broadcast the transaction to the Testnet using the `network` object we created earlier: |
|||
|
|||
```js |
|||
const txId = await broadcastTransaction(transaction, testnet); |
|||
``` |
|||
|
|||
As soon as the `broadcastTransaction` is completed, a transaction ID is returned. |
|||
|
|||
### Seralizing transactions |
|||
|
|||
In case you would like to inspect the raw serialized transaction, you can call the `serialize()` method: |
|||
|
|||
```js |
|||
const serializedTx = transaction.serialize().toString('hex'); |
|||
``` |
|||
|
|||
## Step 5: Checking completion |
|||
|
|||
With the transaction ID, we can check the status of the transaction. Every transaction needs to be confirmed by the network and will be `pending` as soon as it is broadcasted. |
|||
|
|||
> Note: A transactions is completed once it is confirmed and the status changes to `success`. Most transactions will be pending for several minutes before confirmed. You should implement polling in your app to refresh the status display. |
|||
|
|||
```js |
|||
const transactions = new TransactionsApi(apiConfig); |
|||
|
|||
const txInfo = await transactions.getTransactionById({ |
|||
txId, |
|||
}); |
|||
|
|||
console.log(txInfo); |
|||
``` |
|||
|
|||
The API will respond with transaction details, including the `tx_status` property: |
|||
|
|||
```js |
|||
{ |
|||
tx_id: '0x5f5318', |
|||
tx_type: 'token_transfer', |
|||
fee_rate: '180', |
|||
sender_address: 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6', |
|||
sponsored: false, |
|||
post_condition_mode: 'deny', |
|||
tx_status: 'success', |
|||
block_hash: '0xe9b93259', |
|||
block_height: 2977, |
|||
burn_block_time: 1598915954, |
|||
burn_block_time_iso: '2020-08-31T23:19:14.000Z', |
|||
canonical: true, |
|||
tx_index: 1, |
|||
tx_result: { hex: '0x03', repr: 'true' }, |
|||
token_transfer: { |
|||
recipient_address: 'ST9SW39M98MZXBGWSDVN228NW1NWENWCF321GWMK', |
|||
amount: '500000', |
|||
memo: '0x4661756' |
|||
}, |
|||
events: [ { event_index: 0, event_type: 'stx_asset', asset: [ ... ] } ] |
|||
} |
|||
``` |
|||
|
|||
For all property formats and details, please review the [API reference](https://blockstack.github.io/stacks-blockchain-api/#operation/get_transaction_by_id). |
|||
|
|||
## Step 6: Confirming balance (optional) |
|||
|
|||
Now that the token transfer is confirmed, we can verify the new account balance on the sender address by [follwing the "Getting account balances" steps from the previous tutorial](/stacks-blockchain/managing-accounts#step-5-getting-account-balances). |
Loading…
Reference in new issue