The @rgbpp-sdk/service
package provides a wrapped class to interact with Bitcoin/RGB++ Assets Service
(BtcAssetsApi). It offers various features for interacting with Bitcoin and RGB++ assets:
- Retrieve Blockchain Information including Bitcoin chain info, blocks, headers, transactions, addresses, and RGB++ assets
- Handle transactions by posting to
/bitcoin/v1/transaction
or/rgbpp/v1/transaction/ckb-tx
- Generate Bitcoin transaction Proof via
/rgbpp/v1/btc-spv/proof
through Bitcoin SPV Service on CKB - Simplify RGB++ assets workflows with RGB++ CKB transaction Queue and cron jobs
- More detailed API documentation can be found on Testnet and Mainnet
Note
Bitcoin/RGB++ Assets Service
is designed to streamline the transaction workflow. Developers have the option to implement its features by themselves without limitation.
# Install via npm:
$ npm i @rgbpp-sdk/service
# Install via yarn:
$ yarn add @rgbpp-sdk/service
# Install via pnpm:
$ pnpm add @rgbpp-sdk/service
You can get a testnet access token through the /token/generate API directly.
The mainnet BtcAssetsApi is currently limited to verified apps only.
When your app development is ready on testnet, and requires a mainnet access token, please email us at f@cell.studio to request a mainnet JWT token.
In the email, please provide the following information about your app:
name
: Your app name, e.g. "rgbpp-app"domain
: Your app domain, e.g. "rgbpp.app" (without protocol prefix and port suffix)
Initialize BtcAssetsApi service with your access token:
import { BtcAssetsApi } from '@rgbpp-sdk/service';
const service = BtcAssetsApi.fromToken('https://your-btc-assets-api.url', 'your_access_token');
You should pass origin
when initializing BtcAssetsApi service in Node.js:
import { BtcAssetsApi } from '@rgbpp-sdk/service';
const service = BtcAssetsApi.fromToken('https://your-btc-assets-api.url', 'your_access_token', 'https://your.app');
The origin
prop is used to verify your token's corresponding domain
.
For example, if your token was generated in the domain of your.app
,
you should pass https://your.app
as the origin
prop.
Otherwise, the service will reject your request.
Note the format difference domain
and origin
:
domain
:your.app
, without protocol (https://
,http://
, etc.)origin
:https://your.app
, with protocolhttps://
Once the initialization is complete, you can query from the service:
// Query the balance of an address
const res = await service.getBalance('tb1qm06rvrq8jyyckzc5v709u7qpthel9j4d9f7nh3');
console.log(res);
// {
// address: 'tb1qm06rvrq8jyyckzc5v709u7qpthel9j4d9f7nh3',
// satoshi: 72921,
// pending_satoshi: 0,
// utxo_count: 5
// }
All available APIs in the BtcAssetsApi section.
You can identify the error by its code
and message
, or by its detailed context
:
import { BtcAssetsApiError, ErrorCodes } from '@rgbpp-sdk/service';
try {
...
} catch (e) {
if (e instanceof BtcAssetsApiError) {
// check error code
console.log(e.code === ErrorCodes.ASSETS_API_UNAUTHORIZED); // true
// print the whole error
console.log(JSON.stringify(e));
/*{
"message": "BtcAssetsAPI unauthorized, please check your token/origin: (401) Authorization token is invalid: The token header is not a valid base64url serialized JSON.",
"code": 2,
"context": {
"request": {
"url": "https://btc-assets-api.url/bitcoin/v1/info"
},
"response": {
"status": 401,
"data": {
"message": "Authorization token is invalid: The token header is not a valid base64url serialized JSON."
}
}
}
}*/
}
}
declare class BtcAssetsApi extends BtcAssetsApiBase implements BtcApis, RgbppApis {
static fromToken(baseUrl: string, token: string, origin?: string): BtcAssetsApi;
}
declare class BtcAssetsApiBase implements BaseApis {}
interface BaseApis {
request<T>(route: string, options?: BaseApiRequestOptions): Promise<T>;
post<T>(route: string, options?: BaseApiRequestOptions): Promise<T>;
generateToken(): Promise<BtcAssetsApiToken>;
init(force?: boolean): Promise<void>;
}
interface BaseApiRequestOptions extends RequestInit {
params?: Record<string, any>;
method?: 'GET' | 'POST';
requireToken?: boolean;
}
interface BtcAssetsApiToken {
token: string;
}
interface BtcApis {
getBtcBlockchainInfo(): Promise<BtcApiBlockchainInfo>;
getBtcBlockByHash(blockHash: string): Promise<BtcApiBlock>;
getBtcBlockHeaderByHash(blockHash: string): Promise<BtcApiBlockHeader>;
getBtcBlockHashByHeight(blockHeight: number): Promise<BtcApiBlockHash>;
getBtcBlockTransactionIdsByHash(blockHash: number): Promise<BtcApiBlockTransactionIds>;
getBtcRecommendedFeeRates(): Promise<BtcApiRecommendedFeeRates>;
getBtcBalance(address: string, params?: BtcApiBalanceParams): Promise<BtcApiBalance>;
getBtcUtxos(address: string, params?: BtcApiUtxoParams): Promise<BtcApiUtxo[]>;
getBtcTransactions(address: string, params?: BtcApiTransactionParams): Promise<BtcApiTransaction[]>;
getBtcTransaction(txId: string): Promise<BtcApiTransaction>;
sendBtcTransaction(txHex: string): Promise<BtcApiSentTransaction>;
}
interface BtcApiBlockchainInfo {
chain: string;
blocks: number;
headers: number;
bestblockhash: number;
difficulty: number;
mediantime: number;
}
interface BtcApiBlock {
id: string;
height: number;
version: number;
timestamp: number;
tx_count: number;
size: number;
weight: number;
merkle_root: string;
previousblockhash: string;
mediantime: number;
nonce: number;
bits: number;
difficulty: number;
}
interface BtcApiBlockHash {
hash: string;
}
interface BtcApiBlockHeader {
header: string;
}
interface BtcApiBlockTransactionIds {
txids: string[];
}
interface BtcApiBalanceParams {
min_satoshi?: number;
no_cache?: boolean;
}
interface BtcApiBalance {
address: string;
satoshi: number;
pending_satoshi: number;
dust_satoshi: number;
utxo_count: number;
}
interface BtcApiUtxoParams {
only_confirmed?: boolean;
min_satoshi?: number;
no_cache?: boolean;
}
interface BtcApiUtxo {
txid: string;
vout: number;
value: number;
status: {
confirmed: boolean;
block_height: number;
block_hash: string;
block_time: number;
};
}
interface BtcApiSentTransaction {
txid: string;
}
export interface BtcApiTransactionParams {
after_txid?: string;
}
interface BtcApiTransaction {
txid: string;
version: number;
locktime: number;
vin: {
txid: string;
vout: number;
prevout: {
scriptpubkey: string;
scriptpubkey_asm: string;
scriptpubkey_type: string;
scriptpubkey_address: string;
value: number;
};
scriptsig: string;
scriptsig_asm: string;
witness: string[];
is_coinbase: boolean;
sequence: number;
}[];
vout: {
scriptpubkey: string;
scriptpubkey_asm: string;
scriptpubkey_type: string;
scriptpubkey_address: string;
value: number;
}[];
weight: number;
size: number;
fee: number;
status: {
confirmed: boolean;
block_height: number;
block_hash: string;
block_time: number;
};
}
interface RgbppApis {
getRgbppPaymasterInfo(): Promise<RgbppApiPaymasterInfo>;
getRgbppTransactionHash(btcTxId: string): Promise<RgbppApiCkbTransactionHash>;
getRgbppTransactionState(btcTxId: string): Promise<RgbppApiTransactionState>;
getRgbppAssetsByBtcTxId(btcTxId: string): Promise<Cell[]>;
getRgbppAssetsByBtcUtxo(btcTxId: string, vout: number): Promise<Cell[]>;
getRgbppAssetsByBtcAddress(btcAddress: string, params?: RgbppApiAssetsByAddressParams): Promise<Cell[]>;
getRgbppSpvProof(btcTxId: string, confirmations: number): Promise<RgbppApiSpvProof>;
sendRgbppCkbTransaction(payload: RgbppApiSendCkbTransactionPayload): Promise<RgbppApiTransactionState>;
retryRgbppCkbTransaction(payload: RgbppApiRetryCkbTransactionPayload): Promise<RgbppApiTransactionRetry>;
}
type RgbppTransactionState = 'completed' | 'failed' | 'delayed' | 'active' | 'waiting';
interface RgbppApiPaymasterInfo {
btc_address: string;
fee: number;
}
interface RgbppApiCkbTransactionHash {
txhash: string;
}
interface RgbppApiTransactionState {
state: RgbppTransactionState;
}
interface RgbppApiAssetsByAddressParams {
type_script?: string;
no_cache?: boolean;
}
interface RgbppApiSpvProof {
proof: string;
spv_client: {
tx_hash: string;
index: string;
};
}
interface RgbppApiSendCkbTransactionPayload {
btc_txid: string;
ckb_virtual_result: {
ckbRawTx: CKBComponents.RawTransaction;
needPaymasterCell: boolean;
sumInputsCapacity: string;
commitment: string;
};
}
interface RgbppApiRetryCkbTransactionPayload {
btc_txid: string;
}
interface RgbppApiTransactionRetry {
success: boolean;
state: RgbppTransactionState;
}