Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

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
})
Parameters:
  • market: The semi-market to trade on (asks or bids)
  • fillVolume: Amount to trade
  • maxTick: Maximum acceptable tick (price limit). Defaults to no limit
  • maxOffers: Maximum offers to consume. Defaults to 100
  • fillWants: If true, fillVolume is output; if false, it's input. Defaults to false
Example:
// 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[]
})
Parameters:
  • markets: Array of semi-markets to hop through
  • fillVolume: Input amount (first market's inbound token)
  • maxTicks: Price limits for each market
  • maxOffers: Offer limits for each market
Example:
// 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
})
Parameters:
  • market: The semi-market to place the offer on
  • gives: Amount to offer
  • tick: Price level
  • initialOfferId: 0 or undefined for new, existing ID to edit
  • expiry: Optional expiration date
  • provision: Native token provision (required if expiry is set)
Example:
// 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
})
Example:
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
})
Example:
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)
Example:
router.createTypedActions()
  .orderSingle({ /* ... */ })
  .settleAll(USDC)  // Pay USDC debt

settle()

Settle a specific amount of debt.

.settle({
  token: Token,
  amount: TokenAmount
})
Example:
.settle({
  token: USDC,
  amount: USDC.amount('1000')
})

takeAll()

Take all credit for a token.

.takeAll({
  token: Token,
  receiver: Address
})
Example:
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)
Example:
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
})
Example:
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():

  1. Operations (orders, limits, claims, cancels)
  2. Settlements (settle, settleAll)
  3. Takes (take, takeAll)
  4. 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 accounting

Batch 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