Router Actions
Actions are the building blocks of Vif transactions. The vifdk provides type-safe methods for all available router actions.
Market Orders
orderSingle()
Execute a single market order (swap).
.orderSingle({
market: SemiMarket,
fillVolume: TokenAmount,
maxTick?: Tick,
maxOffers?: bigint,
fillWants?: boolean
})market: The semi-market to trade on (asks or bids)fillVolume: Amount to trademaxTick: Maximum acceptable tick (price limit). Defaults to no limitmaxOffers: Maximum offers to consume. Defaults to 100fillWants: If true,fillVolumeis output; if false, it's input. Defaults to false
// Buy WETH with 1000 USDC
router.createTypedActions()
.orderSingle({
market: market.asks,
fillVolume: USDC.amount('1000'), // Spend 1000 USDC (input)
maxTick: market.asks.price(4000), // Don't pay more than $4000/WETH
maxOffers: 50n
})Returns: OrderResult with gave, got, fee, bounty
orderMulti()
Execute a multi-hop market order (exact input only).
.orderMulti({
markets: SemiMarket[],
fillVolume: TokenAmount,
maxTicks?: Tick[],
maxOffers?: bigint[]
})markets: Array of semi-markets to hop throughfillVolume: Input amount (first market's inbound token)maxTicks: Price limits for each marketmaxOffers: Offer limits for each market
// USDC → WETH → DAI
router.createTypedActions()
.orderMulti({
markets: [market1.asks, market2.asks],
fillVolume: USDC.amount('1000'),
maxTicks: [
market1.asks.price(4000),
market2.asks.price(4100)
],
maxOffers: [50n, 50n]
})Returns: MultiOrderResult[] - One result per market hop
Limit Orders
limitSingle()
Create or edit a limit order.
.limitSingle({
market: SemiMarket,
gives: TokenAmount,
tick: Tick,
initialOfferId?: number,
expiry?: Date,
provision?: TokenAmount
})market: The semi-market to place the offer ongives: Amount to offertick: Price levelinitialOfferId: 0 or undefined for new, existing ID to editexpiry: Optional expiration dateprovision: Native token provision (required if expiry is set)
// Sell 1 WETH at 3500 USDC/WETH
router.createTypedActions()
.limitSingle({
market: market.asks,
gives: WETH.amount('1'),
tick: market.asks.price(3500),
expiry: new Date(Date.now() + 86400000), // 24 hours
provision: Token.PROVISION_TOKEN.amount('0.001')
})Returns: LimitOrderResult with offerId, claimedReceived
claim()
Claim filled amounts from an offer.
.claim({
market: SemiMarket,
offerId: number
})router.createTypedActions()
.claim({
market: market.asks,
offerId: 42
})Returns: ClaimCancelResult with inbound, outbound, provision
cancel()
Cancel an offer and claim all remaining balances.
.cancel({
market: SemiMarket,
offerId: number
})router.createTypedActions()
.cancel({
market: market.asks,
offerId: 42
})Returns: ClaimCancelResult with inbound, outbound, provision
Settlement Actions
settleAll()
Settle all debt for a token.
.settleAll(token: Token)router.createTypedActions()
.orderSingle({ /* ... */ })
.settleAll(USDC) // Pay USDC debtsettle()
Settle a specific amount of debt.
.settle({
token: Token,
amount: TokenAmount
}).settle({
token: USDC,
amount: USDC.amount('1000')
})takeAll()
Take all credit for a token.
.takeAll({
token: Token,
receiver: Address
})router.createTypedActions()
.orderSingle({ /* ... */ })
.settleAll(USDC)
.takeAll({
token: WETH,
receiver: walletAddress
})take()
Take a specific amount of credit.
.take({
token: Token,
amount: TokenAmount,
receiver: Address
})Utility Actions
wrapNative()
Wrap native token (ETH → WETH).
.wrapNative(amount: TokenAmount)router.createTypedActions()
.wrapNative(Token.NATIVE_TOKEN.amount('1'))
.limitSingle({ /* use wrapped ETH */ })unwrapNative()
Unwrap native token (WETH → ETH).
.unwrapNative({
amount: TokenAmount,
receiver: Address
})sweep()
Send all tokens from router to receiver.
.sweep({
token: Token,
receiver: Address
})router.createTypedActions()
.limitSingle({ /* ... */ })
.settleAll(WETH)
.sweep({
token: Token.NATIVE_TOKEN,
receiver: walletAddress
})authorize()
Authorize an operator via the router.
.authorize({
authorized: Address,
isAuthorized: boolean
})clearAllUpto()
Clear dust credit up to a maximum amount.
.clearAllUpto({
token: Token,
maxAmount: TokenAmount
})Action Ordering
Actions are automatically ordered when calling .build():
- Operations (orders, limits, claims, cancels)
- Settlements (settle, settleAll)
- Takes (take, takeAll)
- Utilities (sweep, wrap, unwrap)
This ensures proper execution order for flash accounting.
Failable Actions
Actions can be marked as failable to prevent transaction reversion:
import { toFailableAction, Action } from 'vifdk'
router.createActions()
.add(Action.ORDER_SINGLE, params) // Reverts if fails
.add(toFailableAction(Action.ORDER_SINGLE), params) // Continues if fails
.build()Check if an action is failable:
import { isFailableAction } from 'vifdk'
if (isFailableAction(action)) {
// Handle failable action
}Action Results
OrderResult
{
gave: TokenAmount // Amount paid
got: TokenAmount // Amount received
fee: TokenAmount // Fee paid
bounty: TokenAmount // Bounty earned
}LimitOrderResult
{
offerId: number // Created/updated offer ID
claimedReceived: TokenAmount // Claimed from previous fills
}ClaimCancelResult
{
inbound: TokenAmount // Filled amount
outbound: TokenAmount // Remaining/returned amount
provision: TokenAmount // Provision returned
}Common Patterns
Simple Swap
router.createTypedActions()
.orderSingle({
market: market.asks,
fillVolume: USDC.amount('1000')
})
.settleAll(USDC)
.takeAll({ token: WETH, receiver })
.build()Swap with Price Limit
router.createTypedActions()
.orderSingle({
market: market.asks,
fillVolume: USDC.amount('1000'),
maxTick: market.asks.price(4000) // Max $4000/WETH
})
.settleAll(USDC)
.takeAll({ token: WETH, receiver })
.build()Place Limit Order with Provision
router.createTypedActions()
.wrapNative(Token.NATIVE_TOKEN.amount('0.1')) // For provision
.limitSingle({
market: market.asks,
gives: WETH.amount('1'),
tick: market.asks.price(3500),
expiry: new Date(Date.now() + 86400000),
provision: Token.PROVISION_TOKEN.amount('0.001')
})
.settleAll(Token.NATIVE_TOKEN) // Pay provision
.settleAll(WETH) // Pay WETH
.sweep({ token: Token.NATIVE_TOKEN, receiver }) // Return extra
.build()Update and Claim Limit Order
router.createTypedActions()
.limitSingle({
market: market.asks,
initialOfferId: 42, // Edit existing
gives: WETH.amount('2'), // Update amount
tick: market.asks.price(3600) // Update price
})
.settleAll(WETH) // Pay additional WETH
.takeAll({ token: USDC, receiver }) // Claim filled USDC
.build()Multi-Hop Swap
router.createTypedActions()
.orderMulti({
markets: [
wethUsdcMarket.asks, // WETH → USDC
usdcDaiMarket.asks // USDC → DAI
],
fillVolume: WETH.amount('1')
})
.settleAll(WETH)
.takeAll({ token: DAI, receiver })
.build()
// USDC is never transferred! Netted by flash accountingBatch Multiple Limit Orders
router.createTypedActions()
.limitSingle({
market: market.asks,
gives: WETH.amount('1'),
tick: market.asks.price(3500)
})
.limitSingle({
market: market.asks,
gives: WETH.amount('1'),
tick: market.asks.price(3600)
})
.limitSingle({
market: market.asks,
gives: WETH.amount('1'),
tick: market.asks.price(3700)
})
.settleAll(WETH) // Settle once for all three
.build()Related Documentation
- VifRouter - Router class documentation
- Core Classes - Token, Market, etc.
- Using VifRouter - Contract-level actions
- Flash Accounting - Understanding debts/credits