Skip to content

Activos en el mundo real ​

Activos del mundo real (RWAs) modelo de activos fuera de la cadena cuya propiedad o control se rastrea en la cadena. En Iroha, un RWA es un lote registrado con un identificador generado, una cuenta del propietario, una cantidad, metadatos comerciales, procedencia y controles opcionales del ciclo de vida.

RWAs son diferentes de los saldos numéricos de activos:

  • un activo numérico es un saldo fungible mantenido por una cuenta
  • un NFT es un registro único en cadena con un solo propietario
  • un RWA es un lote que puede contener metadatos comerciales, cantidad, reservas, congelaciones, estado de redención, procedencia y política del controlador.

Utilice RWAs cuando el libro mayor necesite representar un lote específico fuera de la cadena en lugar de solo un saldo fungible.

RWA Lote ​

Un lote de RWA contiene:

  • id: el identificador canónico RWA generado, que se muestra como <hash>$<domain>
  • owned_by: la cuenta que actualmente es dueña del lote
  • quantity: la cantidad pendiente representada por el lote.
  • spec: especificación de cantidad, por ejemplo en escala decimal
  • primary_reference: el recibo, certificado, factura o referencia de registro principal fuera de la cadena.
  • status: texto opcional sobre el estado de la empresa
  • metadata: campos compactos JSON utilizados para el contexto empresarial y la indexación.
  • parents: lotes de origen utilizados para obtener este lote
  • controls: Cuentas del controlador, funciones del controlador y operaciones habilitadas del controlador.
  • is_frozen y held_quantity: estado del ciclo de vida aplicado por el tiempo de ejecución.

Mantenga la carga útil en cadena compacta. Guarde documentos legales grandes, informes de inspección y paquetes de auditoría fuera del WSV, luego coloque un digesto, URI, SoraFS camino o referencia manifiesta en los metadatos RWA.

Identificadores ​

RegisterRwa no acepta una llamada elegida por el solicitante id, y no acepta un campo owner. La autoridad de transacción se convierte en la cuenta inicial owned_by, y el tiempo de ejecución genera el RwaId en el dominio objetivo.

La forma textual de un RWA ID es:

text
<generated-hash>$<domain>

Por ejemplo:

text
0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef$commodities.universal

Las solicitudes deben almacenar su identificación comercial en primary_reference o metadata, y luego descubrir la RwaId generada a partir de RwaEvent::Created, FindRwas, /v1/rwas, o la ruta del explorador establecida después de que la transacción se comprometa.

Ciclo de vida ​

Los flujos de trabajo comunes RWA incluyen:

OperaciónEl comportamiento implementado
RegisterRwaCrear un lote generado- ID en un dominio; la autoridad de transacción se convierte en owned_by.
TransferRwaTrasladar la cantidad a otra cuenta. Una transferencia completa puede cambiar owned_by. Una transferencia parcial crea un lote infantil separado con una ID generada.
HoldRwaCantidad de reserva Requiere un controlador configurado y hold_enabled.
ReleaseRwaRetira la cantidad retenida. Requiere un controlador configurado y hold_enabled.
FreezeRwaBloqueo de las operaciones del propietario ordinario. Requiere un controlador configurado y freeze_enabled.
UnfreezeRwaRehabilitar las operaciones ordinarias del propietario. Requiere un controlador configurado y freeze_enabled.
RedeemRwaSubtraer permanentemente la cantidad de circulación. El propietario o un controlador podrá presentarla cuando redeem_enabled sea verdadera.
MergeRwasCombine las cantidades de los lotes padres con el mismo dominio y especificación en un lote de hijos generado.
ForceTransferRwaMover la cantidad a través de un flujo del controlador. Requiere un controlador configurado y force_transfer_enabled.
SetRwaControlsReplace la política de control del lote. Requiere que el propietario o un controlador.
SetKeyValue<Rwa> / RemoveKeyValue<Rwa>Actualización de los metadatos del lote Requiere el propietario o un controlador; lotes congelados requieren un controlador.

No hay instrucción UnregisterRwa en el código actual. Retirar un lote fuera de la cadena con RedeemRwa cuando se entregue, consuma, liquide o retire de otra manera la cantidad representada de la circulación.

Metadatos y controles ​

Usar metadatos para datos compactos que ayuden a las aplicaciones a identificar y verificar el lote:

  • Clasificación de activos, emisor, custodio o referencia del registro
  • Identificadores de almacén, bóveda, ISIN, factura o certificado
  • hashes de contenido para los certificados y documentos legales
  • SoraFS trayectorias o referencias manifiestas para paquetes de pruebas más grandes
  • etiquetas de vencimiento, jurisdicción o cumplimiento utilizadas por los servicios fuera de la cadena

El RwaControlPolicy implementado contiene los siguientes campos:

json
{
  "controller_accounts": [],
  "controller_roles": [],
  "freeze_enabled": true,
  "hold_enabled": true,
  "force_transfer_enabled": false,
  "redeem_enabled": true
}

Las cuentas y roles del controlador solo pueden realizar las operaciones habilitadas por las banderas booleanas correspondientes. La carga útil de control actual contiene identidades de controladores y banderas de operación. transfers Las reglas están fuera de esta carga útil.

