# 轉移代幣和 NFT

本指南將逐步引導您如何使用 OCAP Client 在帳戶之間轉移可替代代幣（包括原生代幣和自訂代幣）以及非同質化代幣（NFT 或資產）。所有轉移操作的主要方法是 `client.transfer()`。

需要記住的一個關鍵特性是，當一個新帳戶收到第一筆入帳交易時，它會自動在鏈上被建立。這意味著您可以將代幣或資產轉移到一個全新的地址，而無需為接收方進行任何預先設定。


## `transfer` 方法

`client.transfer()` 方法是一個多功能的輔助函式，可以簡化發送資產和代幣的過程。它透過單次呼叫即可建構、簽署並將相應的交易（`transferV2Tx`）發送到區塊鏈。

### 參數

<x-field-group>
  <x-field data-name="to" data-type="string" data-required="true">
    <x-field-desc markdown>接收方的帳戶地址。此地址必須是有效的 DID 地址。</x-field-desc>
  </x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="用於簽署交易的發送方錢包物件。"></x-field>
  <x-field data-name="token" data-type="number" data-default="0">
    <x-field-desc markdown>要轉移的鏈原生代幣數量。客戶端會自動處理轉換為正確的小數位數。</x-field-desc>
  </x-field>
  <x-field data-name="assets" data-type="string[]" data-default="[]" data-desc="一個包含要轉移的資產地址（NFT）的陣列。"></x-field>
  <x-field data-name="tokens" data-type="object[]" data-default="[]">
    <x-field-desc markdown>一個包含要轉移的自訂可替代代幣物件的陣列。</x-field-desc>
    <x-field data-name="address" data-type="string" data-required="true" data-desc="自訂代幣合約的地址。"></x-field>
    <x-field data-name="value" data-type="number" data-required="true" data-desc="要轉移的自訂代幣數量。"></x-field>
  </x-field>
  <x-field data-name="memo" data-type="string" data-required="false" data-desc="可選的訊息或備註，將包含在交易中。"></x-field>
  <x-field data-name="delegator" data-type="string" data-required="false">
    <x-field-desc markdown>如果 `wallet` 是代表另一個帳戶操作，此處應為委託帳戶的地址。更多詳情請參閱 [委託權限](./how-to-guides-delegate-permissions.md) 指南。</x-field-desc>
  </x-field>
</x-field-group>

### 返回值

<x-field data-name="Promise<string>" data-type="Promise">
  <x-field-desc markdown>一個 Promise，在成功提交到區塊鏈後會解析為交易雜湊值。</x-field-desc>
</x-field>


## 逐步範例

### 前提條件

在開始之前，請確保您具備：

1. 一個已初始化並連接到鏈主機（例如 `https://beta.abtnetwork.io`）的 `GraphQLClient`。
2. 一個發送方的錢包物件（`senderWallet`），其中有足夠的代幣來支付轉帳和交易費用。
3. 一個接收方的錢包物件（`recipientWallet`），以獲取其地址。接收方的帳戶尚無需存在於鏈上。

```javascript 基本設定 icon=logos:javascript
import GraphQLClient from '@ocap/client';
import { fromRandom } from '@ocap/wallet';

// 1. 初始化客戶端
const client = new GraphQLClient({ endpoint: 'https://beta.abtnetwork.io/api' });

// 2. 為發送方和接收方建立錢包
// 在實際應用中，發送方的錢包應該是載入的，而不是隨機建立的。
const senderWallet = fromRandom(); // 假設此錢包已有資金
const recipientWallet = fromRandom();

console.log(`Sender Address: ${senderWallet.address}`);
console.log(`Recipient Address: ${recipientWallet.address}`);

// 要為此範例中的發送方錢包儲值，請使用水龍頭：
// https://faucet.abtnetwork.io/
```

### 範例 1：轉移原生代幣

此範例展示如何從發送方發送 10 個原生代幣給接收方。

