Skip to main content

Estimate the right fee

OmbraChain uses fee markets for both TRANSFER and TASK_SUBMIT. Set fee too low → tx sits in mempool. Set it too high → wasted OMBRA.

TRANSFER fee

There's no hard minimum. The proposer keeps the entire fee. Defaults that work:

Network stateFee
Quiet (mempool < 10 pending)1_000 micro (0.001 OMBRA)
Normal5_000 micro
Busy (mempool > 100 pending)20_000 micro

Query fee estimate:

curl https://api.ombra-net.com/api/chain/fee-estimate
{ "low": "1000", "medium": "5000", "high": "20000", "sample": 100 }

Each value is the 25th / 50th / 90th percentile of fees in the recent 100 transactions.

TASK_SUBMIT fee

Higher fee → more attractive to miners → faster response. Minimum: MIN_TASK_FEE = 10_000.

Task typeRecommended feeReasoning
chat (short)10_000 - 50_000Fast LLM call, miners abundant
chat (long, > 2K tokens output)100_000 - 500_000Higher per-token cost
code_simple50_000 - 200_000Modest inference
code_agentic500_000 - 2_000_000Long, GPU-heavy
image200_000 - 1_000_000Stable Diffusion costs
audio50_000 - 200_000TTS is cheap
embedding10_000Single forward pass
nft_svg200_000 - 1_000_000Quality SVG generation

Dynamic fee picker

import { OmbraClient } from "@ombrachain/sdk";
const client = new OmbraClient({ endpoint: "https://api.ombra-net.com" });

async function pickFee(taskType: string, priority: "low" | "medium" | "high"): Promise<bigint> {
const est = await client.chain.getFeeEstimate();
const base = BigInt(est[priority]);

// Task-type multiplier (cheap LLM calls don't need huge fees)
const mult: Record<string, bigint> = {
chat: 1n,
code_simple: 5n,
code_agentic: 50n,
image: 30n,
audio: 5n,
embedding: 1n,
nft_svg: 30n,
};
const m = mult[taskType] ?? 5n;

const result = base * m;
const min = 10_000n; // MIN_TASK_FEE
return result < min ? min : result;
}

const fee = await pickFee("chat", "medium");
console.log("recommended fee:", fee, "micro-OMBRA");

Watching mempool

A more reactive picker watches mempool size:

async function feeForCurrentLoad(): Promise<bigint> {
const { total } = await fetch("https://api.ombra-net.com/api/mempool/").then(r => r.json());
if (total < 10) return 1_000n;
if (total < 50) return 5_000n;
if (total < 200) return 20_000n;
return 50_000n; // very busy
}

Refund if tx never includes

If your TRANSFER tx sits in mempool > 10 blocks (~2.5 min), it's likely under-priced. Options:

  1. Re-submit with higher fee — keeps the same nonce. The new tx replaces the old in mempool.
  2. Wait — mempool will eventually clear and your tx will be included.
  3. Cancel — submit a 0-amount TRANSFER to yourself at the same nonce with higher fee. This consumes the nonce.
// Replace stuck tx with higher fee
const replacementTx = buildTransferTx(
wallet.address, originalRecipient,
originalAmount,
20_000n, // bumped fee
originalNonce, // same nonce — replaces old tx
wallet.privateKey,
);
await client.chain.submitTx(replacementTx);

The mempool uses highest-fee-wins for txs with same (from, nonce).