Saltearse al contenido

Guía de Integración de Exchange

Esto describe cómo integrar Aptos y los activos de Aptos en un exchange. Proporciona información genérica para rastrear balances, transferir activos y probar la integración.

Este documento te guiará a través de las siguientes tareas para integrarte con Aptos:

  • Infraestructura
  • Estándares de direcciones
  • Estándares de activos
  • Recuperar balances
  • Rastrear cambios de balance
  • Transferir activos
  • Probar la integración

Se sugiere que ejecutes tu propio full node para interactuar con la blockchain de Aptos. Esto te permitirá consultar la blockchain para obtener el estado más reciente y enviar transacciones. También puedes usar el Indexer para consultar datos on-chain de manera eficiente.

Una sola dirección puede ser representada de tres maneras. Recomendamos que muestres todos los ceros iniciales, y el 0x. Aquí hay un ejemplo de las tres representaciones para la dirección de marco 0x1:

  • 0x00000000000000000000000000000001 - Una representación completa de 32 bytes en hex con un 0x inicial. Esto es preferible.
  • 0x1 - La representación corta de la dirección con un 0x inicial. Esto se mantiene por compatibilidad, pero es preferible con todos los ceros iniciales.
  • 00000000000000000000000000000001 - Una representación completa de 32 bytes en hex sin un 0x inicial. Esto se mantiene por compatibilidad, pero es preferible con un 0x inicial.

Para los ejemplos de SDKs, esto se manejará automáticamente, y sugerimos que uses los SDKs directamente para manejarlo por ti.

import { AccountAddress } from "@aptos-labs/ts-sdk";
const address = AccountAddress.from("0x1");
address.toStringLong(); // 0x00000000000000000000000000000001

Además, hay un Servicio de Nombres de Aptos (ANS) para nombres .apt amigables. Para más información sobre direcciones y Nombres de Aptos, consulta nuestra página sobre Cuentas.

Las cuentas deben existir antes de enviar una transacción a la blockchain. Esto se hace creando un recurso de cuenta, que puede ser creado simplemente llamando 0x1::aptos_account::transfer con una cantidad de cero a la cuenta que quieres crear. Opcionalmente, 0x1::aptos_account::create_account puede ser usado para crear una cuenta con un saldo de cero.