Encuestas, eventos y APIs ​

Utilización FindRwas a la lista registrada RWA Las aplicaciones que necesitan actualizaciones en vivo pueden suscribirse a Rwa eventos de datos para los productos creados, cambiados de propietario, divididos, fusionados, canjeados, congelados, descongelados, los eventos de mantenimiento, liberación, transferencia de fuerza, cambio de controles y metadatos.

Torii expone rutas de estado en cadena como /v1/rwas y /v1/rwas/query, además de rutas exploradoras como /v1/explorer/rwas y /v1/explorer/rwas/{rwa_id} cuando esa familia de rutas está habilitada. Los clientes generados deben preferir el documento en vivo /openapi para la forma exacta de respuesta expuesta por un nodo.

Pruébalo en Taira ​

Verifique si el Taira público ha registrado actualmente lotes RWA:

bash
curl -fsS 'https://taira.sora.org/v1/rwas?limit=5' \
  | jq '{total, rwa_ids: [.items[].id]}'

Lista de las rutas RWA expuestas por el documento en vivo Taira OpenAPI:

bash
curl -fsS https://taira.sora.org/openapi.json \
  | jq -r '.paths | keys[] | select(startswith("/v1/rwas") or startswith("/v1/explorer/rwas"))'

Se espera una salida vacía items cuando aún no se han registrado lotes públicos. Las transacciones de registro, transferencia, retención, congelación y canje son firmadas.

Pruébalo. ​

Los ejemplos a continuación utilizan el Python SDK las superficies de Configuración compartida. Reemplazar la cuenta IDs, llaves privadas, y lote generado IDs con los valores de su propia red antes de enviar una transacción.

Descubra las rutas RWA API ​

Este ejemplo de sólo lectura pide a un nodo Torii en ejecución cuáles rutas RWA orientadas a la aplicación están habilitadas:

python
from iroha_python import create_torii_client

client = create_torii_client("https://taira.sora.org")
openapi = client.request_json("GET", "/openapi", expected_status=(200,))

rwa_paths = sorted(
    path for path in openapi.get("paths", {}) if path.startswith("/v1/rwas")
)

for path in rwa_paths:
    print(path)

Si la lista está vacía, el nodo aún puede admitir instrucciones y consultas RWA a través de otras Torii APIs, pero no expone la familia de rutas JSON opcional.

Registro de un recibo del almacén ​

Utilice un borrador cuando una acción comercial debe convertirse en una transacción firmada. El número de recibo comercial entra en primary_reference; el libro mayor ID se genera después de que la transacción se comprometa.

python
from iroha_python import TransactionConfig, TransactionDraft

config = TransactionConfig(
    chain_id=CHAIN_ID,
    authority=alice,
    metadata={**TX_METADATA, "source": "rwa-docs"},
)

draft = TransactionDraft(config)
draft.register_rwa(
    {
        "domain": "commodities.universal",
        "quantity": "100",
        "spec": {"scale": 0},
        "primary_reference": "warehouse-receipt-001",
        "status": "active",
        "metadata": {
            "asset_class": "commodity",
            "commodity": "copper",
            "warehouse": "DXB-01",
            "inspection_report": "sorafs://reports/copper-001.json",
        },
        "parents": [],
        "controls": {
            "controller_accounts": [alice],
            "controller_roles": [],
            "freeze_enabled": True,
            "hold_enabled": True,
            "force_transfer_enabled": False,
            "redeem_enabled": True,
        },
    }
)

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Después de que la transacción se comprometa, se genera una lista RWA IDs. Las rutas en estado de cadena exponen el canónico IDs; utilice eventos o rutas detalladas del explorador cuando necesite emparejar un ID de vuelta a primary_reference o metadatos:

python
page = client.list_rwas_typed(limit=20, offset=0)

for lot in page.items:
    print(lot.id)

Los nodos habilitados para exploradores también pueden devolver proyecciones más ricas:

python
page = client.list_explorer_rwas_typed(domain="commodities.universal")

for lot in page.items:
    print(lot.id, lot.primary_reference, lot.owned_by, lot.quantity)

Traslado con una retención temporal ​

Utilice el generado RWA ID devuelto por la cadena. Este ejemplo supone que alice es el propietario y también está configurado como un controlador con hold_enabled.

python
warehouse_lot_id = (
    "0123456789abcdef0123456789abcdef"
    "0123456789abcdef0123456789abcdef$commodities.universal"
)

draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=alice, metadata=TX_METADATA)
)

draft.transfer_rwa(warehouse_lot_id, quantity="10", destination=bob)
draft.hold_rwa(warehouse_lot_id, quantity="5")

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Enviar ReleaseRwa después del éxito del proceso fuera de la cadena:

python
draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=alice, metadata=TX_METADATA)
)
draft.release_rwa(warehouse_lot_id, quantity="5")

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Añadir metadatos de control y auditoría ​

Los controles y los metadatos son separados. Utilice controles para la política del controlador, y metadatos para hechos que las aplicaciones o auditores necesitan mostrar:

python
draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=alice, metadata=TX_METADATA)
)

