Use this file to discover all available pages before exploring further.
Try Cobo WaaS Skill in your AI coding assistant (Claude Code, Cursor, etc.). Describe your needs in natural language to auto-generate production-ready SDK code and debug faster 🚀
After you have familiarized yourself with Custodial Wallets through the Cobo Portal quick start guide, this guide will help you seamlessly integrate Custodial Wallet (Asset Wallets) functionality into your application using the WaaS 2.0 API.Following this guide, you’ll learn how to:
Create a wallet
Generate a deposit address within the wallet
Deposit tokens into the wallet and track the transaction status
Withdraw tokens from the wallet
Query wallet balances
This guide uses the development environment in all its code samples. It is recommended that you use the development environment to test your new features first before deploying them to the production environment.
Follow the instructions in Send your first request to set up your account and send your first API request to the WaaS 2.0 service.
If you choose to use a WaaS SDK instead of manually writing the API requests, refer to the SDK guide corresponding to the programming language of your choice (Python, Java, Go, JavaScript) to integrate the SDK into your project.
To create an Asset Wallet, call the Create wallet operation and specify the properties in the request body as follows:
wallet_type: Custodial.
wallet_subtype: Asset.
Upon successful completion of the request, the response will include the wallet ID, which is the unique identifier of the wallet you have just created. Store this wallet ID as you will need it for subsequent steps.
Sample code in Python
import jsonimport cobo_waas2from 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 clientwith 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)
Sample code in Java
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(); } }}
After setting up a wallet, you now need to generate deposit addresses within the wallet to receive tokens. To generate deposit addresses within the Asset Wallet you have just created, call the Create addresses in wallet operation and specify the parameters and properties as follows:
Path:
wallet_id: The ID of the wallet you have just created.
Request body:
chain_id: The ID of the blockchain.
count: Use this parameter to specify the number of addresses you want to create.
Upon successful completion of the request, the response will include the addresses you have just created. You can now proceed to deposit tokens into these addresses.
Sample code in Python
import jsonimport cobo_waas2from 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 clientwith 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)
Sample code in Java
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(); } }}
After depositing tokens to the addresses you have generated, you can track the status of your deposit using one of the following two options. Compared with using API to query the transaction status, webhooks can give you real-time notifications and are thus the recommended option.
Option 1: Use webhooks for real-time notifications
Webhook is an essential mechanism for the WaaS service to communicate with your application. After you register a webhook endpoint on Cobo Portal, the WaaS service sends push messages to the designated URL when an event occurs.To learn how to set up a webhook endpoint and register it on Cobo Portal, refer to Introduction to webhooks and callbacks.To track the status of your deposit, you can subscribe to the following webhook event types:
To query the status of a deposit transaction, call the List all transactions operation and set the query parameters as follows:
types: Deposit.
statuses: Confirming,Completed. If you are depositing from an external address, you will be able to query the transaction details when the transaction is waiting for the required number of confirmations or when it is successfully completed.
wallet_ids: The ID of the wallet you have created in the first step.
Sample code in Python
import jsonimport uuidimport cobo_waas2from 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 clientwith 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)
To enhance the security of your transactions, it is highly recommended that you set up a callback endpoint to receive and approve withdrawal requests. Once you initiate a withdrawal using the WaaS 2.0 API, the callback endpoint will receive a callback message containing the transaction details. The transaction will proceed only if you approve the withdrawal request.To learn how to set up a callback endpoint and register it on Cobo Portal, refer to Introduction to webhooks and callbacks.
To withdraw tokens from the Asset Wallet, call the Transfer token operation and set the properties in the request body as follows:
request_id: Your request ID.
source.source_type: Asset.
source.wallet_id: The ID of the wallet you have just created.
token_id: The ID of the token you want to withdraw.
destination.destination_type: Address.
destination.account_output: The receiving address and memo (if applicable), and the amount you want to withdraw.
category_names: The custom category for you to identify your transactions.
description: The description of the transfer.
Sample code in Python
import jsonimport uuidimport cobo_waas2from 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 clientwith 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)
Sample code in Java
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(); } }}
The response of the withdrawal request is as follows. Record the transaction ID as you will use it in the following steps.
If you have set up a callback endpoint, after you initiate the withdrawal transaction, your callback endpoint will receive a message containing the transaction details. Check if the transaction meets expectations, and respond with a success status code (200 or 201) and a response body of ok to approve the transaction. To learn more about handling a callback message, see Set up a callback or webhook endpoint.
In addition to webhook events, you can also call the Get transaction information operation to query the status of the transaction. Set the path parameter transaction_id to the transaction ID returned in the response of the previous withdrawal request.
Sample code in Python
import jsonimport uuidimport cobo_waas2from 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 clientwith 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)
Sample code in Java
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(); } }}
After successfully withdrawing tokens from your wallet, you can call List token balances by wallet to query the wallet balances. Specify the path and query parameters as follows:
wallet_id: The ID of the wallet you have just created.
token_ids: You can leave it empty to query the balances of all tokens, or set it to the specific token you want to query.
Sample code in Python
import jsonimport cobo_waas2from 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 clientwith 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)
Sample code in Java
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(); } }}