import { Aptos, Ed25519Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
const aptos = new Aptos();
const account = new Ed25519Account({privateKey: new Ed25519PrivateKey("private key")})
const transaction = await aptos.transferCoinTransaction({sender: account.accountAddress, recipient: "receiver address", amount: 100000000})
const pendingTransaction = await aptos.transaction.signAndSubmitTransaction({signer: account, transaction})
const committedTransaction = await aptos.waitForTransaction({transactionHash: pendingTransaction.hash});

Aptos proporciona dos estándares para tokens fungibles, similares a los tokens ERC-20 en Ethereum:

Además, hay un período de migración para activos de Coin a estándares de Activo Funciable. Llamaremos a esto monedas migradas. Las monedas migradas pueden tener dos formas, pero cualquiera puede ser utilizado indistintamente con estándares de Coin. Esto es importante tener en cuenta al consultar balances, para usar funciones de moneda y no funciones de activo fungible. El estándar FA solo puede lidiar con la forma FA.

Un coin tiene un contrato asociado que contiene la estructura on-chain que representa el coin. El coin es representado como un nombre de struct e.g. 0x1::aptos_coin::AptosCoin para APT.

Todos los coins se almacenan en un recurso de cuenta llamado 0x1::coin::CoinStore<CoinType>. Los coins deben ser registrados antes de usar el CoinStore, pero si se usan las funciones apropiadas e.g. 0x1::aptos_account::transfer o 0x1::aptos_account::transfer_coins<CoinType>, esto se hará automáticamente.

Los coins pueden ser migrados a un activo fungible. Para apoyar un activo migrado, continúe llamando a las funciones de moneda tal como se mencionará más adelante.

Más información en: Estándar de Coin

Un activo fungible tiene una dirección de metadatos asociada que contiene los metadatos para el activo fungible. Esto se llama a menudo la dirección de metadatos de fa. El activo es representado como una dirección e.g. 0xA para APT.

Todos los activos fungibles se almacenan en un objeto, que se llama un store de activo fungible.

Para exchanges, el store más importante es primary_fungible_store, que es el store por defecto para activos fungibles. Esto está directamente conectado a un propietario. A partir de este punto en esta guía, solo hablaremos sobre el soporte de primary_fungible_store para activos fungibles.

Más información en: Estándar de Activo Funciable

La recuperación de balances actuales para activos es diferente para cada estándar. La integración se considera completa cuando puede manejar ambos.

Los balances siempre se devuelven en sus subunidades. Por ejemplo, APT se devuelve en octas (1e-8 APT). Entonces, cuando una API devuelve un balance de 100000000, esto es 1 APT. Si devuelve 100, esto es 0.000001 APT.

Para recuperar el balance de un coin, o un coin que fue migrada a un activo fungible, puedes usar la función de vista 0x1::coin::balance<CoinType>(dirección de cuenta). Esto combinará los balances de coin y coin migrados a activo fungible.

import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
const config = new AptosConfig({ network: Network.DEVNET });
const aptos = new Aptos(config);
const coinType = "0x1::aptos_coin::AptosCoin";
const account = "0x00000000000000000000000000000001";
const [balanceStr] = await aptos.view<[string]>({
payload: {
function: "0x1::coin::balance",
typeArguments: [coinType],
functionArguments: [account]
}
});
const balance = parseInt(balanceStr, 10);

Una versión de ledger específica (altura de transacción) puede ser proporcionada para obtener el balance en ese punto en el tiempo. El siguiente ejemplo muestra para la versión de ledger 1,000,000.

import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
const config = new AptosConfig({ network: Network.DEVNET });
const aptos = new Aptos(config);
const coinType = "0x1::aptos_coin::AptosCoin";
const account = "0x00000000000000000000000000000001";
const [balanceStr] = await aptos.view<[string]>({
payload: {
function: "0x1::coin::balance",
typeArguments: [coinType],
functionArguments: [account],
options: {
ledgerVersion: 1_000_000
}
}
});
const balance = parseInt(balanceStr, 10);

Para recuperar el balance de un activo fungible, puedes usar la función de vista 0x1::primary_fungible_store::balance<0x1::object::ObjectCore>(dirección de cuenta, dirección de metadatos de activo fungible). Nota, que esto no incluirá el balance de monedas si es una moneda migrada.

import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
const config = new AptosConfig({ network: Network.DEVNET });
const aptos = new Aptos(config);
const faMetadataAddress = "0xA";
const account = "0x00000000000000000000000000000001";
const [balanceStr] = await aptos.view<[string]>({
payload: {
function: "0x1::primary_fungible_store::balance",
typeArguments: ["0x1::object::ObjectCore"],
functionArguments: [account, faMetadataAddress]
}
});
const balance = parseInt(balanceStr, 10);

Una versión de ledger específica (altura de transacción) puede ser proporcionada para obtener el balance en ese punto en el tiempo. El siguiente ejemplo muestra para la versión de ledger 1,000,000.

import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
const config = new AptosConfig({ network: Network.DEVNET });
const aptos = new Aptos(config);
const faMetadataAddress = "0xA";
const account = "0x00000000000000000000000000000001";
const [balanceStr] = await aptos.view<[string]>({
payload: {
function: "0x1::primary_fungible_store::balance",
typeArguments: ["0x1::object::ObjectCore"],
functionArguments: [account, faMetadataAddress]
},
options: {
ledgerVersion: 1_000_000
}
});
const balance = parseInt(balanceStr, 10);

Además de los SDKs, también puedes usar directamente el endpoint de balance de la API del nodo de aptos para obtener el balance de una moneda migrada o activo fungible.

Los cambios de balance pueden ser consultados de dos maneras:

  1. Observando eventos que cambian el balance para cada transacción.
  2. Consultando el indexador para eventos de balance de cambio indexados.

En el pasado, podía usar el endpoint events para una cuenta para obtener las transacciones que cambiaron el balance. Esto todavía es posible, pero estará obsoleto en el futuro, y no se recomienda para nuevas integraciones.

Los balances de coin se rastrean como dos elementos, cambios en el conjunto de escritura, y eventos. Los cambios en el conjunto de escritura son el estado final del balance de coin, y los eventos son los eventos que se emiten cuando un coin se retira o deposita.

Aquí hay un ejemplo de una transferencia de coin. La transferencia de coin puede ser rastreada como una transacción individual aquí desde la API REST.

Lo desglosaremos en varios pasos:

  1. Los detalles generales de la transacción nos dicen información sobre la transacción. Lo más importante aquí es la versión de la transacción es 1747361321. Esto nos da el orden total de todas las transacciones en la blockchain. Piensa en ella como la altura del bloque, pero para las transacciones.
Detalles de la transacción
{
"version": "1747361321",
"hash": "0x7c56ad56c7d02bb11887e535b9f1b221626d5b0d4cb5a1ffbadc358c1db515ea",
"state_change_hash": "0xc901b5e9e0965201e8205977720d7dea8a3709ee0d818fd5ec752cac13eaf18a",
"event_root_hash": "0x0077cb7df9db9ee7194c489db177fe9a325bcf3f1309ea99ed934085e5592041",
"state_checkpoint_hash": null,
"gas_used": "999",
"success": true,
"vm_status": "Executed successfully",
"accumulator_root_hash": "0xb531e918441ff0a37b49856e0f1b80c329146461582287cf9788964d25e31a68",
}
  1. Los changes de Write set son el estado final de la transacción. Muestra todos los recursos que fueron modificados por la transacción, y cuál era su estado final.

En este caso, solo nos importan los cambios en el store de coin.

Cambios de Coin Store
"changes": [
{
"address": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"state_key_hash": "0xb2bfa7198457291a0e582b912be2bf8577feff08e352c9f16935a55ebd202dcc",
"data": {
"type": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>",
"data": {
"coin": {
"value": "903837250"
},
"deposit_events": {
"counter": "10",
"guid": {
"id": {
"addr": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"creation_num": "2"
}
}
},
"frozen": false,
"withdraw_events": {
"counter": "52485",
"guid": {
"id": {
"addr": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"creation_num": "3"
}
}
}
}
},
"type": "write_resource"
},
{
"address": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"state_key_hash": "0xa45b7cfe18cc0ef1d6588f0f548a6a6a260d5e6bbab174507ed40cd21b7bd082",
"data": {
"type": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>",
"data": {
"coin": {
"value": "10"
},
"deposit_events": {
"counter": "1",
"guid": {
"id": {
"addr": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"creation_num": "2"
}
}
},
"frozen": false,
"withdraw_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"creation_num": "3"
}
}
}
}
},
"type": "write_resource"
}],
  1. Los eventos son los eventos que fueron emitidos por la transacción. En este caso, solo nos importan los eventos 0x1::coin::Withdraw y 0x1::coin::Deposit.

