> ## Documentation Index
> Fetch the complete documentation index at: https://docs.li.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# 在后端使用

> 使用 Bigmi 在后端轻松构建 Bitcoin 应用。

开始之前，请安装最新版本的 Bigmi 核心包。

## 安装

```sh theme={"system"}
pnpm add @bigmi/core
```

## 配置

### 客户端配置

客户端是 Bigmi 的核心。以下是配置方法：

```typescript theme={"system"}
import { createClient, bitcoin, blockchair, ankr, fallback } from '@bigmi/core'

const client = createClient({
  chain: bitcoin,
  transport: fallback([
    blockchair(),
    ankr({apiKey: 'YOUR_ANKR_API_KEY'})
  ]),
  // Additional parameters
})
```

#### 参数

| 参数                | 是否必填 | 默认值                          | 说明                                                                              |
| ----------------- | ---- | ---------------------------- | ------------------------------------------------------------------------------- |
| `chain`           | 否    | -                            | 此客户端将在其上执行操作的链/网络。该库导出了 `bitcoin` 和 `signet` 网络，也可以使用 `defineChain` 工具函数创建自定义链。 |
| `transport`       | 是    | -                            | 这是一个通过 HTTP 访问的 JSON-RPC 服务，用于与区块链通信。                                           |
| `account`         | 否    | -                            | 供客户端执行操作的账户或地址。                                                                 |
| `pollingInterval` | 否    | 4,000ms                      | 轮询操作或事件的频率。                                                                     |
| `cacheTime`       | 否    | `pollingInterval` \| 4,000ms | 客户端缓存响应的时长。                                                                     |
| `key`             | 否    | 'base'                       | 客户端的键。                                                                          |
| `name`            | 否    | 'Base Client'                | 客户端的名称。                                                                         |
| `type`            | 否    | 'base'                       | 客户端的类型。                                                                         |
| `rpcSchema`       | 否    | -                            | 客户端的类型化 JSON-RPC schema。                                                        |

### 传输配置

Bigmi 支持通过 HTTP 使用的 JSON-RPC 端点。

Bigmi 还包含封装了 Blockchair、Blockcypher、Ankr 和 Mempool API 的传输，用于区块链读取操作。

这些传输大多可免费使用，但有 API 调用限制。对于生产环境场景，可以使用 `apiKey` 和 `baseUrl` 进行配置。

建议使用封装了多个传输的 fallback 传输，以获得更好的可靠性。

```typescript theme={"system"}
import { createClient, bitcoin, blockchair, ankr, fallback, mempool, http } from '@bigmi/core'

const client = createClient({
  chain: bitcoin,
  transport: fallback([
    blockchair(),
    ankr({apiKey: 'YOUR_ANKR_API_KEY'}),
    mempool(),
    http() // It defaults to the chain's public RPC URL.
  ]),
})
```

#### UTXO-API 传输参数

这些包括基于 API 的传输 `blockchair`、`ankr`、`mempool` 和 `blockcypher`。

<Note>
  由于这些是对 HTTP 传输的封装，它们也可以使用任意 HTTP 传输配置参数进行配置。
</Note>

| 参数        | 是否必填 | 类型       | 默认值 | 说明           |
| --------- | ---- | -------- | --- | ------------ |
| `apiKey`  | 否    | `string` | -   | 服务的 API 密钥。  |
| `baseUrl` | 否    | `string` | -   | API 的基础 URL。 |

#### HTTP 传输配置参数

