# Pearl

Source: https://developers.bitgo.com/docs/pearl

## Overview

Pearl is the native asset of the Pearl blockchain. It uses:

- UTXO model
- BIP-340 Schnorr signature algorithm
- BIP-341 script-path spending with a nothing-up-my-sleeve (NUMS) internal key

Pearl blockchain is a taproot-only Layer 1 network, forked from btcd and built by Pearl Research Labs. It secures the chain with Proof-of-Useful-Work (PoUW) consensus, where miners perform matrix multiplication instead of traditional hashcash. Every output is a Pay-to-Taproot (P2TR) output with a NUMS internal key and a taptree of 2-of-2 `OP_CHECKSIG` leaves, which together form a 2-of-3 script-path multisig. Pearl supports only taproot (P2TR) addresses with bech32m encoding, so it has no legacy or SegWit v0 output types.

## Explorer

<a href="https://blockbook.pearlresearch.ai/" target="_blank" rel="noreferrer">
  https://blockbook.pearlresearch.ai/
</a>

Testnet explorer: <a href="https://blockbook.testnet.pearlresearch.ai/" target="_blank" rel="noreferrer">https://blockbook.testnet.pearlresearch.ai/</a>

## Wallet Types

BitGo enables holding pearl in the following wallet types:

|                  | Multisig Cold | Multisig Hot | MPC Cold | MPC Hot |
| ---------------- | ------------- | ------------ | -------- | ------- |
| **Custody**      | ✅            | ❌           | ❌       | ❌      |
| **Self-Custody** | ✅            | ✅           | ❌       | ❌      |

## Ticker Symbols

| Mainnet | Testnet |
| ------- | ------- |
| PEARL   | TPEARL  |

## Faucet

Pearl doesn't have a public faucet to obtain testnet `tpearl` for development and testing.

## Units

Pearl is divisible by 10<sup>-8</sup> and the base unit is a grain:

- 1 pearl = 100,000,000 grain
- 1 grain = 0.00000001 pearl

You can pass balances in string or integer format. However, BitGo recommends using string format to ensure values don't exceed the programmable number limit.

## Tokens

The Pearl blockchain doesn't natively support tokens.

## Fees

Pearl has the following fees:

- Minimum fee rate = 1 grain/vByte (1000 grain/kvByte)
- Default fee rate = 10 grain/vByte

## Dust Threshold

A dust threshold is the minimum amount of Pearl that you can create in a single output. Pearl computes the dust threshold dynamically based on the output type, using a dust relay fee of 3000 grain/kvByte.

## Create Wallet

```shell cURL
export BITGO_EXPRESS_HOST="<YOUR_LOCALHOST>"
export COIN="tpearl"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export LABEL="<DESIRED_WALLET_NAME>"
export PASSPHRASE="<YOUR_BITGO_LOGIN_PASSPHRASE>"
export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"

curl -X POST \
  http://$BITGO_EXPRESS_HOST/api/v2/$COIN/wallet/generate \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "label": "'"$LABEL"'",
    "passphrase": "'"$PASSPHRASE"'",
    "enterprise": "'"$ENTERPRISE_ID"'",
    "disableTransactionNotifications": true,
    "disableKRSEmail": true
}'
```
```js JavaScript
const { BitGo } = require('bitgo');

const accessToken = '<YOUR_ACCESS_TOKEN>';

// Initialize the SDK
const bitgo = new BitGo({
  accessToken: accessToken,
  env: 'test',
});

// Generate hot wallet
async function createHotWalletSimple() {
  const newWallet = await bitgo.coin('tpearl').wallets().generateWallet({
    label: '<DESIRED_WALLET_NAME>',
    passphrase: '<YOUR_BITGO_LOGIN_PASSWORD>',
  });

  // Print wallet details
  console.log(JSON.stringify(newWallet, undefined, 2));
}
```

## Create Address