El evento de retiro de coin se emite cuando se retiran monedas de una cuenta. El balance de la cuenta disminuirá por esa cantidad en el campo data.amount. Para determinar el activo coincidente, debe coincidir el guid en los withdraw_events con el guid en la sección changes para un CoinStore. Pero si el CoinStore no se encuentra en los changes, significa que se eliminó, y un CoinStoreDeleteEvent debe estar presente en su lugar. Luego, puede coincidir el guid con deleted_withdraw_event_handle_creation_number y event_handle_creation_address.

Evento de retiro de Coin
{
"events": [
{
"guid": {
"creation_number": "3",
"account_address": "0xf8e25f6c8ce40a15107fb4b4d288ca03dd434d057392f2ccb5fde505a300a0bf"
},
"sequence_number": "0",
"type": "0x1::coin::WithdrawEvent",
"data": {
"amount": "100000"
}
},
]
}
Evento de eliminación de Coin Store
{
"events": [
{
"guid": {
"creation_number": "0",
"account_address": "0x0"
},
"sequence_number": "0",
"type": "0x1::coin::CoinStoreDeletion",
"data": {
"coin_type": "0x1::aptos_coin::AptosCoin",
"deleted_deposit_event_handle_creation_number": "2",
"deleted_withdraw_event_handle_creation_number": "3",
"event_handle_creation_address": "0xf8e25f6c8ce40a15107fb4b4d288ca03dd434d057392f2ccb5fde505a300a0bf"
}
}
]
}

El evento de depósito de coin se emite cuando se depositan monedas en una cuenta. El balance de la cuenta aumentará por esa cantidad en el campo data.amoount. Para determinar el activo coincidente, debe coincidir el guid en los deposit_events con el guid en la sección changes para un CoinStore. De manera similar, si el CoinStore no se encuentra en los changes, significa que se eliminó, y un CoinStoreDeleteEvent debe estar presente en su lugar. Luego, puede coincidir el guid con deleted_deposit_event_handle_creation_number y event_handle_creation_address.

Evento de depósito de Coin
{
"events": [{
"guid": {
"creation_number": "2",
"account_address": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28"
},
"sequence_number": "0",
"type": "0x1::coin::DepositEvent",
"data": {
"amount": "10"
}
}]
}
  1. El consumo de gas solo se rastrea para APT. No hay un evento directo para rastrear el gas, pero puede ser calculado de la transacción. Usando el campo gas_used, y el campo gas_unit_price, puedes calcular el gas total utilizado. En este caso, el gas_used es 999 y el gas_unit_price es 100, por lo que el gas deducido del remitente(0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0) es 999 * 100 = 99900 subunidades Recuerda que las subunidades se usan aquí. El valor en el token de gas APT es 0.00099900 APT.