```javascript 轉移原生代幣 icon=logos:javascript
async function transferNativeTokens() {
  try {
    const hash = await client.transfer({
      to: recipientWallet.address,
      token: 10, // 要發送的原生代幣數量
      wallet: senderWallet,
      memo: 'Sending you 10 native tokens!'
    });
    console.log('Native token transfer successful. Tx Hash:', hash);
  } catch (err) {
    console.error('Error transferring tokens:', err);
  }
}

transferNativeTokens();
```

### 範例 2：轉移 NFT（資產）

要轉移 NFT，您需要其唯一的資產地址。首先，您需要建立或取得一個資產（參見 [管理資產 (NFT)](./how-to-guides-manage-assets.md)）。在此範例中，我們假設 `senderWallet` 已經擁有一個地址為 `zNKj...` 的 NFT。

```javascript 轉移 NFT icon=logos:javascript
async function transferNFT() {
  // 假設這是 senderWallet 所擁有的 NFT 地址
  const nftAddress = 'zNKjL4wTmxQPk5nN2ADDPCd58286b2de3f3e';

  try {
    const hash = await client.transfer({
      to: recipientWallet.address,
      assets: [nftAddress], // 一個資產地址的陣列
      wallet: senderWallet,
      memo: 'Here is the NFT you wanted.'
    });
    console.log('NFT transfer successful. Tx Hash:', hash);
  } catch (err) {
    console.error('Error transferring NFT:', err);
  }
}

transferNFT();
```

### 範例 3：轉移自訂代幣

此範例展示如何轉移自訂可替代代幣。您需要該代幣的合約地址。有關建立自訂代幣的資訊，請參閱 [管理代幣](./how-to-guides-manage-tokens.md) 指南。

```javascript 轉移自訂代幣 icon=logos:javascript
async function transferCustomToken() {
  // 假設這是 senderWallet 所擁有的自訂代幣地址
  const customTokenAddress = 'z37bA4x...'; 

  try {
    const hash = await client.transfer({
      to: recipientWallet.address,
      wallet: senderWallet,
      tokens: [
        { address: customTokenAddress, value: 50 } // 50 個單位的自訂代幣
      ],
      memo: 'Sending 50 custom tokens.'
    });
    console.log('Custom token transfer successful. Tx Hash:', hash);
  } catch (err) {
    console.error('Error transferring custom token:', err);
  }
}

transferCustomToken();
```

### 範例 4：組合轉移

您可以在單一的原子交易中同時發送原生代幣、自訂代幣和多個 NFT。這種方式非常高效。

```javascript 組合轉移 icon=logos:javascript
async function combinedTransfer() {
  // 假設這些是 senderWallet 所擁有的資產和代幣地址
  const nftAddress1 = 'zNKjL4wTmxQPk5nN2ADDPCd58286b2de3f3e';
  const nftAddress2 = 'zNKiabcdeQPk5nN2ADDPCd58286b2defghj';
  const customTokenAddress = 'z37bA4x...'; // 自訂可替代代幣的地址

  try {
    const hash = await client.transfer({
      to: recipientWallet.address,
      wallet: senderWallet,
      token: 5, // 5 個原生代幣
      assets: [nftAddress1, nftAddress2], // 一個包含兩個 NFT 的陣列
      tokens: [
        { address: customTokenAddress, value: 50 } // 50 個單位的自訂代幣
      ],
      memo: 'Sending a mix of tokens and NFTs.'
    });
    console.log('Combined transfer successful. Tx Hash:', hash);
  } catch (err) {
    console.error('Error with combined transfer:', err);
  }
}

combinedTransfer();
```

透過遵循這些範例，您可以輕鬆地在您的應用程式中實現代幣和 NFT 的轉移。有關建立您希望轉移的項目的更多詳細資訊，請參閱相關指南。

### 延伸閱讀

* [如何管理資產 (NFT)](./how-to-guides-manage-assets.md)
* [如何管理代幣](./how-to-guides-manage-tokens.md)
* [高階 API](./api-reference-transaction-helpers.md)
