Manage entities

Create, transfer, verify, and govern entity domains on the IXO Protocol with the IXO MultiClient SDK.

This guide shows the chain-level message patterns for managing entities on the IXO Protocol using the @ixo/impactxclient-sdk. For the data model, read Entity domains and Domain configuration first.

Before you start

You need:

npm install @ixo/impactxclient-sdk

The signing client follows the canonical three-step pattern: compose, sign, broadcast.

import { ixo, createSigningClient } from "@ixo/impactxclient-sdk";

const signingClient = await createSigningClient(RPC_ENDPOINT, offlineSigner);

Create an entity

const message = {
  typeUrl: "/ixo.entity.v1beta1.MsgCreateEntity",
  value: ixo.entity.v1beta1.MsgCreateEntity.fromPartial({
    ownerAddress: signerAddress,
    entityType: "asset",
    context: [
      ixo.iid.v1beta1.Context.fromPartial({
        key: "class",
        val: "did:ixo:entity:protocol123",
      }),
    ],
    verification: [],
    controller: [],
    service: [],
    linkedResource: [],
    accordedRight: [],
    linkedEntity: [],
    linkedClaim: [],
  }),
};

const response = await signingClient.signAndBroadcast(signerAddress, [message], "auto");

The chain returns a transaction with events that include the new entity DID.

Transfer entity ownership

MsgTransferEntity reassigns the underlying entity NFT to a new controller account.

const transferMsg = {
  typeUrl: "/ixo.entity.v1beta1.MsgTransferEntity",
  value: ixo.entity.v1beta1.MsgTransferEntity.fromPartial({
    id: entityDid,
    ownerAddress: currentOwnerAddress,
    recipientDid: "did:ixo:recipient123",
  }),
};

await signingClient.signAndBroadcast(currentOwnerAddress, [transferMsg], "auto");

Update verification status

A verifying authority (oracle, registry, or DAO controller) calls MsgUpdateEntityVerified to flip the verified flag for one or more entities it is permitted to attest.

const verifyMsg = {
  typeUrl: "/ixo.entity.v1beta1.MsgUpdateEntityVerified",
  value: ixo.entity.v1beta1.MsgUpdateEntityVerified.fromPartial({
    id: entityDid,
    relayerNode: relayerDid,
    entityVerified: true,
  }),
};

await signingClient.signAndBroadcast(signerAddress, [verifyMsg], "auto");

Manage entity accounts

Entities can hold named sub-accounts (for example treasury, payouts, operations) that can transact on behalf of the entity under explicit authz grants.

const createAccountMsg = {
  typeUrl: "/ixo.entity.v1beta1.MsgCreateEntityAccount",
  value: ixo.entity.v1beta1.MsgCreateEntityAccount.fromPartial({
    id: entityDid,
    ownerAddress: signerAddress,
    name: "treasury",
  }),
};

const grantMsg = {
  typeUrl: "/ixo.entity.v1beta1.MsgGrantEntityAccountAuthz",
  value: ixo.entity.v1beta1.MsgGrantEntityAccountAuthz.fromPartial({
    id: entityDid,
    ownerAddress: signerAddress,
    name: "treasury",
    granteeAddress: granteeAddress,
    grant: /* cosmos.authz.v1beta1.Grant */ undefined,
  }),
};

const revokeMsg = {
  typeUrl: "/ixo.entity.v1beta1.MsgRevokeEntityAccountAuthz",
  value: ixo.entity.v1beta1.MsgRevokeEntityAccountAuthz.fromPartial({
    id: entityDid,
    ownerAddress: signerAddress,
    name: "treasury",
    granteeAddress: granteeAddress,
    msgTypeUrl: "/cosmos.bank.v1beta1.MsgSend",
  }),
};

Construct the grant value using cosmos.authz.v1beta1.Grant.fromPartial({...}) with the matching authorization. See Authentication and authorization and Custom authorisations for IXO Claims.

Verify the result

Query the entity through the Blocksync GraphQL API:

query GetEntity($did: String!) {
  entity(id: $did) {
    id
    type
    status
    relayerNode
    owner
    controller
    accounts {
      name
      address
    }
  }
}

Or use the gRPC gateway directly — see gRPC gateway API for the entity module endpoints.

Troubleshooting

invalid entity type

The entityType value must match a type the chain accepts. Inspect module params via the gRPC gateway or query the EntityList endpoint to confirm allowed types on your network.

unauthorized

The signer must be a current controller or relayer with the right capability. Confirm the signer address is in the entity's controller set or has an active authz grant.

account already exists

Account names are unique per entity. Pick a different name or revoke and re-grant authz on the existing account.

Next steps