Información de gas
{
"gas_used": "999",
"max_gas_amount": "100000",
"gas_unit_price": "100",
"sender": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
}
  1. En resumen, necesitas tanto los eventos como los cambios para determinar la cantidad transferida de la cuenta. Los balances finales solo se mostrarán en los cambios. Si observas todos estos eventos, podrás manejar todas las transacciones posibles. A continuación está el ejemplo completo de la respuesta de la transacción.
Respuesta completa
{
"version": "1747361321",
"hash": "0x7c56ad56c7d02bb11887e535b9f1b221626d5b0d4cb5a1ffbadc358c1db515ea",
"state_change_hash": "0xc901b5e9e0965201e8205977720d7dea8a3709ee0d818fd5ec752cac13eaf18a",
"event_root_hash": "0x0077cb7df9db9ee7194c489db177fe9a325bcf3f1309ea99ed934085e5592041",
"state_checkpoint_hash": null,
"gas_used": "999",
"success": true,
"vm_status": "Executed successfully",
"accumulator_root_hash": "0xb531e918441ff0a37b49856e0f1b80c329146461582287cf9788964d25e31a68",
"changes": [
{
"address": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"state_key_hash": "0xb2bfa7198457291a0e582b912be2bf8577feff08e352c9f16935a55ebd202dcc",
"data": {
"type": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>",
"data": {
"coin": {
"value": "903837250"
},
"deposit_events": {
"counter": "10",
"guid": {
"id": {
"addr": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"creation_num": "2"
}
}
},
"frozen": false,
"withdraw_events": {
"counter": "52485",
"guid": {
"id": {
"addr": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"creation_num": "3"
}
}
}
}
},
"type": "write_resource"
},
{
"address": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"state_key_hash": "0xa3f2635d084b3cc01ae545c96ee15901549dab594363a46bf18e3d575c83102d",
"data": {
"type": "0x1::account::Account",
"data": {
"authentication_key": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"coin_register_events": {
"counter": "1",
"guid": {
"id": {
"addr": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"creation_num": "0"
}
}
},
"guid_creation_num": "4",
"key_rotation_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"creation_num": "1"
}
}
},
"rotation_capability_offer": {
"for": {
"vec": []
}
},
"sequence_number": "104628",
"signer_capability_offer": {
"for": {
"vec": []
}
}
}
},
"type": "write_resource"
},
{
"address": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"state_key_hash": "0xa45b7cfe18cc0ef1d6588f0f548a6a6a260d5e6bbab174507ed40cd21b7bd082",
"data": {
"type": "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>",
"data": {
"coin": {
"value": "10"
},
"deposit_events": {
"counter": "1",
"guid": {
"id": {
"addr": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"creation_num": "2"
}
}
},
"frozen": false,
"withdraw_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"creation_num": "3"
}
}
}
}
},
"type": "write_resource"
},
{
"address": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"state_key_hash": "0xba04f5a13812778031f67322e9801be65a846224e46f1360a6008402fcd0e0e0",
"data": {
"type": "0x1::account::Account",
"data": {
"authentication_key": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"coin_register_events": {
"counter": "1",
"guid": {
"id": {
"addr": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"creation_num": "0"
}
}
},
"guid_creation_num": "4",
"key_rotation_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"creation_num": "1"
}
}
},
"rotation_capability_offer": {
"for": {
"vec": []
}
},
"sequence_number": "0",
"signer_capability_offer": {
"for": {
"vec": []
}
}
}
},
"type": "write_resource"
},
{
"state_key_hash": "0x6e4b28d40f98a106a65163530924c0dcb40c1349d3aa915d108b4d6cfc1ddb19",
"handle": "0x1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca",
"key": "0x0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935",
"value": "0x9f9835f429758d010000000000000000",
"data": null,
"type": "write_table_item"
}
],
"sender": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0",
"sequence_number": "104627",
"max_gas_amount": "100000",
"gas_unit_price": "100",
"expiration_timestamp_secs": "1727826277",
"payload": {
"function": "0x1::aptos_account::transfer",
"type_arguments": [],
"arguments": [
"0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28",
"10"
],
"type": "entry_function_payload"
},
"signature": {
"public_key": "0xfd448fada2bac29c5f3213277e001ca8851d5644578e79484b0426c41357a457",
"signature": "0x40d8a6ee9150aa5736bee23ce1b1b851790bc0aa7e2485c0760d5808027040a2ef4170b88962867b045197576c5e89a4c640bf43586e6b3ead2b510b59acc20a",
"type": "ed25519_signature"
},
"events": [
{
"guid": {
"creation_number": "0",
"account_address": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28"
},
"sequence_number": "0",
"type": "0x1::account::CoinRegisterEvent",
"data": {
"type_info": {
"account_address": "0x1",
"module_name": "0x6170746f735f636f696e",
"struct_name": "0x4170746f73436f696e"
}
}
},
{
"guid": {
"creation_number": "3",
"account_address": "0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0"
},
"sequence_number": "52484",
"type": "0x1::coin::WithdrawEvent",
"data": {
"amount": "10"
}
},
{
"guid": {
"creation_number": "2",
"account_address": "0x5d6233bb8d7f8bd714af196339e9fb3104c9d66f38867b2a0585c4f7b9d04d28"
},
"sequence_number": "0",
"type": "0x1::coin::DepositEvent",
"data": {
"amount": "10"
}
},
{
"guid": {
"creation_number": "0",
"account_address": "0x0"
},
"sequence_number": "0",
"type": "0x1::transaction_fee::FeeStatement",
"data": {
"execution_gas_units": "6",
"io_gas_units": "5",
"storage_fee_octas": "98800",
"storage_fee_refund_octas": "0",
"total_charge_gas_units": "999"
}
}
],
"timestamp": "1727825677775812",
"type": "user_transaction"
}