| 参数                | 是否必填 | 类型                                         | 默认值      | 说明                                                                           |
| ----------------- | ---- | ------------------------------------------ | -------- | ---------------------------------------------------------------------------- |
| `key`             | 否    | `string`                                   | 'http'   | 传输的键。                                                                        |
| `name`            | 否    | `string`                                   | 'HTTP'   | 传输的名称。                                                                       |
| `rank`            | 否    | `boolean` \| `RankOptions`                 | false    | 如果为 `true`，传输将按延迟排序。可提供选项来自定义排序行为。                                           |
| `retryCount`      | 否    | `number`                                   | 3        | 放弃前重试请求的次数。                                                                  |
| `retryDelay`      | 否    | `number`                                   | 150      | 重试之间的延迟（毫秒）。                                                                 |
| `timeout`         | 否    | `number`                                   | 10,000ms | 等待响应的最长时间。                                                                   |
| `raw`             | 否    | `boolean`                                  | false    | 如果为 `true`，JSON-RPC 错误将作为响应的一部分返回，而不是被抛出。                                    |
| `onFetchRequest`  | 否    | `function`                                 | -        | 用于拦截 fetch 请求的回调函数。                                                          |
| `onFetchResponse` | 否    | `function`                                 | -        | 用于拦截 fetch 响应的回调函数。                                                          |
| `fetchOptions`    | 否    | `object`                                   | -        | 传递给请求的 [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) 选项。 |
| `methods`         | 否    | `{include?: method[], exclude?: method[]}` | -        | 在此传输中包含或排除的方法。                                                               |

#### Fallback 传输配置参数

| 参数            | 是否必填 | 类型                         | 默认值        | 说明                                 |
| ------------- | ---- | -------------------------- | ---------- | ---------------------------------- |
| `key`         | 否    | `string`                   | 'fallback' | 传输的键。                              |
| `name`        | 否    | `string`                   | 'Fallback' | 传输的名称。                             |
| `rank`        | 否    | `boolean` \| `RankOptions` | false      | 如果为 `true`，传输将按延迟排序。可提供选项来自定义排序行为。 |
| `retryCount`  | 否    | `number`                   | 3          | 放弃前重试请求的次数。                        |
| `retryDelay`  | 否    | `number`                   | 150        | 在回退到下一个传输之前，重试之间的延迟（毫秒）。           |
| `shouldThrow` | 否    | `function`                 | -          | 当某个传输抛出错误时，此谓词决定是回退到下一个传输还是结束执行。   |

### 链配置

Bigmi 内置了主网和 signet 链定义。

```typescript theme={"system"}
import { createClient, bitcoin, signet, http, mempool, fallback } from '@bigmi/core'

const mainnetClient = createClient({
    chain: bitcoin,
    transport: fallback([
        mempool(),
        http()
    ])
})

const testnetClient = createClient({
    chain: signet,
    transport: fallback([
        mempool({baseUrl: 'https://mempool.space/signet/api'}),
        http()
    ])
})

```

#### 自定义链

可以使用 `defineChain` 工具函数创建自定义链。

<CodeGroup>
  ```typescript testnet4.ts theme={"system"}
  import { defineChain, createClient, ChainId, ankr, mempool, http, fallback } from '@bigmi/core'

  const testnet4 = defineChain({
    id: ChainId.Testnet4,
    name: 'Bitcoin Testnet4',
    nativeCurrency: { name: 'Bitcoin', symbol: 'BTC', decimals: 8 },
    rpcUrls: {
      default: {
        http: ['https://bitcoin-testnet-rpc.publicnode.com'],
      },
    },
    blockExplorers: {
      default: {
        name: 'Mempool',
        url: 'https://mempool.space/testnet4/',
      },
    },
    testnet: true
  })


  const testnet4Client = createClient({
    chain: testnet4,
    transport: fallback([
      ankr({apiKey: 'YOUR_ANKR_API_KEY'}),
      mempool({ baseUrl: 'https://mempool.space/testnet4/api' }),
      http()
    ]),
  })
  ```
</CodeGroup>

## Actions

Bigmi 包含许多称为 action 的函数，可用于执行各种区块链操作。

### 读取区块链数据

<CodeGroup>
  ```typescript main.ts theme={"system"}
  import { getBalance, getTransaction, getBlockCount } from '@bigmi/core'
  import { client } from './client.ts'

  // check address balance
  const address = 'some_address'
  const balance = await getBalance(client, { address })
  console.log('Balance:', balance)

  // get transaction
  const txId = 'some_tx'
  const tx = await getTransaction(client, { txId })
  console.log('Transaction:', tx)

  // get the latest block 
  const blockCount = await getBlockCount(client)
  console.log('Current block:', blockCount)
  ```

  ```typescript client.ts theme={"system"}
  import { createClient, bitcoin, http, fallback, mempool } from '@bigmi/core'

  export const client = createClient({
      chain: bitcoin,
      transport: fallback([
          mempool(),
          http()
      ])
  })
  ```
