Publishing Anchor Metadata
By AnchorFactory ·
For your anchor to be discoverable by wallets and applications, you need to publish service metadata on-chain. This metadata tells the resolver where your anchor lives, what it supports, and how to interact with it.
How Discovery Works
Your Anchor Account
→ publishes metadata via SET_INFO block
→ metadata stored on your account's chain
Resolver
→ reads metadata from known anchor accounts
→ returns matching services when queried
Wallet / dApp
→ queries resolver: "find FX anchors supporting KTA/USDC"
→ gets your endpoint URL + capabilities
→ calls your API directlyMetadata Format
Anchor metadata is a JSON object stored as a base64-encoded string in the account's metadata field via a SET_INFO operation.
FX Anchor Example
{
"version": 1,
"currencyMap": {
"$KTA": "keeta_anqdilpazdekdu4acw65fj7smltcp26wbrildkqtszqvverljpwpezmd44ssg",
"$USDC": "keeta_amnkge74xitii5dsobstldatv3irmyimujfjotftx7plaaaseam4bntb7wnna"
},
"services": {
"fx": {
"myExchange": {
"from": [
{ "asset": "$KTA", "network": "chain:keeta:21378" },
{ "asset": "$USDC", "network": "chain:keeta:21378" }
],
"operations": ["getEstimate", "createExchange", "getExchangeStatus"]
}
}
}
}Fields
Field | Required | Description |
|---|---|---|
| Yes | Schema version (currently |
| Yes | Shorthand symbol → full token address mapping |
| Yes | Service category → anchor definitions |
| No | Child resolver public keys (for scaling) |
Service Categories
Category | Key | Typical Operations |
|---|---|---|
FX |
|
|
KYC |
|
|
Asset Movement |
|
|
Banking |
|
|
Username |
|
|
Storage |
|
|
Notification |
|
|
Publishing Metadata On-Chain
Step 1: Build the Metadata
const KeetaNet = require("@keetanetwork/keetanet-client");
const metadata = {
version: 1,
currencyMap: {
"$KTA": "keeta_anqdilpazdekdu4acw65fj7smltcp26wbrildkqtszqvverljpwpezmd44ssg",
"$USDC": "keeta_amnkge74xitii5dsobstldatv3irmyimujfjotftx7plaaaseam4bntb7wnna",
},
services: {
fx: {
myExchange: {
from: [
{ asset: "$KTA", network: "chain:keeta:21378" },
{ asset: "$USDC", network: "chain:keeta:21378" },
],
operations: ["getEstimate", "createExchange", "getExchangeStatus"],
},
},
},
};
const metadataBase64 = btoa(JSON.stringify(metadata));Step 2: Publish a SET_INFO Block
const seed = Buffer.from(process.env.SEED, "hex");
const account = KeetaNet.lib.Account.fromSeed(seed, 0);
const client = await KeetaNet.UserClient.fromNetwork("main", null, { account });
// Get current chain head
const state = await client.getAccountState(account);
const head = state.head; // previous block hash
// Build SET_INFO block
const builder = new KeetaNet.lib.Block.Builder();
builder.account = account;
builder.previous = head || KeetaNet.lib.Block.NO_PREVIOUS;
builder.network = 0x5382; // mainnet
builder.addOperation({
type: KeetaNet.lib.Block.Operation.SET_INFO,
name: "My FX Anchor",
description: "Currency exchange service for KTA and USDC",
metadata: metadataBase64,
});
const block = await builder.seal();
// Publish (requires fee block)
await client.publish([block], {
generateFeeBlock: async (staple) => {
return feeBuilder.computeFeeBlock(staple);
},
});
console.log("Metadata published! Block hash:", block.hash);Step 3: Verify Discovery
const { Resolver } = await import("@keetanetwork/anchor/lib/resolver");
const resolver = new Resolver({
root: resolverAccount,
client: client,
});
// Look up your anchor
const fxServices = await resolver.lookup("fx", {
inputCurrency: "$KTA",
outputCurrency: "$USDC",
});
console.log("Found services:", fxServices);Updating Metadata
To update your metadata, publish a new SET_INFO block with the updated JSON. The latest block's metadata replaces the previous one.
// Change supported pairs, update endpoints, etc.
metadata.services.fx.myExchange.from.push(
{ asset: "$EURC", network: "chain:keeta:21378" }
);
// Publish new SET_INFO block (same flow as above)Metadata Size Limits
On-chain metadata is limited to approximately 5400 characters of compressed JSON. If your anchor supports many pairs (>60 pools), you'll need to split across multiple resolver accounts.
Multi-Resolver Pattern
{
"version": 1,
"currencyMap": { ... },
"services": {
"fx": {
"topPool1": { ... },
"topPool2": { ... }
}
},
"resolvers": [
"keeta_child_resolver_1...",
"keeta_child_resolver_2..."
]
}Master resolver: top pools by market cap + references to child resolvers
Child resolvers: ~60 pools each, assigned by creation time
The resolver SDK follows
resolversreferences automatically
Master Metadata Endpoint
The current live metadata for all registered anchors is available at:
https://static.network.keeta.com/metadata/servicesStudy this to see the exact format used by production anchors.
Next Steps
Build an FX Anchor — build the service that this metadata points to
Metadata Schema — full schema reference
Live Anchors — see what production anchors publish