Para activos fungibles, los cambios de balance se rastrean en el primary_fungible_store. La dirección del store principal de activos fungibles es determinista, y siempre será rastreada por el propietario del store.

Un ejemplo: https://api.mainnet.aptoslabs.com/v1/transactions/by\_version/1750174030

Hay varios pasos cuando se rastrean activos fungibles:

  1. Habrá dos tipos de eventos para activos fungibles. 0x1::fungible_asset::Deposit y 0x1::fungible_asset::Withdraw.

Los eventos Withdraw son similares a los eventos de coin, donde el balance disminuirá por la cantidad en el campo data.amount. Y de manera similar, los eventos Deposit aumentarán el balance por la cantidad en el campo data.amount.

Nota: He omitido el número de secuencia y el campo GUID, ya que no se aplican a los eventos de módulo.

Cada evento tiene un campo store, que en este caso es 0x8a9d57692a9d4deb1680eaf107b83c152436e10f7bb521143fa403fa95ef76a. Esta es la dirección del FungibleStore para el activo, donde se almacena el balance. Tenga en cuenta esto, para el siguiente paso.

Eventos de Activo Funciable
{
"events": [
{
"type": "0x1::fungible_asset::Withdraw",
"data": {
"amount": "1",
"store": "0x8a9d57692a9d4deb1680eaf107b83c152436e10f7bb521143fa403fa95ef76a"
}
},
{
"type": "0x1::fungible_asset::Deposit",
"data": {
"amount": "1",
"store": "0x8a9d57692a9d4deb1680eaf107b83c152436e10f7bb521143fa403fa95ef76a"
}
}
]
}
  1. A continuación, examinamos los 0x1::fungible_asset::FungibleStore cambios. Esto mostrará el estado final del balance para el activo fungible. El balance está en el campo data.balance. El campo address coincidirá con el campo store de los eventos. El identificador del activo fungible es el campo metadata. Es la dirección del metadata para el activo fungible.

Además, para averiguar el propietario real de los activos, necesitarás mirar el propietario del store. En este caso, necesitarás el 0x1::object::ObjectCore, donde el campo address coincide con el campo store de los eventos. El campo owner mostrará la dirección del propietario del activo. similar a los eventos de coin, si el ObjectCore no se encuentra en los changes, significa que se eliminó, y un FungibleStoreDeletion evento debe estar presente en su lugar. Luego, puedes coincidir los campos store entre los eventos Withdraw/Deposit y el evento FungibleStoreDeletion.