</CodeGroup>

### 创建并发送 Bitcoin 交易

<CodeGroup>
  ```typescript main.ts theme={"system"}
  import { sendBitcoin } from './sendBitcoin.ts'
  import { client } from './client.ts'

  const privateKey = Buffer.from('0xgf.....', 'hex')
  const fromAddress = 'b1qc....'
  const toAddress = 'b1qer..'
  const amount = 10000 // in sats, equivalent to 0.0001 BTC

  // send bitcoin to another address
  const { txId, confirmed, fee } = await sendBitcoin(client, fromAddress, toAddress, amount, privateKey)
  console.log({
    txId,
    confirmed,
    fee
  })
  ```

  ```typescript client.ts theme={"system"}
  import { createClient, bitcoin, http, fallback, mempool } from '@bigmi/core'

  export const client = createClient({
      chain: bitcoin,
      transport: fallback([
          mempool(),
          http()
      ])
  })
  ```

  ```typescript sendBitcoin.ts theme={"system"}
  import * as bitcoin from 'bitcoinjs-lib';
  import * as ecc from '@bitcoinerlab/secp256k1'
  import { createClient, getBalance, getUTXOs, sendUTXOTransaction, waitForTransaction, estimateFee, type Client } from '@bigmi/core';



  export async function sendBitcoin(
    client: Client,
    fromAddress: string,
    toAddress: string,
    amount: number,
    privateKey: Buffer
  ) {
    try {
      // Check balance
      const balance = await getBalance(client, { address: fromAddress });
      // Add a 1000 sats buffer for transaction fees
      if (balance < amount + 1000) {
        throw new Error('Insufficient balance');
      }
      
      // Get UTXOs
      const utxos = await getUTXOs(client, {
        address: fromAddress,
        // Add a 1000 sats buffer for transaction fees
        minValue: amount + 1000,
      });
      
      if (utxos.length === 0) {
        throw new Error('No UTXOs available');
      }
      
      //init ECC lib
      bitcoin.initEccLib(ecc)

      // Create transaction
      const psbt = new bitcoin.Psbt();
      
      let totalInput = 0;
      for (const utxo of utxos) {
        psbt.addInput({
          hash: utxo.txId,
          index: utxo.vout,
          witnessUtxo: {
            script: Buffer.from(utxo.scriptHex, 'hex'),
            value: utxo.value,
          },
        });
        totalInput += utxo.value;
      }
      
      // Add outputs
      psbt.addOutput({
        address: toAddress,
        value: amount,
      });
      
      // Calculate fee and change
      const fee = await estimateFee(client, utxos.length, 2);
      const change = totalInput - amount - fee;
      
      if (change < 0) {
        throw new Error('Insufficient funds for fee');
      }
      
      if (change > 546) { // Dust threshold
        psbt.addOutput({
          address: fromAddress,
          value: change,
        });
      }
      
      // Sign and finalize
      const keyPair = bitcoin.ECPair.fromPrivateKey(privateKey);
      psbt.signAllInputs(keyPair);
      psbt.finalizeAllInputs();
      
      // Get transaction hex
      const txHex = psbt.extractTransaction().toHex();
      
      // Broadcast with Bigmi
      const txId = await sendUTXOTransaction(client, { hex: txHex });
      
      // Wait for confirmation
      const confirmed = await waitForTransaction(client, {
        txId,
        txHex,
        senderAddress: fromAddress,
        confirmations: 1,
      });
      
      return {
        txId,
        fee,
        confirmed,
      };
      
    } catch (error) {
      console.error('Transaction failed:', error);
      throw error;
    }
  }
  ```
</CodeGroup>
