Authorization (x/authz) lets one account grant another the right to broadcast specific message types on its behalf, scoped by amount, time, or message URL. x/feegrant lets one account pay another’s transaction fees. Both are standard Cosmos SDK modules — IXO uses the upstream message types directly.
Before you start
You need:
An IXO account with uixo for fees on the network you target — see Networks and endpoints .
An offline signer — see the SDK README .
The granter and grantee bech32 addresses.
npm install @ixo/impactxclient-sdk
import { cosmos , createSigningClient } from "@ixo/impactxclient-sdk" ;
const signingClient = await createSigningClient ( RPC_ENDPOINT , offlineSigner );
Grant a send authorization
SendAuthorization lets the grantee call cosmos.bank.v1beta1.MsgSend from the granter, capped at spend_limit.
const sendAuth = cosmos . bank . v1beta1 . SendAuthorization . fromPartial ({
spendLimit: [{ denom: "uixo" , amount: "1000000" }],
});
const grantMsg = {
typeUrl: "/cosmos.authz.v1beta1.MsgGrant" ,
value: cosmos . authz . v1beta1 . MsgGrant . fromPartial ({
granter: granterAddress ,
grantee: granteeAddress ,
grant: cosmos . authz . v1beta1 . Grant . fromPartial ({
authorization: {
typeUrl: "/cosmos.bank.v1beta1.SendAuthorization" ,
value: cosmos . bank . v1beta1 . SendAuthorization . encode ( sendAuth ). finish (),
},
}),
}),
};
await signingClient . signAndBroadcast ( granterAddress , [ grantMsg ], "auto" );
For broader grants (e.g. authorize any IBC transfer message URL), use cosmos.authz.v1beta1.GenericAuthorization with the target msg type URL.
Execute a granted message
The grantee wraps the message they were authorized to send inside cosmos.authz.v1beta1.MsgExec.
const innerSend = cosmos . bank . v1beta1 . MsgSend . fromPartial ({
fromAddress: granterAddress ,
toAddress: recipientAddress ,
amount: [{ denom: "uixo" , amount: "100000" }],
});
const execMsg = {
typeUrl: "/cosmos.authz.v1beta1.MsgExec" ,
value: cosmos . authz . v1beta1 . MsgExec . fromPartial ({
grantee: granteeAddress ,
msgs: [
{
typeUrl: "/cosmos.bank.v1beta1.MsgSend" ,
value: cosmos . bank . v1beta1 . MsgSend . encode ( innerSend ). finish (),
},
],
}),
};
await signingClient . signAndBroadcast ( granteeAddress , [ execMsg ], "auto" );
For an IBC transfer, replace the inner message with ibc.applications.transfer.v1.MsgTransfer.
Revoke an authorization
const revokeMsg = {
typeUrl: "/cosmos.authz.v1beta1.MsgRevoke" ,
value: cosmos . authz . v1beta1 . MsgRevoke . fromPartial ({
granter: granterAddress ,
grantee: granteeAddress ,
msgTypeUrl: "/cosmos.bank.v1beta1.MsgSend" ,
}),
};
Grant a fee allowance
const basicAllowance = cosmos . feegrant . v1beta1 . BasicAllowance . fromPartial ({
spendLimit: [{ denom: "uixo" , amount: "500000" }],
});
const grantAllowanceMsg = {
typeUrl: "/cosmos.feegrant.v1beta1.MsgGrantAllowance" ,
value: cosmos . feegrant . v1beta1 . MsgGrantAllowance . fromPartial ({
granter: granterAddress ,
grantee: granteeAddress ,
allowance: {
typeUrl: "/cosmos.feegrant.v1beta1.BasicAllowance" ,
value: cosmos . feegrant . v1beta1 . BasicAllowance . encode ( basicAllowance ). finish (),
},
}),
};
Revoke a fee allowance
const revokeAllowanceMsg = {
typeUrl: "/cosmos.feegrant.v1beta1.MsgRevokeAllowance" ,
value: cosmos . feegrant . v1beta1 . MsgRevokeAllowance . fromPartial ({
granter: granterAddress ,
grantee: granteeAddress ,
}),
};
The grantee then sets the granter’s address as the feePayer in the transaction’s fee object — the granter is debited instead of the grantee.
Verify the result
Query active grants through the gRPC gateway API :
cosmos.authz.v1beta1.Query/Grants — grants between a granter and grantee
cosmos.authz.v1beta1.Query/GranterGrants — all grants issued by a granter
cosmos.authz.v1beta1.Query/GranteeGrants — all grants received by a grantee
cosmos.feegrant.v1beta1.Query/Allowance — fee allowance status
Troubleshooting
invalid authorization parameters
Confirm bech32 addresses are valid for the chain prefix (ixo), the denom is supported, and the amount is within spend_limit.
Confirm the grant has not expired, the grantee’s transaction message URL exactly matches the authorization’s allowed type, and the spend limit has not been exhausted.
Ensure the granter has sufficient balance for the allowance, the allowance type matches the use case (BasicAllowance vs PeriodicAllowance vs AllowedMsgAllowance), and the transaction’s feePayer is set to the granter.
Use AllowedMsgAllowance to combine fee payment with a strict whitelist of message URLs the grantee may submit at the granter’s expense.
Next steps
Custom authorizations Use IXO-specific authz types for entities, claims, and tokens.
Smart accounts Add programmable authenticators on top of authz.
Cosmos authz module Full reference for x/authz.
Cosmos feegrant module Full reference for x/feegrant.