Cambios de Activo Funciable
{
"changes":[
{
"address": "0x8a9d57692a9d4deb1680eaf107b83c152436e10f7bb521143fa403fa95ef76a",
"state_key_hash": "0x5b587931247dd5b43874ab29c3305c0ee7d26e7571fed3aea409375530e3a62c",
"data": {
"type": "0x1::fungible_asset::FungibleStore",
"data": {
"balance": "126691270443",
"frozen": false,
"metadata": {
"inner": "0x2ebb2ccac5e027a87fa0e2e5f656a3a4238d6a48d93ec9b610d570fc0aa0df12"
}
}
},
"type": "write_resource"
},
{
"address": "0x8a9d57692a9d4deb1680eaf107b83c152436e10f7bb521143fa403fa95ef76a",
"state_key_hash": "0x5b587931247dd5b43874ab29c3305c0ee7d26e7571fed3aea409375530e3a62c",
"data": {
"type": "0x1::object::ObjectCore",
"data": {
"allow_ungated_transfer": false,
"guid_creation_num": "1125899906842628",
"owner": "0xc67545d6f3d36ed01efc9b28cbfd0c1ae326d5d262dd077a29539bcee0edce9e",
"transfer_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0x8a9d57692a9d4deb1680eaf107b83c152436e10f7bb521143fa403fa95ef76a",
"creation_num": "1125899906842624"
}
}
}
}
},
"type": "write_resource"
}
]
}
Evento de eliminación de FungibleStore
{
"guid": {
"creation_number": "0",
"account_address": "0x0"
},
"sequence_number": "0",
"type": "0x1::fungible_asset::FungibleStoreDeletion",
"data": {
"metadata": "0x2ebb2ccac5e027a87fa0e2e5f656a3a4238d6a48d93ec9b610d570fc0aa0df12",
"owner": "0xcf3906e2c9bc7e489c3b09d5ed5d90d8d403a68a50fe52932116b26e5878af26",
"store": "0xa6ab8518e5f28a5f27247a895aa8b3de4a917209c6841b16187e8d64a67de242"
}
}

Cambios de balance de monedas migradas a activos fungibles

Sección titulada «Cambios de balance de monedas migradas a activos fungibles»

Para monedas migradas a activos fungibles, es simplemente el seguimiento de los dos anteriores. Una moneda migrada a un activo fungible tendrá ambos cambios de store de coin y cambios de store de activo fungible principal. Las cantidades necesitarían ser agregadas juntas, y de lo contrario, manejadas como una moneda.

La dirección de metadatos de activo fungible es el hash del tipo de moneda y 0xA

address = sha3_256(0xA | coin_type | 0xFE)

Aquí hay un ejemplo de una moneda migrada con APT: https://api.mainnet.aptoslabs.com/v1/transactions/by\_version/1642580695

