Intent Execution
An intent is a directed acyclic graph (DAG) of steps. Each step is an action with optional dependencies on other steps. txfence validates the graph, evaluates each step against policy, and executes them in topological order — handling partial failures, poisoned downstream steps, and timeout enforcement.
Intent structure
import type { Intent, IntentStep } from '@txfence/core'
const intent: Intent = {
id: 'treasury-rebalance-001',
steps: [
{
id: 'withdraw',
action: {
kind: 'transfer',
chain: 'ethereum',
token: { token: 'USDC', amount: 10000n * 10n**6n, decimals: 6 },
to: '0xINTERMEDIARY',
},
},
{
id: 'swap',
dependsOn: ['withdraw'], // runs after withdraw succeeds
action: {
kind: 'swap',
chain: 'ethereum',
from: { token: 'USDC', amount: 10000n * 10n**6n, decimals: 6 }, // source TokenAmount
to: 'ETH', // destination token symbol
via: '0xE592427A0AEce92De3Edee1F18E0157C05861564', // router address (Uniswap V3)
maxSlippage: 50,
},
},
],
intentPolicy: { // field is `intentPolicy`, not `policy`
maxTotalGrossSpend: { token: 'USDC', amount: 20000n * 10n**6n, decimals: 6 },
maxSteps: 5,
requireAllSteps: false,
maxDurationMs: 60000,
allowedChains: ['ethereum'],
},
}Executing an intent
const result = await agent.executeIntent(intent, {
dryRun: false,
})
console.log(result.status) // 'completed' | 'partial' | 'failed' | 'rejected'
console.log(result.receipts) // Map<stepId, SuccessReceipt>validateIntentGraph
Validate graph structure before execution:
import { validateIntentGraph } from '@txfence/core'
const validation = validateIntentGraph(intent)
if (!validation.valid) {
console.error(validation.errors)
// 'cycle_detected' | 'duplicate_step_id' | 'missing_dependency'
}
console.log(validation.executionPlan) // topologically sorted step IDsPartial failure handling
When requireAllSteps: false, a failed step poisons only its downstream dependents — other branches continue executing.
import { getPoisonedSteps } from '@txfence/core'
const poisoned = getPoisonedSteps('withdraw', intent.steps)
// returns all steps transitively dependent on 'withdraw'When requireAllSteps: true, any step failure aborts the entire intent.
Position analysis
Before execution, you can inspect what an intent will spend, hold intermediately, and net out to. The pipeline runs this analysis automatically — these helpers expose it for custom tooling.
import {
analyzeIntentPosition,
getActionPositionChanges,
mergePositionChanges,
isSingleTokenIntent,
getDominantToken,
} from '@txfence/core'
const plan = validateIntentGraph(intent).executionPlan
const analysis = analyzeIntentPosition(intent.steps, plan)
console.log(analysis.totalGrossOutflow) // total outflow across all steps
console.log(analysis.netChange) // PositionChange[] — net delta per token
console.log(analysis.maxIntermediateExposure) // peak exposure during execution
console.log(analysis.isSingleToken) // true when all steps use one token
console.log(analysis.dominantToken) // the dominant token symbol, if any
// Per-action position deltas — useful when building bespoke evaluators
getActionPositionChanges(action)
mergePositionChanges([{ token: 'USDC', amount: 100n, chain: 'ethereum' }, ...])
isSingleTokenIntent(intent.steps)
getDominantToken(intent.steps)maxTotalGrossSpend and maxNetSpend enforcement uses isSingleTokenIntent internally — multi-token intents skip those checks until a price oracle is added in v2.
IntentPolicy constraints
interface IntentPolicy {
maxTotalGrossSpend?: TokenAmount // total outflow cap (single-token only in v1)
maxNetSpend?: TokenAmount // net position change cap
maxIntermediateExposure?: TokenAmount // max exposure at any point during execution
maxSteps?: number
requireAllSteps?: boolean
maxDurationMs?: number // timeout — remaining steps marked 'abandoned'
allowedChains?: ChainId[]
}CLI
# Validate graph structure
txfence intent validate --intent ./intent.json --config ./txfence.config.ts
# Dry run
txfence intent submit --intent ./intent.json --config ./txfence.config.ts --dry-run
# Execute
txfence intent submit --intent ./intent.json --config ./txfence.config.ts --executeExits 0 on completed, 2 on partial, 1 on failed/rejected.
Multi-token spend constraints require a price oracle — maxTotalGrossSpend and maxNetSpend are only enforced for single-token intents in v1. Swap inflows (received token amounts) are unknown at evaluation time — position analysis tracks outflows only.