```shell cURL
export COIN="tpearl"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/address \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{"chain": 30}'
```
```js JavaScript
const { BitGo } = require('bitgo');
const accessToken = '<YOUR_ACCESS_TOKEN>';

// Initialize the SDK
const bitgo = new BitGo({
  accessToken: accessToken,
  env: 'test',
});

const wallet = await bitgo.coin('tpearl').wallets().generateWallet({
  label: '<DESIRED_WALLET_NAME>',
  passphrase: '<YOUR_BITGO_LOGIN_PASSPHRASE>',
});

const address = await wallet.createAddress({ chain: 30 });
console.log(JSON.stringify(address, undefined, 2));
```

> 📘 **Note:** Pearl supports only the taproot address type (`p2tr`). To learn more, see [UTXO Address Types](/docs/utxo-address-types).

## Consolidate Balance

Pearl is a UTXO asset and therefore doesn't require consolidating to the base address in order to use the maximum spendable amount.

## Estimate Fee

```shell cURL
export COIN="tpearl"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"

curl -X GET \
  https://app.bitgo-test.com/api/v2/$COIN/tx/fee \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```
```js JavaScript
const BitGoJS = require('../../../src/index.js');
const bitgo = new BitGoJS.BitGo({ env: 'test' });
const Promise = require('bluebird');
const accessToken = '<YOUR_ACCESS_TOKEN>';
const coin = 'tpearl';

Promise.coroutine(function *() {
  bitgo.authenticateWithAccessToken({ accessToken });
  bitgo.coin(coin).feeEstimate({ numBlocks: 2 }, function callback(err, res) {
     console.dir(res);
  });
})();
```

## Transact

```shell cURL
export BITGO_EXPRESS_HOST="<YOUR_LOCALHOST>"
export COIN="tpearl"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export ADDRESS="<DESTINATION_ADDRESS>"
export AMOUNT="<AMOUNT_IN_BASE_UNITS>"
export WALLET_PASSPHRASE="<YOUR_WALLET_PASSPHRASE>"

curl -X POST \
  http://$BITGO_EXPRESS_HOST/api/v2/$COIN/wallet/$WALLET_ID/sendcoins \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "address": "'"$ADDRESS"'",
    "amount": "'"$AMOUNT"'",
    "walletPassphrase": "'"$WALLET_PASSPHRASE"'",
    "txFormat": "psbt"
}'
```
```shell cURL (send to many)
export BITGO_EXPRESS_HOST="<YOUR_LOCALHOST>"
export COIN="tpearl"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export ADDRESS_1="<DESTINATION_ADDRESS_1>"
export ADDRESS_2="<DESTINATION_ADDRESS_2>"
export AMOUNT_1="<AMOUNT_1_IN_BASE_UNITS>"
export AMOUNT_2="<AMOUNT_2_IN_BASE_UNITS>"
export WALLET_PASSPHRASE="<YOUR_WALLET_PASSPHRASE>"

curl -X POST \
  http://$BITGO_EXPRESS_HOST/api/v2/$COIN/wallet/$WALLET_ID/sendmany \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "recipients": [
    {
      "address": "'"$ADDRESS_1"'",
      "amount": "'"$AMOUNT_1"'"
    },
    {
      "address": "'"$ADDRESS_2"'",
      "amount": "'"$AMOUNT_2"'"
    }
  ],
    "walletPassphrase": "'"$WALLET_PASSPHRASE"'",
    "txFormat": "psbt"
}'
```
```js JavaScript
const tx = await fundedWallet.send({
    address: `<DESTINATION_ADDRESS>`,
    amount: `<AMOUNT>`,
    walletPassphrase: process.env.PASSWORD as string,
  });
```
```js JavaScript (send to many)
let params = {
  recipients: [
    {
      amount: "<AMOUNT_1>",
      address: "<DESTINATION_ADDRESS_1>",
    },
    {
      amount: "<AMOUNT_2>",
      address: "<DESTINATION_ADDRESS_2>",
    },
  ],
  walletPassphrase: "<YOUR_WALLET_PASSPHRASE>",
};
wallet.sendMany(params).then(function (transaction) {
  // Print transaction details
  console.dir(transaction);
});
```

## Stake

Pearl isn't a stakeable asset.