Respuesta completa
{
"version": "1642580695",
"hash": "0xe67ba1c4242d5c1de42eb8419558c4edf2318e185a3940a00f4150b519d06508",
"state_change_hash": "0x07c5ec97afdf731c2778fccb37fe209369b28dcf6dcf11c3cf13b83c962f7f96",
"event_root_hash": "0xad349cbea90bef601dfae9df822f5698af296951fc5f94359fcacc1e69e9fa3d",
"state_checkpoint_hash": null,
"gas_used": "545",
"success": true,
"vm_status": "Executed successfully",
"accumulator_root_hash": "0x88e81bde70f32a86e46b288a917a44b2868a46973fac7fad16b5e780f48b0e67",
"changes": [
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::coin::PairedCoinType",
"data": {
"type": {
"account_address": "0x1",
"module_name": "0x6170746f735f636f696e",
"struct_name": "0x4170746f73436f696e"
}
}
},
"type": "write_resource"
},
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::coin::PairedFungibleAssetRefs",
"data": {
"burn_ref_opt": {
"vec": [
{
"metadata": {
"inner": "0xa"
}
}
]
},
"mint_ref_opt": {
"vec": [
{
"metadata": {
"inner": "0xa"
}
}
]
},
"transfer_ref_opt": {
"vec": [
{
"metadata": {
"inner": "0xa"
}
}
]
}
}
},
"type": "write_resource"
},
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::fungible_asset::ConcurrentSupply",
"data": {
"current": {
"max_value": "340282366920938463463374607431768211455",
"value": "47948384"
}
}
},
"type": "write_resource"
},
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::fungible_asset::Metadata",
"data": {
"decimals": 8,
"icon_uri": "",
"name": "Aptos Coin",
"project_uri": "",
"symbol": "APT"
}
},
"type": "write_resource"
},
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::object::ObjectCore",
"data": {
"allow_ungated_transfer": true,
"guid_creation_num": "1125899906842625",
"owner": "0x1",
"transfer_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0xa",
"creation_num": "1125899906842624"
}
}
}
}
},
"type": "write_resource"
},
{
"address": "0xa",
"state_key_hash": "0x1db5441d8fa4229c5844f73fd66da4ad8176cb8793d8b3a7f6ca858722030043",
"data": {
"type": "0x1::primary_fungible_store::DeriveRefPod",
"data": {
"metadata_derive_ref": {
"self": "0xa"
}
}
},
"type": "write_resource"
},
{
"address": "0x7ed92ce166e251fc133f6b4d46a6b41307962e3b6864c2231110b3808648188",
"state_key_hash": "0x5ce89e323a23fb5570694dfb687d474d44563638c5ef774a2364d8347f5732b8",
"data": {
"type": "0x1::coin::MigrationFlag",
"data": {
"dummy_field": false
}
},
"type": "write_resource"
},
{
"address": "0x7ed92ce166e251fc133f6b4d46a6b41307962e3b6864c2231110b3808648188",
"state_key_hash": "0x5ce89e323a23fb5570694dfb687d474d44563638c5ef774a2364d8347f5732b8",
"data": {
"type": "0x1::fungible_asset::FungibleStore",
"data": {
"balance": "37949184",
"frozen": false,
"metadata": {
"inner": "0xa"
}
}
},
"type": "write_resource"
},
{
"address": "0x7ed92ce166e251fc133f6b4d46a6b41307962e3b6864c2231110b3808648188",
"state_key_hash": "0x5ce89e323a23fb5570694dfb687d474d44563638c5ef774a2364d8347f5732b8",
"data": {
"type": "0x1::object::ObjectCore",
"data": {
"allow_ungated_transfer": false,
"guid_creation_num": "1125899906842625",
"owner": "0xa746e980ae21949a4f084db7403430f00bce3c9a1da4101ffcf0bf45ebd35e7e",
"transfer_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0x7ed92ce166e251fc133f6b4d46a6b41307962e3b6864c2231110b3808648188",
"creation_num": "1125899906842624"
}
}
}
}
},
"type": "write_resource"
},
{
"address": "0x8a4613c356c21a45045e06dcc404bfee363aabd65a774d4d43defd71289239b2",
"state_key_hash": "0x7c2d6e31d4ac5bbf93e19412437c0c288766b240674f71f457b9e3ef68be5003",
"data": {
"type": "0x1::fungible_asset::FungibleStore",
"data": {
"balance": "10000",
"frozen": false,
"metadata": {
"inner": "0xa"
}
}
},
"type": "write_resource"
},
{
"address": "0x8a4613c356c21a45045e06dcc404bfee363aabd65a774d4d43defd71289239b2",
"state_key_hash": "0x7c2d6e31d4ac5bbf93e19412437c0c288766b240674f71f457b9e3ef68be5003",
"data": {
"type": "0x1::object::ObjectCore",
"data": {
"allow_ungated_transfer": false,
"guid_creation_num": "1125899906842625",
"owner": "0x5",
"transfer_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0x8a4613c356c21a45045e06dcc404bfee363aabd65a774d4d43defd71289239b2",
"creation_num": "1125899906842624"
}
}
}
}
},
"type": "write_resource"
},
{
"address": "0xa746e980ae21949a4f084db7403430f00bce3c9a1da4101ffcf0bf45ebd35e7e",
"state_key_hash": "0xfb7c1f2762da89f00a222f93bd771b478edb4361475c4a518178564be8616dd6",
"data": {
"type": "0x1::account::Account",
"data": {
"authentication_key": "0xa746e980ae21949a4f084db7403430f00bce3c9a1da4101ffcf0bf45ebd35e7e",
"coin_register_events": {
"counter": "14",
"guid": {
"id": {
"addr": "0xa746e980ae21949a4f084db7403430f00bce3c9a1da4101ffcf0bf45ebd35e7e",
"creation_num": "0"
}
}
},
"guid_creation_num": "44",
"key_rotation_events": {
"counter": "0",
"guid": {
"id": {
"addr": "0xa746e980ae21949a4f084db7403430f00bce3c9a1da4101ffcf0bf45ebd35e7e",
"creation_num": "1"
}
}
},
"rotation_capability_offer": {
"for": {
"vec": []
}
},
"sequence_number": "52",
"signer_capability_offer": {
"for": {
"vec": []
}
}
}
},
"type": "write_resource"
}
],
"sender": "0xa746e980ae21949a4f084db7403430f00bce3c9a1da4101ffcf0bf45ebd35e7e",
"sequence_number": "51",
"max_gas_amount": "817",
"gas_unit_price": "100",
"expiration_timestamp_secs": "1724196316",
"payload": {
"function": "0x1::primary_fungible_store::transfer",
"type_arguments": [
"0x1::fungible_asset::Metadata"
],
"arguments": [
{
"inner": "0xa"
},
"0x5",
"10000"
],
"type": "entry_function_payload"
},
"signature": {
"public_key": "0x330e75a102e37270b788caee8dd819e5badedd5fa17fe9f72017732e9bb98c60",
"signature": "0xd4666df2887cf2d8192230e4a03d842ea75a86ffbc46a9a16a9baede6ff646c6b2bcafc524d3a4a7a66c223b5db576beb5cfefbd549620e69097c0a364c7a800",
"type": "ed25519_signature"
},
"events": [
{
"guid": {
"creation_number": "0",
"account_address": "0x0"
},
"sequence_number": "0",
"type": "0x1::fungible_asset::Withdraw",
"data": {
"amount": "10000",
"store": "0x7ed92ce166e251fc133f6b4d46a6b41307962e3b6864c2231110b3808648188"
}
},
{
"guid": {
"creation_number": "0",
"account_address": "0x0"
},
"sequence_number": "0",
"type": "0x1::fungible_asset::Deposit",
"data": {
"amount": "10000",
"store": "0x8a4613c356c21a45045e06dcc404bfee363aabd65a774d4d43defd71289239b2"
}
},
{
"guid": {
"creation_number": "0",
"account_address": "0x0"
},
"sequence_number": "0",
"type": "0x1::fungible_asset::Withdraw",
"data": {
"amount": "54500",
"store": "0x7ed92ce166e251fc133f6b4d46a6b41307962e3b6864c2231110b3808648188"
}
},
{
"guid": {
"creation_number": "0",
"account_address": "0x0"
},
"sequence_number": "0",
"type": "0x1::transaction_fee::FeeStatement",
"data": {
"execution_gas_units": "6",
"io_gas_units": "7",
"storage_fee_octas": "53240",
"storage_fee_refund_octas": "0",
"total_charge_gas_units": "545"
}
}
],
"timestamp": "1724196287102837",
"type": "user_transaction"
}

