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

# 集成全托管钱包（资产钱包）

<Tip>
  即刻安装 [Cobo WaaS Skill](/developers/v2_cn/guides/overview/cobo-waas-skill)，在 Claude Code、Cursor 等 AI 开发环境中使用自然语言集成 WaaS API，显著提升开发效率 🚀
</Tip>

在您通过 [Cobo Portal 快速入门指南](https://manuals.cobo.com/cn/portal/quick-start-guide-custodial-wallets)熟悉全托管钱包的基本操作后，本指南将帮助您使用 WaaS 2.0 API 将全托管钱包（资产钱包）功能无缝集成到您的应用程序中。

通过本指南，您将了解如何：

1. 创建钱包
2. 在钱包中生成充币地址
3. 向钱包存入代币并跟踪交易状态
4. 从钱包提取代币
5. 查询钱包余额
6. 自动将资金归集到指定地址

<Note>本指南在所有代码示例中都使用[开发环境](/developers/v2_cn/guides/overview/environments)。建议您先在开发环境中测试新功能，然后再将其部署到生产环境。</Note>

## 前提条件

* 按照[发送您的第一个 API 请求](/developers/v2_cn/guides/get-started/get-started-with-waas)中的说明设置您的账户，并向 WaaS 2.0 服务发送第一个 API 请求。
* 如果您选择使用 WaaS SDK 而不是手动编写 API 请求，请参阅相应编程语言的 SDK 指南（[Python](/developers/v2_cn/developer-tools/quickstart-python)、[Java](/developers/v2_cn/developer-tools/quickstart-java)、[Go](/developers/v2_cn/developer-tools/quickstart-go)、[JavaScript](/developers/v2_cn/developer-tools/quickstart-javascript)），将 SDK 集成到您的项目中。

## 1. 创建钱包

要创建资产钱包，请调用 [Create wallet](/developers/v2/api-references/wallets/create-wallet)，并在请求包体中指定以下属性：

* `wallet_type`：`Custodial`。
* `wallet_subtype`：`Asset`。

在请求成功完成后，响应中将包含钱包 ID，即您刚刚创建的钱包的唯一标识符。请保存此钱包 ID，因为您将在后续步骤中使用它。

<Accordion title="Python 示例代码">
  ```python theme={null}
  import json

  import cobo_waas2
  from cobo_waas2 import (
     WalletType,
     WalletSubtype,
     CreateCustodialWalletParams,
     CreateWalletParams,
  )

  configuration = cobo_waas2.Configuration(
     # Replace `<YOUR_API_SECRET>` with your API secret
     api_private_key="<YOUR_API_SECRET>",
     # Use the development environment
     host="https://api.dev.cobo.com/v2"
  )

  # Enter a context with an instance of the API client
  with cobo_waas2.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     wallet_api_instance = cobo_waas2.WalletsApi(api_client)
     try:
         # Create an Asset Wallet
         api_response = wallet_api_instance.create_wallet(
             CreateWalletParams(
                 actual_instance=CreateCustodialWalletParams(
                     name="Asset Example Wallet Demo(Python)",
                     wallet_type=WalletType.CUSTODIAL,
                     wallet_subtype=WalletSubtype.ASSET,
                 )
             )
         )
         print("The response of WalletsApi->create_wallet:")
         print(json.dumps(api_response.to_dict(), indent=2))

     except Exception as e:
         print("Exception when calling WalletsApi->create_wallet, %s\n", e)
  ```
</Accordion>

<Accordion title="Java 示例代码">
  ```java theme={null}
  import com.cobo.waas2.ApiClient;
  import com.cobo.waas2.ApiException;
  import com.cobo.waas2.Configuration;
  import com.cobo.waas2.Env;
  import com.cobo.waas2.api.WalletsApi;
  import com.cobo.waas2.model.*;

  public class CreateWalletExample {
     public static void main(String[] args) {
         ApiClient defaultClient = Configuration.getDefaultApiClient();
         // Use the development environment
         defaultClient.setEnv(Env.DEV);
         // Replace `<YOUR_API_SECRET>` with your API secret
         defaultClient.setPrivKey("<YOUR_API_SECRET>");
         WalletsApi apiInstance = new WalletsApi();
         try {
             CreateCustodialWalletParams params = new CreateCustodialWalletParams()
                     .name("Asset Example Wallet Demo(Java)")
                     .walletType(WalletType.CUSTODIAL)
                     .walletSubtype(WalletSubtype.ASSET);
             // Create an Asset Wallet
             CreatedWalletInfo result = apiInstance.createWallet(new CreateWalletParams(params));
             System.out.println(result);
         } catch (ApiException e) {
             System.err.println("Exception when calling WalletsApi#createWallet");
             System.err.println("Status code: " + e.getCode());
             System.err.println("Reason: " + e.getResponseBody());
             System.err.println("Response headers: " + e.getResponseHeaders());
             e.printStackTrace();
         }
     }
  }
  ```
</Accordion>

## 2. 生成充币地址

创建钱包后，您现在需要在钱包中生成充币地址来接收代币。要在刚刚创建的资产钱包中生成充币地址，请调用 [Create addresses in wallet](/developers/v2/api-references/wallets/create-addresses-in-wallet)，并指定以下参数和属性：

* 路径：
  * `wallet_id`：您刚刚创建的钱包 ID。
* 请求包体：
  * `chain_id`：链 ID。
  * `count`：指定要创建的地址数量。

在请求成功完成后，响应将包含您刚刚创建的地址。您现在可以将代币充币到这些地址中。

<Accordion title="Python 示例代码">
  ```python theme={null}
  import json

  import cobo_waas2
  from cobo_waas2 import (
     CreateAddressRequest,
     AddressEncoding,
  )

  configuration = cobo_waas2.Configuration(
     # Replace `<YOUR_API_SECRET>` with your API secret
     api_private_key="<YOUR_API_SECRET>",
     # Use the development environment
     host="https://api.dev.cobo.com/v2"
  )

  # Enter a context with an instance of the API client
  with cobo_waas2.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     wallet_api_instance = cobo_waas2.WalletsApi(api_client)
     try:
         # Generate two addresses on the Bitcoin testnet3 (XTN) chain using P2TR encoding
         api_response = wallet_api_instance.create_address(
             wallet_id="<Your Wallet ID>",
             create_address_request=CreateAddressRequest(
                 chain_id="XTN", count=2, encoding=AddressEncoding.ENCODING_P2_TR
             ),
         )
         print("The response of WalletsApi->create_address:")
         for address_info in api_response:
             print(json.dumps(address_info.to_dict(), indent=2))

     except Exception as e:
         print("Exception when calling WalletsApi->create_address, %s\n", e)
  ```
</Accordion>

<Accordion title="Java 示例代码">
  ```java theme={null}
  import com.cobo.waas2.ApiClient;
  import com.cobo.waas2.ApiException;
  import com.cobo.waas2.Configuration;
  import com.cobo.waas2.Env;
  import com.cobo.waas2.api.WalletsApi;
  import com.cobo.waas2.model.AddressEncoding;
  import com.cobo.waas2.model.AddressInfo;
  import com.cobo.waas2.model.CreateAddressRequest;

  import java.util.List;
  import java.util.UUID;

  public class CreateAddressExample {
     public static void main(String[] args) {
         ApiClient defaultClient = Configuration.getDefaultApiClient();
         // Use the development environment
         defaultClient.setEnv(Env.DEV);
         // Replace `<YOUR_API_SECRET>` with your API secret
         defaultClient.setPrivKey("<YOUR_API_SECRET>");
         WalletsApi apiInstance = new WalletsApi();
         try {
             UUID wallet_id = UUID.fromString("<YOUR_WALLET_ID>");
             CreateAddressRequest params = new CreateAddressRequest()
                     .chainId("XTN")
                     .count(2)
                     .encoding(AddressEncoding.BECH32);
             // Generate two addresses on the Bitcoin testnet3 (XTN) chain using P2TR encoding
             List<AddressInfo> result = apiInstance.createAddress(wallet_id, params);
             for (AddressInfo addressInfo : result)
                 System.out.println(addressInfo);
         } catch (ApiException e) {
             System.err.println("Exception when calling WalletsApi#createAddress");
             System.err.println("Status code: " + e.getCode());
             System.err.println("Reason: " + e.getResponseBody());
             System.err.println("Response headers: " + e.getResponseHeaders());
             e.printStackTrace();
         }
     }
  }
  ```
</Accordion>

## 3. 处理充币

在将代币存入生成的地址后，您可以通过以下两种方式跟踪充币状态。我们推荐使用 Webhook，因为它能提供实时通知，相比定期使用 API 查询交易状态更为高效和实时。

### 选项 1：使用 Webhook 进行实时通知

Webhook 是 WaaS 服务与您的 App 通信的重要机制。注册 Webhook Endpoint 后，WaaS 服务会在事件发生时将推送消息发送到指定的 URL。

要了解如何设置 Webhook Endpoint 并在 Cobo Portal 上注册，请参阅 [Webhook 和 Callback 简介](/developers/v2_cn/guides/webhooks-callbacks/introduction)。

要跟踪充币状态，您可以订阅以下 Webhook 事件类型：

* `wallets.transaction.created`
* `wallets.transaction.updated`
* `wallets.transaction.succeeded`
* `wallets.transaction.failed`

要了解每个事件类型的触发条件和数据结构，请参阅 [Webhook 事件类型和数据类型](/developers/v2_cn/guides/webhooks-callbacks/webhook-event-type)。

### 选项 2：通过 API 调用获取交易状态

要查询充币交易的状态，请调用 [List all transactions](/developers/v2/api-references/transactions/list-all-transactions)，并设置以下查询参数：

* `types`：`Deposit`。
* `statuses`：`Confirming,Completed`。如果您从外部地址充币，则可以在交易等待所需的确认数量或成功完成时查询交易详细信息。
* `wallet_ids`：您在第一步中创建的钱包 ID。

<Accordion title="Python 示例代码">
  ```python theme={null}
  import json
  import uuid

  import cobo_waas2
  from cobo_waas2 import (
     CreateAddressRequest,
     AddressEncoding,
     TransferParams,
     TransferSource,
     CustodialTransferSource,
     WalletSubtype,
     TransferDestination, AddressTransferDestination, TransferDestinationType, AddressTransferDestinationAccountOutput,
  )

  configuration = cobo_waas2.Configuration(
     # Replace `<YOUR_API_SECRET>` with your API secret
     api_private_key="<YOUR_API_SECRET>",
     # Use the development environment
     host="https://api.dev.cobo.com/v2"
  )

  # Enter a context with an instance of the API client
  with cobo_waas2.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     transaction_api_instance = cobo_waas2.TransactionsApi(api_client)
     try:
         # List deposit transactions
         api_response = transaction_api_instance.list_transactions(
             types="Deposit",
             statuses="Confirming,Completed",
             wallet_ids="<YOUR_WALLET_ID>"
         )
         print("The response of TransactionsApi->list_transactions:")
         print(json.dumps(api_response.to_dict(), indent=2))

     except Exception as e:
         print("Exception when calling TransactionsApi->list_transactions, %s\n", e)
  ```
</Accordion>

<Accordion title="Java 示例代码">
  ```java theme={null}
  import com.cobo.waas2.ApiClient;
  import com.cobo.waas2.ApiException;
  import com.cobo.waas2.Configuration;
  import com.cobo.waas2.Env;
  import com.cobo.waas2.api.TransactionsApi;
  import com.cobo.waas2.model.ListTransactions200Response;

  import java.util.UUID;

  public class ListTransactionsExample {
     public static void main(String[] args) {
         ApiClient defaultClient = Configuration.getDefaultApiClient();
         // Use the development environment
         defaultClient.setEnv(Env.DEV);
         // Replace `<YOUR_API_SECRET>` with your API secret
         defaultClient.setPrivKey("<YOUR_API_SECRET>");
         TransactionsApi apiInstance = new TransactionsApi();
         try {
             String requestId = null;
             String coboIds = null;
             String transactionIds = null;
             String transactionHashes = "";
             String types = "Deposit";
             String statuses = "Confirming,Completed";
             String walletIds = "<YOUR_WALLET_ID>";
             String chainIds = null;
             String tokenIds = null;
             String assetIds = null;
             UUID vaultId = null;
             UUID projectId = null;
             Long minCreatedTimestamp = null;
             Long maxCreatedTimestamp = null;
             Integer limit = 50;
             String before = null;
             String after = null;

             // List deposit transactions
             ListTransactions200Response result = apiInstance.listTransactions(
                     requestId, coboIds, transactionIds, transactionHashes, types, statuses, walletIds, chainIds,
                     tokenIds, assetIds, vaultId, projectId, minCreatedTimestamp, maxCreatedTimestamp, limit, before, after);
             System.out.println(result);
         } catch (ApiException e) {
             System.err.println("Exception when calling WalletsApi#createAddress");
             System.err.println("Status code: " + e.getCode());
             System.err.println("Reason: " + e.getResponseBody());
             System.err.println("Response headers: " + e.getResponseHeaders());
             e.printStackTrace();
         }
     }
  }
  ```
</Accordion>

## 充币前提条件

在充币之前，请确认相关链已为您的团队启用，且代币已上线并开放充币。仅当代币的 `can_deposit` 属性为 `true` 时，该代币才支持充币。向未启用的代币（`can_deposit` 为 `false`，即当前已暂停充币）充币可能无法被自动检测或入账，因此请在转入资金前确认此属性。

**检查代币是否支持充币**

调用 [List supported tokens](/developers/v2/api-references/wallets/list-supported-tokens)，将查询参数 `token_ids` 设置为您要检查的代币（例如 `ETH_USDT`）。在响应中读取该代币的 `can_deposit` 字段：

* `true`：已开放充币，您可以向该代币充币。
* `false`：当前已暂停充币，请勿转入资金。

如需检查单个代币，也可以调用 [Get token information](/developers/v2/api-references/wallets/get-token-information) 并设置路径参数 `token_id`。这两个操作都支持可选查询参数 `wallet_type`、`wallet_subtype` 和 `chain_ids`，用于缩小查询范围。

**检查已发起充币的状态**

如果您已向当时未启用的代币充币，请勿继续向同一地址转入资金。请改为调用 [List all transactions](/developers/v2/api-references/transactions/list-all-transactions) 并设置以下查询参数，确认该笔转账的当前状态：

* `types`：`Deposit`。
* `token_ids`：您充值的代币，例如 `ETH_USDT`。
* `wallet_ids`：您的钱包 ID。
* `transaction_hash`（可选）：链上交易哈希，用于定位特定转账。

读取每笔返回交易的 `status` 字段，判断该笔充币是否已被记录。调用该操作的示例代码，请参阅上文「选项 2：通过 API 调用获取交易状态」。

## Memo 和 Tag 要求

部分链除了充币地址外还需要提供 Memo 或 Tag，以便将充币正确路由到对应账户，例如 XRP、XLM、EOS、ATOM、TON、IOST、BNB Chain 和 Hedera。向这些链充币时如果未附带所需的 Memo 或 Tag，或填写了错误的 Memo 或 Tag，该笔充币将无法匹配充币地址，不会自动入账。如果需要 Memo 的链上的充币未出现在您的交易列表中，请联系 [help@cobo.com](mailto:help@cobo.com) 获取协助。

**检查链是否需要 Memo 或 Tag**

调用 [List supported chains](/developers/v2/api-references/wallets/list-supported-chains)（或调用 [List enabled chains](/developers/v2/api-references/wallets/list-enabled-chains) 查询已为您的团队启用的链），并读取该链的 `require_memo` 字段：

* `true`：该链的每笔充币都需要 Memo 或 Tag。
* `false`：无需 Memo 或 Tag。

如需检查单条链，请调用 [Get chain information](/developers/v2/api-references/wallets/get-chain-information) 并设置路径参数 `chain_id`。

**获取充币地址的 Memo 或 Tag**

Memo 或 Tag 与充币地址绑定。当您在需要 Memo 的链上生成地址时，地址响应中会包含 `memo` 字段。请从 [Create addresses in wallet](/developers/v2/api-references/wallets/create-addresses-in-wallet) 的响应中获取该字段，或之后通过 [List wallet addresses](/developers/v2/api-references/wallets/list-wallet-addresses) 查询。充币时，请同时使用该响应中的地址及其 `memo` 值，并在每笔转账中附上准确的 Memo 或 Tag。

**确认需要 Memo 的链上的充币**

如需确认向需要 Memo 的链发起的充币是否已入账，请调用 [List all transactions](/developers/v2/api-references/transactions/list-all-transactions)，将 `types` 设置为 `Deposit`，将 `wallet_ids` 设置为您的钱包 ID，然后读取每笔返回交易的 `status` 字段。

## 内部交易和合约触发的交易

充币检测机制会跟踪向您的充币地址发起的标准顶层转账。非顶层的转账——例如由合约调用产生的内部（trace）转账，或由智能合约发出而非直接转入您地址的代币转移——可能无法被自动检测或入账。此情况适用于多条链。

如果您预期会收到此类转账的充币但未到账，请先通过对应链的区块链浏览器确认该交易已在链上完成，然后使用 [List all transactions](/developers/v2/api-references/transactions/list-all-transactions) 查询该交易是否已被 Cobo 记录。如果未查询到记录，请联系 [help@cobo.com](mailto:help@cobo.com) 进一步处理。

## 充币问题排查

### 如果错过了充币的 Webhook 通知，如何重新确认？

如果您的 Endpoint 暂时不可用，可能会错过 Webhook 通知。您无需等待新的通知即可确认充币。请直接使用 [List all transactions](/developers/v2/api-references/transactions/list-all-transactions) 查询当前状态，或使用 [Get transaction information](/developers/v2/api-references/transactions/get-transaction-information) 获取单笔转账。请确保您的 Webhook Endpoint 返回成功状态码，以便后续事件能够可靠送达；请参阅 [Webhook 和 Callback 简介](/developers/v2_cn/guides/webhooks-callbacks/introduction)。

### 代币上线前充币会如何处理？

在代币上线并开放充币之前发起的充币，可能在转账时无法被检测或入账。充币前请按 [充币前提条件](#充币前提条件) 所述确认代币已启用。如需检查此类充币之后是否已被记录，请使用 [List all transactions](/developers/v2/api-references/transactions/list-all-transactions)。如果该笔交易未出现在列表中，系统不会自动找回上线前的充币，请联系 [help@cobo.com](mailto:help@cobo.com) 获取协助。

## 4. 提取代币

现在您的钱包中已经有了代币，让我们来学习如何提取它们。

### 设置 Callback Endpoint

为了增强交易的安全性，强烈建议您设置 Callback Endpoint 来接收和批准提币请求。一旦您使用 WaaS 2.0 API 发起提币，Callback Endpoint 将接收包含交易详细信息的回调消息。只有在您批准提币请求后，交易才会继续进行。

要了解如何设置 Callback Endpoint 并在 Cobo Portal 上注册，请参阅[Webhook 和 Callback 简介](/developers/v2_cn/guides/webhooks-callbacks/introduction)。

### 提取代币

要从资产钱包中提取代币，请调用 [Transfer token](/developers/v2/api-references/transactions/transfer-token)，并在请求包体中指定以下属性：

* `request_id`：您的请求 ID。
* `source.source_type`：`Asset`。
* `source.wallet_id`：您刚刚创建的钱包 ID。
* `token_id`：您要提取的代币 ID。
* `destination.destination_type`：`Address`。
* `destination.account_output`：接收地址和 memo（如有），以及您要提取的金额。
* `category_names`：用于识别交易的自定义类别。
* `description`：转账的描述。

<Accordion title="Python 示例代码">
  ```python theme={null}
  import json
  import uuid

  import cobo_waas2
  from cobo_waas2 import (
     CreateAddressRequest,
     AddressEncoding,
     TransferParams,
     TransferSource,
     CustodialTransferSource,
     WalletSubtype,
     TransferDestination, AddressTransferDestination, TransferDestinationType, AddressTransferDestinationAccountOutput,
  )

  configuration = cobo_waas2.Configuration(
     # Replace `<YOUR_API_SECRET>` with your API secret
     api_private_key="<YOUR_API_SECRET>",
     # Use the development environment
     host="https://api.dev.cobo.com/v2"
  )

  # Enter a context with an instance of the API client
  with cobo_waas2.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     transaction_api_instance = cobo_waas2.TransactionsApi(api_client)
     try:
         # Transfer Bitcoin testnet3(XTN) token from the wallet
         api_response = transaction_api_instance.create_transfer_transaction(
             transfer_params=TransferParams(
                 request_id=str(uuid.uuid4()),
                 source=TransferSource(
                     actual_instance=CustodialTransferSource(
                         source_type=WalletSubtype.ASSET,
                         wallet_id="<YOUR_WALLET ID>",
                     )
                 ),
                 token_id="XTN",
                 destination=TransferDestination(
                     actual_instance=AddressTransferDestination(
                         destination_type=TransferDestinationType.ADDRESS,
                         account_output=AddressTransferDestinationAccountOutput(
                             address="<TARGET_ADDRESS>",
                             amount="<TRANSFER_AMOUNT>"
                         )
                     )
                 ),
                 category_names=["<CATEGORY_NAME>"],
                 description="<DESCRIPTION>",
             )
         )
         print("The response of TransactionsApi->create_transfer_transaction:")
         print(json.dumps(api_response.to_dict(), indent=2))

     except Exception as e:
         print("Exception when calling TransactionsApi->create_transfer_transaction, %s\n", e)
  ```
</Accordion>

<Accordion title="Java 示例代码">
  ```java theme={null}
  import com.cobo.waas2.ApiClient;
  import com.cobo.waas2.ApiException;
  import com.cobo.waas2.Configuration;
  import com.cobo.waas2.Env;
  import com.cobo.waas2.api.TransactionsApi;
  import com.cobo.waas2.model.*;

  import java.util.ArrayList;
  import java.util.List;
  import java.util.UUID;

  public class TransferExample {
     public static void main(String[] args) {
         ApiClient defaultClient = Configuration.getDefaultApiClient();
         // Use the development environment
         defaultClient.setEnv(Env.DEV);
         // Replace `<YOUR_API_SECRET>` with your API secret
         defaultClient.setPrivKey("<YOUR_API_SECRET>");
         TransactionsApi apiInstance = new TransactionsApi();
         try {
             UUID walletId = UUID.fromString("<YOUR_WALLET_ID>");

             TransferParams params = new TransferParams();
             params.setRequestId("Demo" + UUID.randomUUID());

             CustodialTransferSource custodialTransferSource = new CustodialTransferSource().sourceType(WalletSubtype.ASSET).walletId(walletId
  );
             params.setSource(new TransferSource(custodialTransferSource));

             params.setTokenId("XTN");
             AddressTransferDestination addressTransferDestination = new AddressTransferDestination()
                     .destinationType(TransferDestinationType.ADDRESS)
                     .accountOutput(new AddressTransferDestinationAccountOutput()
                             .address("<TARGET_ADDRESS>")
                             .amount("<TRANSFER_AMOUNT>"));
             params.setDestination(new TransferDestination(addressTransferDestination));

             List<String> categoryNames = new ArrayList<>();
             categoryNames.add("<CATEGORY_NAME>");
             params.categoryNames(categoryNames).description("<DESCRIPTION>");

             // Transfer Bitcoin testnet3(XTN) token from the wallet
             CreateTransferTransaction201Response result = apiInstance.createTransferTransaction(params);
             System.out.println(result);
         } catch (ApiException e) {
             System.err.println("Exception when calling TransactionsApi#createTransferTransaction");
             System.err.println("Status code: " + e.getCode());
             System.err.println("Reason: " + e.getResponseBody());
             System.err.println("Response headers: " + e.getResponseHeaders());
             e.printStackTrace();
         }
     }
  }
  ```
</Accordion>

提币请求的响应如下。请记录交易 ID，因为您将在后续步骤中使用它。

```json theme={null}
{
   "request_id": "<YOUR_REQUEST_ID>",
   "transaction_id": "<THE_GENERATED_TRANSACTION_ID>",
   "status": "Submitted"
}
```

### 确认提币

如果您已经设置了 Callback Endpoint，则在发起提币交易后，您的 Callback Endpoint 将接收包含交易详细信息的消息。检查交易是否符合预期，然后使用成功状态码（200 或 201）和响应包体 `ok` 来批准交易。要了解如何处理回调消息，请参阅[设置 Callback 或 Webhook 端点](/developers/v2_cn/guides/webhooks-callbacks/set-up-endpoint)。

### 监控提币状态

除了 Webhook 事件外，您还可以调用 [Get transaction information](/developers/v2/api-references/transactions/get-transaction-information) 来查询交易状态。将路径参数 `transaction_id` 设置为上一个提币请求响应中返回的交易 ID。

<Accordion title="Python 示例代码">
  ```python theme={null}
  import json
  import uuid

  import cobo_waas2
  from cobo_waas2 import (
     CreateAddressRequest,
     AddressEncoding,
     TransferParams,
     TransferSource,
     CustodialTransferSource,
     WalletSubtype,
     TransferDestination, AddressTransferDestination, TransferDestinationType, AddressTransferDestinationAccountOutput,
  )

  configuration = cobo_waas2.Configuration(
     # Replace `<YOUR_API_SECRET>` with your API secret
     api_private_key="<YOUR_API_SECRET>",
     # Use the development environment
     host="https://api.dev.cobo.com/v2"
  )

  # Enter a context with an instance of the API client
  with cobo_waas2.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     transaction_api_instance = cobo_waas2.TransactionsApi(api_client)
     try:
         # Get transaction by ID
         api_response = transaction_api_instance.get_transaction_by_id(
             transaction_id="<YOUR_TRANSACTION_ID>"
         )
         print("The response of TransactionsApi->get_transaction_by_id:")
         print(json.dumps(api_response.to_dict(), indent=2))

     except Exception as e:
         print("Exception when calling TransactionsApi->get_transaction_by_id, %s\n", e)
  ```
</Accordion>

<Accordion title="Java 示例代码">
  ```java theme={null}
  import com.cobo.waas2.ApiClient;
  import com.cobo.waas2.ApiException;
  import com.cobo.waas2.Configuration;
  import com.cobo.waas2.Env;
  import com.cobo.waas2.api.TransactionsApi;
  import com.cobo.waas2.model.TransactionDetail;

  import java.util.UUID;

  public class GetTransactionExample {
     public static void main(String[] args) {
         ApiClient defaultClient = Configuration.getDefaultApiClient();
         // Use the development environment
         defaultClient.setEnv(Env.DEV);
         // Replace `<YOUR_API_SECRET>` with your API secret
         defaultClient.setPrivKey("<YOUR_API_SECRET>");
         TransactionsApi apiInstance = new TransactionsApi();
         try {
             UUID transactionId = UUID.fromString("<YOUR_TRANSACTION_ID>");
             
             // Get transaction by ID
             TransactionDetail result = apiInstance.getTransactionById(transactionId);
             System.out.println(result);
         } catch (ApiException e) {
             System.err.println("Exception when calling TransactionsApi#getTransactionById");
             System.err.println("Status code: " + e.getCode());
             System.err.println("Reason: " + e.getResponseBody());
             System.err.println("Response headers: " + e.getResponseHeaders());
             e.printStackTrace();
         }
     }
  }
  ```
</Accordion>

## 5. 查询钱包余额

在成功提取代币后，您可以调用 [List token balances by wallet](/developers/v2/api-references/wallets/list-token-balances-by-wallet) 来查询钱包余额。指定以下路径和查询参数：

* `wallet_id`：您在第一步中创建的钱包 ID。
* `token_ids`：您可以将其留空以查询所有代币的余额，也可以将其设置为您要查询的特定代币。

<Accordion title="Python 示例代码">
  ```python theme={null}
  import json

  import cobo_waas2
  from cobo_waas2 import (
     WalletType,
     WalletSubtype,
  )

  configuration = cobo_waas2.Configuration(
     # Replace `<YOUR_API_SECRET>` with your API secret
     api_private_key="<YOUR_API_SECRET>",
     # Use the development environment
     host="https://api.dev.cobo.com/v2"
  )

  # Enter a context with an instance of the API client
  with cobo_waas2.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     wallet_api_instance = cobo_waas2.WalletsApi(api_client)
     try:
         # Query token balances
         api_response = wallet_api_instance.list_token_balances_for_wallet(
             wallet_id="<YOUR_WALLET_ID>",
         )
         print(f"The response of WalletsApi->list_token_balances_for_wallet:")
         print(json.dumps(api_response.to_dict(), indent=2))

     except Exception as e:
         print("Exception when calling WalletsApi->list_token_balances_for_wallet, %s\n", e)
  ```
</Accordion>

<Accordion title="Java 示例代码">
  ```java theme={null}
  import com.cobo.waas2.ApiClient;
  import com.cobo.waas2.ApiException;
  import com.cobo.waas2.Configuration;
  import com.cobo.waas2.Env;
  import com.cobo.waas2.api.WalletsApi;
  import com.cobo.waas2.model.ListTokenBalancesForAddress200Response;

  import java.util.UUID;

  public class ListTokenBalancesExample {
      public static void main(String[] args) {
          ApiClient defaultClient = Configuration.getDefaultApiClient();
          // Use the development environment
          defaultClient.setEnv(Env.DEV);
          // Replace `<YOUR_API_SECRET>` with your API secret
          defaultClient.setPrivKey("<YOUR_API_SECRET>");
          WalletsApi apiInstance = new WalletsApi();
          try {
              UUID wallet_id = UUID.fromString("<YOUR_WALLET_ID>");
              String tokenIds = null;
              Integer limit = 50;
              String before = null;
              String after = null;
              // Query token balances
              ListTokenBalancesForAddress200Response result = apiInstance.listTokenBalancesForWallet(wallet_id, tokenIds, limit, before, after);
              System.out.println(result);
          } catch (ApiException e) {
              System.err.println("Exception when calling WalletsApi#listTokenBalancesForWallet");
              System.err.println("Status code: " + e.getCode());
              System.err.println("Reason: " + e.getResponseBody());
              System.err.println("Response headers: " + e.getResponseHeaders());
              e.printStackTrace();
          }
      }
  }
  ```
</Accordion>

## 6. 自动归集资金（auto-sweep）

自动归集（auto-sweep）会自动将充币地址中的代币归集到指定的归集目标地址，您无需手动从每个充币地址转出资金。要创建自动归集任务，请调用 [Create auto-sweep task](/developers/v2/api-references/autosweep/create-auto-sweep-task)，并指定以下参数：

* `wallet_id`：您创建的钱包 ID。
* `token_id`：要归集的代币 ID。
* `min_balance_threshold`：（可选）地址被归集所需的最低代币余额。余额低于此值的地址将被跳过，可用于过滤粉尘（dust）。系统不提供按地址设置的黑名单；请使用 `min_balance_threshold` 控制最低归集金额。

<Note>
  归集会将代币从充币地址转出，因此需要链上原生代币支付 gas 费。请确保源充币地址中有足够的原生代币，或已配置 Fee Station 或自动加油（Auto Fueling）来提供 gas。仅达到充币阈值并不会完成归集：如果没有可用的 gas，归集交易将无法广播。当归集无法进行时，原因会显示在任务详情返回的 `failed_reasons` 数组中。
</Note>

### 获取归集交易

Create auto-sweep task 会立即返回 `task_id`。此时任务 `status` 为 `Submitted`，`transaction_ids` 数组为空。这是预期行为，并不表示失败。

当任务触发一个或多个归集交易后，其状态会变为 `TransactionCreated`，此时 `transaction_ids` 会被填充。要获取交易 ID，请使用 `task_id` 轮询 [Get auto-sweep task details](/developers/v2/api-references/autosweep/get-auto-sweep-task-details)，直到 `status` 变为 `TransactionCreated`。

### 时间与生命周期

自动归集基于轮询机制，并非即时执行。归集会在满足触发条件后不久发起，因此充币与归集交易之间存在短暂延迟属于正常现象。无法继续的任务不会一直处于等待状态：长时间缺少 gas 或未完成签名的任务会在超时后自动取消，相关资金会保留在源地址中，您可以稍后重新归集。

<Info>对于 EVM 兼容链（如 Ethereum 和 BNB Smart Chain），所有 EVM 链共用同一个地址。因此，当您使用 [List sweep-to addresses](/developers/v2/api-references/autosweep/list-sweep-to-addresses) 列出归集目标地址时，所有 EVM 兼容链只会返回一个地址条目（显示在 Ethereum 下）。请勿期望每条 EVM 链都有单独的地址条目。</Info>
