Skip to main content
即刻安装 Cobo WaaS Skill,在 Claude Code、Cursor 等 AI 开发环境中使用自然语言集成 WaaS API,显著提升开发效率 🚀
在您通过 Cobo Portal 快速入门指南熟悉全托管钱包的基本操作后,本指南将帮助您使用 WaaS 2.0 API 将全托管钱包(资产钱包)功能无缝集成到您的应用程序中。 通过本指南,您将了解如何:
  1. 创建钱包
  2. 在钱包中生成充币地址
  3. 向钱包存入代币并跟踪交易状态
  4. 从钱包提取代币
  5. 查询钱包余额
本指南在所有代码示例中都使用开发环境。建议您先在开发环境中测试新功能,然后再将其部署到生产环境。

前提条件

  • 按照发送您的第一个 API 请求中的说明设置您的账户,并向 WaaS 2.0 服务发送第一个 API 请求。
  • 如果您选择使用 WaaS SDK 而不是手动编写 API 请求,请参阅相应编程语言的 SDK 指南(PythonJavaGoJavaScript),将 SDK 集成到您的项目中。

1. 创建钱包

要创建资产钱包,请调用 Create wallet,并在请求包体中指定以下属性:
  • wallet_typeCustodial
  • wallet_subtypeAsset
在请求成功完成后,响应中将包含钱包 ID,即您刚刚创建的钱包的唯一标识符。请保存此钱包 ID,因为您将在后续步骤中使用它。
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)
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();
       }
   }
}

2. 生成充币地址

创建钱包后,您现在需要在钱包中生成充币地址来接收代币。要在刚刚创建的资产钱包中生成充币地址,请调用 Create addresses in wallet,并指定以下参数和属性:
  • 路径:
    • wallet_id:您刚刚创建的钱包 ID。
  • 请求包体:
    • chain_id:链 ID。
    • count:指定要创建的地址数量。
在请求成功完成后,响应将包含您刚刚创建的地址。您现在可以将代币充币到这些地址中。
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)
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();
       }
   }
}

3. 处理充币

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

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

Webhook 是 WaaS 服务与您的 App 通信的重要机制。注册 Webhook Endpoint 后,WaaS 服务会在事件发生时将推送消息发送到指定的 URL。 要了解如何设置 Webhook Endpoint 并在 Cobo Portal 上注册,请参阅 Webhook 和 Callback 简介 要跟踪充币状态,您可以订阅以下 Webhook 事件类型:
  • wallets.transaction.created
  • wallets.transaction.updated
  • wallets.transaction.succeeded
  • wallets.transaction.failed
要了解每个事件类型的触发条件和数据结构,请参阅 Webhook 事件类型和数据类型

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

要查询充币交易的状态,请调用 List all transactions,并设置以下查询参数:
  • typesDeposit
  • statusesConfirming,Completed。如果您从外部地址充币,则可以在交易等待所需的确认数量或成功完成时查询交易详细信息。
  • wallet_ids:您在第一步中创建的钱包 ID。
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)
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();
       }
   }
}

4. 提取代币

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

设置 Callback Endpoint

为了增强交易的安全性,强烈建议您设置 Callback Endpoint 来接收和批准提币请求。一旦您使用 WaaS 2.0 API 发起提币,Callback Endpoint 将接收包含交易详细信息的回调消息。只有在您批准提币请求后,交易才会继续进行。 要了解如何设置 Callback Endpoint 并在 Cobo Portal 上注册,请参阅Webhook 和 Callback 简介

提取代币

要从资产钱包中提取代币,请调用 Transfer token,并在请求包体中指定以下属性:
  • request_id:您的请求 ID。
  • source.source_typeAsset
  • source.wallet_id:您刚刚创建的钱包 ID。
  • token_id:您要提取的代币 ID。
  • destination.destination_typeAddress
  • destination.account_output:接收地址和 memo(如有),以及您要提取的金额。
  • category_names:用于识别交易的自定义类别。
  • description:转账的描述。
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)
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();
       }
   }
}
提币请求的响应如下。请记录交易 ID,因为您将在后续步骤中使用它。
{
   "request_id": "<YOUR_REQUEST_ID>",
   "transaction_id": "<THE_GENERATED_TRANSACTION_ID>",
   "status": "Submitted"
}

确认提币

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

监控提币状态

除了 Webhook 事件外,您还可以调用 Get transaction information 来查询交易状态。将路径参数 transaction_id 设置为上一个提币请求响应中返回的交易 ID。
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)
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();
       }
   }
}

5. 查询钱包余额

在成功提取代币后,您可以调用 List token balances by wallet 来查询钱包余额。指定以下路径和查询参数:
  • wallet_id:您在第一步中创建的钱包 ID。
  • token_ids:您可以将其留空以查询所有代币的余额,也可以将其设置为您要查询的特定代币。
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)
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();
        }
    }
}