Te sugerimos que uses 0x1::aptos_account::transfer_coins<CoinType>(dirección de receptor, cantidad) para transferir monedas. Esto registrará el coin si no ha sido registrado aún, y creará la cuenta asociada si no ha sido creada aún. Esto continuará funcionando con cualquier moneda que haya sido migrada a un activo fungible, incluyendo APT.

Las monedas pueden ser transferidas de las siguientes maneras:

Te sugerimos que uses 0x1::primary_fungible_store::transfer<0x1::object::ObjectCore>(dirección de receptor, cantidad) para transferir activos fungibles. Enviará el activo asociado y creará un store principal para el activo si no ha sido creado aún.

Para verificar que todo está funcionando correctamente, hemos proporcionado estas verificaciones.

Para probar las verificaciones de balance, puedes verificar el balance para la cuenta 0x5 para el activo 0x1::aptos_coin::AptosCoin. El balance debería mostrar 0.002 APT, donde 0.001 APT es una moneda, y 0.001 APT es una moneda migrada (activo fungible).

Si tu balance no es correcto, consulta Balances de Coin y Moneda Migrada para más información.

Verificaciones de cambio de balance / transferencia

Sección titulada «Verificaciones de cambio de balance / transferencia»

Para probar una transferencia, crea una transacción para transferir 0.001 APT a otra cuenta. La transacción debería ser exitosa, y el balance debería actualizarse, donde el balance es 0.001 APT menor y menos el costo de gas asociado.

Para probar una transferencia, puedes financiar una cuenta con el activo fungible aquí https://test-token-faucet.vercel.app/ y luego transferir el activo fungible a otra cuenta. El balance debería actualizarse según el cambio, y deberías poder rastrear el mint en el sitio web.

Nombre del TokenSímboloDirección del TokenFuente de la Dirección
Tether USDUSDt0x357b0b74bc833e95a115ad22604854d6b0fca151cecd94111770e5d6ffc9dc2bAptos Foundation
USDCUSDC0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3bCircle
Ondo US Dollar YieldUSDY0xcfea864b32833f157f042618bd845145256b1bf4c0da34a7013b76e42daa53cc::usdy::USDYOndo Finance

¿Cuál es la finalidad de una transacción?

Sección titulada «¿Cuál es la finalidad de una transacción?»

Aptos usa un algoritmo de consenso BFT, por lo que las transacciones se finalizan inmediatamente después de comprometerse a la blockchain.

¿Cuál es el cargo de transacción en una transacción?

Sección titulada «¿Cuál es el cargo de transacción en una transacción?»

Los cargos de transacción son variables, pero para la mayoría de los casos aquí son fijos. Consulta simulando transacciones para tener una idea del cargo.