draft.set_rwa_controls(
    warehouse_lot_id,
    {
        "controller_accounts": [alice],
        "controller_roles": [],
        "freeze_enabled": True,
        "hold_enabled": True,
        "force_transfer_enabled": True,
        "redeem_enabled": True,
    },
)
draft.set_rwa_key_value(warehouse_lot_id, "auditor", "alice")
draft.set_rwa_key_value(
    warehouse_lot_id,
    "proof_hash",
    "sha256:2b1c7a4e...",
)

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Cantidad de rescate o retirada ​

Enviar RedeemRwa después de que el activo fuera de la cadena representado sea entregado, consumido, retirado o eliminado de otra manera de la circulación. Esto restará permanentemente la cantidad presentada del lote. El lote debe tener redeem_enabled. El firmante debe ser el propietario o un controlador.

python
draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=alice, metadata=TX_METADATA)
)
draft.redeem_rwa(warehouse_lot_id, quantity="1")

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Se congela durante la revisión del cumplimiento ​

Enviar FreezeRwa cuando una revisión fuera de la cadena debe bloquear las operaciones ordinarias del propietario. El firmante debe ser un controlador. El lote debe tener freeze_enabled.

python
draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=alice, metadata=TX_METADATA)
)
draft.freeze_rwa(warehouse_lot_id)
draft.set_rwa_key_value(
    warehouse_lot_id,
    "review",
    {
        "status": "frozen",
        "reason": "custodian inventory check",
        "case_id": "OPS-2026-0042",
    },
)

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Presentar UnfreezeRwa después de la aprobación del examen:

python
draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=alice, metadata=TX_METADATA)
)
draft.unfreeze_rwa(warehouse_lot_id)
draft.set_rwa_key_value(
    warehouse_lot_id,
    "review",
    {"status": "cleared", "case_id": "OPS-2026-0042"},
)

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Las facturas que se deben recibir ​

Representar una factura como lote RWA almacenando el número de la factura en primary_reference y los metadatos. Después del registro, utilice la ID generada para su transferencia y canje.

python
draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=alice, metadata=TX_METADATA)
)
draft.register_rwa(
    {
        "domain": "receivables.universal",
        "quantity": "50000",
        "spec": {"scale": 2},
        "primary_reference": "INV-2026-0007",
        "status": "issued",
        "metadata": {
            "asset_class": "invoice",
            "currency": "USD",
            "debtor": "example-buyer",
            "due_date": "2026-06-30",
            "document_hash": "sha256:4df4c8...",
        },
        "parents": [],
        "controls": {
            "controller_accounts": [alice],
            "controller_roles": [],
            "freeze_enabled": True,
            "hold_enabled": False,
            "force_transfer_enabled": False,
            "redeem_enabled": True,
        },
    }
)

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Cuando se financie o pague el crédito, utilice el lote de facturas generado ID:

python
invoice_lot_id = (
    "fedcba9876543210fedcba9876543210"
    "fedcba9876543210fedcba9876543210$receivables.universal"
)

draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=alice, metadata=TX_METADATA)
)
draft.transfer_rwa(invoice_lot_id, quantity="50000", destination=bob)

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Redención del importe representado después de la liquidación fuera de la cadena:

python
draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=bob, metadata=TX_METADATA)
)
draft.redeem_rwa(invoice_lot_id, quantity="50000")

envelope = draft.sign_with_keypair(bob_pair)
client.submit_transaction_envelope_and_wait(envelope)

Retiro del crédito por carbono ​

Presentar RedeemRwa para eliminar los créditos de carbono reclamados de la circulación. Guardar el certificado fuera de cadena o la prueba del registro en metadatos:

python
carbon_lot_id = (
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$carbon.universal"
)

draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=alice, metadata=TX_METADATA)
)
draft.redeem_rwa(carbon_lot_id, quantity="250")
draft.set_rwa_key_value(
    carbon_lot_id,
    "retirement_certificate",
    "sorafs://certificates/carbon-credit-2026-001-retired.json",
)

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Fusión de dos lotes ​

Combinar los lotes cuando se consolidan dos posiciones fuera de la cadena. Los padres deben estar en el mismo dominio y usar la misma especificación de cantidad. El tiempo de ejecución genera el lote hijo ID.

python
warehouse_lot_id_2 = (
    "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
    "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb$commodities.universal"
)

draft = TransactionDraft(
    TransactionConfig(chain_id=CHAIN_ID, authority=alice, metadata=TX_METADATA)
)
draft.merge_rwas(
    {
        "parents": [
            {"rwa": warehouse_lot_id, "quantity": "40"},
            {"rwa": warehouse_lot_id_2, "quantity": "60"},
        ],
        "primary_reference": "warehouse-receipt-003",
        "status": "merged",
        "metadata": {
            "asset_class": "commodity",
            "commodity": "copper",
            "warehouse": "DXB-01",
            "merge_reason": "same custodian and quality grade",
        },
    }
)

envelope = draft.sign_with_keypair(alice_pair)
client.submit_transaction_envelope_and_wait(envelope)

Para el ejemplo completo de la transacción Python, véase Real-World Assets.