The IXO Protocol bonds module provides universal token bonding-curve functions to mint, burn, swap, and settle bonds. Bonds price their tokens via a bonding curve (function_type and function_parameters), accept one or more reserve_tokens, and pass through a lifecycle of HATCH → OPEN → SETTLE (or FAILED). Alpha bonds add risk-adjustment via the oracle_did-controlled MsgSetNextAlpha.
Before you start
You need:
- An IXO account with sufficient
uixofor fees on the network you target — see Networks and endpoints. - An offline signer — see the SDK README on creating signers.
- For
MsgCreateBond: a controller DID, a creator DID, optional oracle DID for alpha bonds, and reserve token denoms. - For
MsgWithdrawReserve: the bond'sallow_reserve_withdrawalsflag must betrue.
npm install @ixo/impactxclient-sdkimport { ixo, createSigningClient } from "@ixo/impactxclient-sdk";
const signingClient = await createSigningClient(RPC_ENDPOINT, offlineSigner);Create a bond
const createBondMsg = {
typeUrl: "/ixo.bonds.v1beta1.MsgCreateBond",
value: ixo.bonds.v1beta1.MsgCreateBond.fromPartial({
bondDid: "did:ixo:bond:abc123",
token: "BOND",
name: "Solar Farm Alpha Bond",
description: "Outcome-linked bond for verified solar production",
functionType: "augmented_function",
functionParameters: [
ixo.bonds.v1beta1.FunctionParam.fromPartial({ param: "p0", value: "1" }),
],
creatorDid: "did:ixo:creator123",
controllerDid: "did:ixo:controller123",
oracleDid: "did:ixo:oracle123",
reserveTokens: ["uixo"],
txFeePercentage: "0.5",
exitFeePercentage: "1.0",
feeAddress: feeAddress,
reserveWithdrawalAddress: reserveAddress,
maxSupply: { denom: "BOND", amount: "1000000" },
orderQuantityLimits: [],
sanityRate: "0",
sanityMarginPercentage: "0",
allowSells: true,
allowReserveWithdrawals: false,
alphaBond: true,
batchBlocks: "1",
outcomePayment: "0",
creatorAddress: signerAddress,
}),
};
await signingClient.signAndBroadcast(signerAddress, [createBondMsg], "auto");Edit, set alpha, transition state
const editMsg = {
typeUrl: "/ixo.bonds.v1beta1.MsgEditBond",
value: ixo.bonds.v1beta1.MsgEditBond.fromPartial({
bondDid: "did:ixo:bond:abc123",
name: "Solar Farm Alpha Bond v2",
description: "Updated description",
orderQuantityLimits: "",
sanityRate: "",
sanityMarginPercentage: "",
editorDid: "did:ixo:editor123",
editorAddress: signerAddress,
}),
};
const setAlphaMsg = {
typeUrl: "/ixo.bonds.v1beta1.MsgSetNextAlpha",
value: ixo.bonds.v1beta1.MsgSetNextAlpha.fromPartial({
bondDid: "did:ixo:bond:abc123",
alpha: "0.85",
delta: "0.05",
oracleDid: "did:ixo:oracle123",
oracleAddress: oracleSignerAddress,
}),
};
const updateStateMsg = {
typeUrl: "/ixo.bonds.v1beta1.MsgUpdateBondState",
value: ixo.bonds.v1beta1.MsgUpdateBondState.fromPartial({
bondDid: "did:ixo:bond:abc123",
state: "OPEN",
editorDid: "did:ixo:editor123",
editorAddress: signerAddress,
}),
};Bond states are: HATCH (initial fundraising), OPEN (active trading), SETTLE (settlement), FAILED.
Buy, sell, swap
const buyMsg = {
typeUrl: "/ixo.bonds.v1beta1.MsgBuy",
value: ixo.bonds.v1beta1.MsgBuy.fromPartial({
buyerDid: "did:ixo:buyer123",
amount: { denom: "BOND", amount: "1000000" },
maxPrices: [{ denom: "uixo", amount: "100" }],
bondDid: "did:ixo:bond:abc123",
buyerAddress: signerAddress,
}),
};
const sellMsg = {
typeUrl: "/ixo.bonds.v1beta1.MsgSell",
value: ixo.bonds.v1beta1.MsgSell.fromPartial({
sellerDid: "did:ixo:seller123",
amount: { denom: "BOND", amount: "1000000" },
bondDid: "did:ixo:bond:abc123",
sellerAddress: signerAddress,
}),
};
const swapMsg = {
typeUrl: "/ixo.bonds.v1beta1.MsgSwap",
value: ixo.bonds.v1beta1.MsgSwap.fromPartial({
swapperDid: "did:ixo:swapper123",
bondDid: "did:ixo:bond:abc123",
from: { denom: "uixo", amount: "1000" },
toToken: "uatom",
swapperAddress: signerAddress,
}),
};Outcome payments and withdrawals
const outcomePayMsg = {
typeUrl: "/ixo.bonds.v1beta1.MsgMakeOutcomePayment",
value: ixo.bonds.v1beta1.MsgMakeOutcomePayment.fromPartial({
senderDid: "did:ixo:funder123",
amount: "1000000",
bondDid: "did:ixo:bond:abc123",
senderAddress: signerAddress,
}),
};
const withdrawShareMsg = {
typeUrl: "/ixo.bonds.v1beta1.MsgWithdrawShare",
value: ixo.bonds.v1beta1.MsgWithdrawShare.fromPartial({
recipientDid: "did:ixo:holder123",
bondDid: "did:ixo:bond:abc123",
recipientAddress: signerAddress,
}),
};
const withdrawReserveMsg = {
typeUrl: "/ixo.bonds.v1beta1.MsgWithdrawReserve",
value: ixo.bonds.v1beta1.MsgWithdrawReserve.fromPartial({
withdrawerDid: "did:ixo:treasury123",
amount: [{ denom: "uixo", amount: "500000" }],
bondDid: "did:ixo:bond:abc123",
withdrawerAddress: signerAddress,
}),
};Verify the result
Query bond state through the Blocksync GraphQL API or ixo.bonds.v1beta1 query endpoints on the gRPC gateway API.
Troubleshooting
invalid function type or parameters
function_type must be one of the supported curve types (power_function, sigmoid_function, swapper_function, augmented_function). Each requires a specific set of function_parameters — see the bonds proto.
state transition rejected
State transitions are constrained by the bond's lifecycle. HATCH → OPEN requires the hatch threshold to be met. OPEN → SETTLE is typically called once the outcome obligation is met or the bond expires.
reserve withdrawal not allowed
MsgWithdrawReserve fails when allow_reserve_withdrawals is false on MsgCreateBond. This flag is immutable.