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:
- A funded IXO account on the network you target — see Networks and endpoints.
- An offline signer (Cosmos-kit, Keplr, or
getOfflineSignerfromcosmjs-utils) — see the SDK README on creating signers. - The
@ixo/impactxclient-sdkinstalled.
npm install @ixo/impactxclient-sdkThe 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.
Field names mirror the x/entity proto definitions. Inspect entity.proto for the authoritative field list and any version-specific changes.
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.
account already exists
Account names are unique per entity. Pick a different name or revoke and re-grant authz on the existing account.