New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@txnlab/deflex

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@txnlab/deflex

DEPRECATED: This package has been renamed to @txnlab/haystack-router. TypeScript/JavaScript SDK for Deflex Order Router - smart order routing and DEX aggregation on Algorand

latest
Source
npmnpm
Version
1.9.0
Version published
Maintainers
1
Created
Source

⚠️ DEPRECATED - This package has been renamed

This package has been renamed to @txnlab/haystack-router and will no longer receive updates.

Please migrate to the new package:

npm uninstall @txnlab/deflex
npm install @txnlab/haystack-router

See the migration guide for details.

Deflex SDK

npm version bundle size CI License: MIT TypeScript

TypeScript/JavaScript SDK for Deflex Order Router - smart order routing and DEX aggregation on Algorand.

Prerequisites

  • Deflex API Key - Request an API key by emailing support@txnlab.dev
  • algosdk 3.0.0 or later

Installation

npm install @txnlab/deflex algosdk

Note: algosdk is a peer dependency and must be installed alongside @txnlab/deflex.

Quick Start

import { DeflexClient } from '@txnlab/deflex'
import { useWallet } from '@txnlab/use-wallet-*' // react, vue, solid, or svelte

const { activeAddress, transactionSigner } = useWallet()

// Initialize the client
const deflex = new DeflexClient({
  apiKey: 'your-api-key',
})

// Get a quote
const quote = await deflex.newQuote({
  address: activeAddress,
  fromAssetId: 0, // ALGO
  toAssetId: 31566704, // USDC
  amount: 1_000_000, // 1 ALGO (in microAlgos)
})

// Execute the swap
const swap = await deflex.newSwap({
  quote,
  address: activeAddress,
  signer: transactionSigner,
  slippage: 1, // 1% slippage tolerance
})
const result = await swap.execute()

console.log(`Swap completed in round ${result.confirmedRound}`)

Usage

Initialize the Client

import { DeflexClient } from '@txnlab/deflex'

// Basic initialization
const deflex = new DeflexClient({
  apiKey: 'your-api-key',
})

// Custom Algod configuration
const deflex = new DeflexClient({
  apiKey: 'your-api-key',
  algodUri: 'https://mainnet-api.4160.nodely.dev/',
  algodToken: '',
  algodPort: 443,
  autoOptIn: true, // Automatically handle asset opt-ins
})

// Earn fees with the referral program
const deflex = new DeflexClient({
  apiKey: 'your-api-key',
  referrerAddress: 'YOUR_ALGORAND_ADDRESS', // Earns 25% of swap fees
  feeBps: 15, // 0.15% fee (max: 300 = 3%)
})

By providing your Algorand address as the referrerAddress when initializing the client, you can earn 25% of the swap fees generated through your integration. Set the feeBps parameter to specify the total fee charged to users (default: 0.15%, max: 3.00%). Learn more about the Deflex Referral Program.

Get a Swap Quote

The newQuote() method returns a DeflexQuote object:

// Basic quote
const quote = await deflex.newQuote({
  fromASAID: 0, // ALGO
  toASAID: 31566704, // USDC
  amount: 1_000_000, // 1 ALGO
  address: userAddress, // Required for auto opt-in detection
})

Execute a Swap

The newSwap() method returns a SwapComposer instance:

import { useWallet } from '@txnlab/use-wallet-*' // react, vue, solid, or svelte

const { activeAddress, transactionSigner } = useWallet()

const swap = await deflex.newSwap({
  quote,
  address: activeAddress,
  signer: transactionSigner,
  slippage: 1, // 1% slippage tolerance
})
const result = await swap.execute()

console.log(`Confirmed in round ${result.confirmedRound}`)
console.log('Transaction IDs:', result.txIds)

Transaction Tracking

Add a custom note to the input transaction for tracking purposes, and retrieve its transaction ID after execution:

const swap = await deflex.newSwap({
  quote,
  address: activeAddress,
  signer: transactionSigner,
  slippage: 1,
  note: new TextEncoder().encode('tracking-id-123'), // Custom note for tracking
})

const result = await swap.execute()

// Get the transaction ID of the user-signed input transaction
const inputTxId = swap.getInputTransactionId()
console.log('Input transaction ID:', inputTxId)

The note is applied only to the user-signed payment or asset transfer transaction (not pre-signed or middleware transactions). The transaction ID is available after calling buildGroup(), sign(), or execute().

Transaction Signing

The SDK supports both standard algosdk.TransactionSigner and ARC-1 compliant signer functions.

Use the @txnlab/use-wallet library for wallet management in your dApp:

import { useWallet } from '@txnlab/use-wallet-*' // react, vue, solid, or svelte

const { activeAddress, transactionSigner } = useWallet()

const swap = await deflex.newSwap({
  quote,
  address: activeAddress,
  signer: transactionSigner,
  slippage: 1,
})
await swap.execute()

Tip: The @txnlab/use-wallet library supports multiple wallet providers (Pera, Defly, Lute, WalletConnect, etc.) and provides a unified interface. Choose the framework-specific adapter for your project: @txnlab/use-wallet-react, @txnlab/use-wallet-vue, @txnlab/use-wallet-solid, or @txnlab/use-wallet-svelte.

2. Custom Signer Function

The SDK accepts custom signer functions that receive the complete transaction group and an array of indexes indicating which transactions need signing:

import { Address, encodeUnsignedTransaction, type Transaction } from 'algosdk'

// Example: Wrapping an ARC-1 compliant wallet
const customSigner = async (
  txnGroup: Transaction[],
  indexesToSign: number[],
) => {
  // Convert to wallet's expected format
  const walletTxns = txnGroup.map((txn, index) => ({
    txn: Buffer.from(encodeUnsignedTransaction(txn)).toString('base64'),
    signers: indexesToSign.includes(index)
      ? [Address.fromString(activeAddress)]
      : [],
  }))

  // Sign with wallet provider
  const signedTxns = await walletProvider.signTxns(walletTxns)

  return signedTxns
}

const swap = await deflex.newSwap({
  quote,
  address: activeAddress,
  signer: customSigner,
  slippage: 1,
})
await swap.execute()

The signer function supports two return patterns:

  • Pattern 1 (Pera, Defly, algosdk): Returns only the signed transactions as Uint8Array[]
  • Pattern 2 (Lute, ARC-1 compliant): Returns an array matching the transaction group length with null for unsigned transactions as (Uint8Array | null)[]

Both patterns are automatically handled by the SDK.

Advanced Transaction Composition

Build the transaction group by adding custom transactions and ABI method calls before or after the swap using the SwapComposer instance:

import { ABIMethod, Transaction } from 'algosdk'
import { useWallet } from '@txnlab/use-wallet-*' // react, vue, solid, or svelte

const { activeAddress, transactionSigner } = useWallet()

// Create your custom transactions
const customTxn = new Transaction({...})

// Define an ABI method call
const methodCall = {
  appID: 123456,
  method: new ABIMethod({...}),
  methodArgs: [...],
  sender: activeAddress,
  suggestedParams: await algodClient.getTransactionParams().do(),
}

// Build and execute the transaction group
const swap = await deflex.newSwap({
  quote,
  address: activeAddress,
  signer: transactionSigner,
  slippage: 1,
})

const result = await swap
  .addTransaction(customTxn)      // Add transaction before swap
  .addSwapTransactions()          // Add swap transactions
  .addMethodCall(methodCall)      // Add ABI method call after swap
  .execute()                      // Sign and execute entire group

Middleware for Custom Asset Requirements

Some Algorand assets require additional transactions to be added to swap groups (e.g., assets with transfer restrictions, taxes, or custom smart contract logic). The Deflex SDK supports a middleware system that allows these special requirements to be handled by external packages without modifying the core SDK.

Middleware can:

  • Adjust quote parameters (e.g., reduce maxGroupSize to account for extra transactions)
  • Add transactions before the swap (e.g., unfreeze account, setup calls)
  • Add transactions after the swap (e.g., tax payments, cleanup calls)
import { DeflexClient } from '@txnlab/deflex'
import { FirstStageMiddleware } from '@firststage/deflex-middleware' // Example external package

// Initialize middleware
const firstStage = new FirstStageMiddleware({
  contractAppId: 123456,
})

// Pass middleware to DeflexClient
const deflex = new DeflexClient({
  apiKey: 'your-api-key',
  middleware: [firstStage], // Middleware is applied automatically
})

// Use normally - middleware handles everything
const quote = await deflex.newQuote({
  fromASAID: 0,        // ALGO
  toASAID: 789012,     // Custom asset (e.g., MOOJ, DEAL)
  amount: 1_000_000,
  address: userAddress,
})

const swap = await deflex.newSwap({ quote, address, signer, slippage: 1 })
await swap.execute() // Middleware transactions are automatically included

Built-in Middleware

The SDK includes AutoOptOutMiddleware, which automatically opts out of assets when swapping your full balance, cleaning up zero balance assets and reducing minimum balance requirements:

import { DeflexClient, AutoOptOutMiddleware } from '@txnlab/deflex'

const autoOptOut = new AutoOptOutMiddleware({
  excludedAssets: [31566704], // Optional: exclude specific assets like USDC
})

const deflex = new DeflexClient({
  apiKey: 'your-api-key',
  middleware: [autoOptOut],
})

// When swapping full balance, opt-out transaction is automatically added
const quote = await deflex.newQuote({
  fromASAID: someAssetId,
  toASAID: 0,
  amount: fullBalance, // If this matches your full balance, asset will be opted out
  address: userAddress,
})

For details on creating your own middleware, see MIDDLEWARE.md.

Manual Asset Opt-In Detection

If you're not using autoOptIn: true, you can manually check if opt-in is needed:

const deflex = new DeflexClient({
  apiKey: 'your-api-key',
  autoOptIn: false, // Default if not provided
})

// Check if user needs to opt into the output asset
const needsOptIn = await deflex.needsAssetOptIn(userAddress, toAssetId)

// Include opt-in in quote if needed
const quote = await deflex.newQuote({
  fromAssetId,
  toAssetId,
  amount,
  optIn: needsOptIn,
})

Error Handling

import { useWallet } from '@txnlab/use-wallet-*' // react, vue, solid, or svelte

const { activeAddress, transactionSigner } = useWallet()

try {
  const quote = await deflex.newQuote({
    fromAssetId: 0,
    toAssetId: 31566704,
    amount: 1_000_000,
    address: activeAddress,
  })

  const swap = await deflex.newSwap({
    quote,
    address: activeAddress,
    signer: transactionSigner,
    slippage: 1,
  })
  const result = await swap.execute()

  console.log('Swap successful:', result)
} catch (error) {
  console.error('Swap failed:', error.message)
}

API Reference

DeflexClient

The main client for interacting with the Deflex API.

new DeflexClient(config: DeflexConfigParams)
OptionDescriptionTypeDefault
apiKeyYour Deflex API keystringrequired
apiBaseUrlBase URL for the Deflex APIstringhttps://deflex.txnlab.dev
algodUriAlgod node URIstringhttps://mainnet-api.4160.nodely.dev/
algodTokenAlgod node tokenstring''
algodPortAlgod node portstring | number443
referrerAddressReferrer address for fee sharing (receives 25% of swap fees)stringundefined
feeBpsFee in basis points (0.15%, max: 300 = 3.00%)number15
autoOptInAuto-detect and add required opt-in transactionsbooleanfalse
middlewareArray of middleware for custom asset requirementsSwapMiddleware[][]

Referral Program: By providing a referrerAddress, you can earn 25% of the swap fees generated through your integration. The feeBps parameter sets the total fee charged (default: 0.15%). Learn more about the Deflex Referral Program.

DeflexClient.newQuote()

Fetch a swap quote and return a DeflexQuote object.

async newQuote(params: FetchQuoteParams): Promise<DeflexQuote>
ParameterDescriptionTypeDefault
fromASAIDInput asset IDbigint | numberrequired
toASAIDOutput asset IDbigint | numberrequired
amountAmount to swap in base unitsbigint | numberrequired
typeQuote type'fixed-input' | 'fixed-output''fixed-input'
addressUser address (recommended for auto opt-in)stringundefined
disabledProtocolsArray of protocols to excludeProtocol[][]
maxGroupSizeMaximum transactions in atomic groupnumber16
maxDepthMaximum swap hopsnumber4
optInOverride auto opt-in behaviorbooleanundefined

DeflexClient.newSwap()

Returns a SwapComposer instance for building and executing swaps.

async newSwap(config: SwapComposerConfig): Promise<SwapComposer>
ParameterDescriptionType
quoteQuote result or raw API responseDeflexQuote | FetchQuoteResponse
addressSigner addressstring
slippageSlippage tolerance as percentage (e.g., 1 for 1%)number
signerTransaction signer functionalgosdk.TransactionSigner | ((txnGroup: Transaction[], indexesToSign: number[]) => Promise<(Uint8Array | null)[]>)
noteOptional note for the user-signed input transaction (for tracking purposes)Uint8Array

DeflexClient.needsAssetOptIn()

Checks if an address needs to opt into an asset.

async needsAssetOptIn(address: string, assetId: bigint | number): Promise<boolean>
ParameterDescriptionType
addressAlgorand address to checkstring
assetIdAsset ID to checkbigint | number

DeflexQuote

Plain object returned by newQuote(). Extends the raw API response with additional metadata.

Additional properties added by SDK:

PropertyDescriptionType
quoteQuoted amount (coerced to bigint)bigint
amountOriginal request amountbigint
addressUser address (if provided)string | undefined
createdAtTimestamp when quote was creatednumber

All properties from API response:

PropertyDescriptionType
fromASAIDInput asset IDnumber
toASAIDOutput asset IDnumber
typeQuote type ('fixed-input' or 'fixed-output')string
profitProfit informationProfit
priceBaselineBaseline price without feesnumber
userPriceImpactPrice impact for the usernumber | undefined
marketPriceImpactOverall market price impactnumber | undefined
usdInUSD value of inputnumber
usdOutUSD value of outputnumber
routeRouting path informationRoute[]
flattenedRouteFlattened routing percentagesRecord<string, number>
quotesIndividual DEX quotesDexQuote[]
requiredAppOptInsRequired app opt-insnumber[]
txnPayloadEncrypted transaction payloadTxnPayload | null
protocolFeesFees by protocolRecord<string, number>
timingPerformance timing dataunknown | undefined

SwapComposer

Builder for constructing and executing atomic swap transaction groups, returned by newSwap().

MethodDescriptionParametersReturns
addTransaction(transaction, signer?)Add a transaction to the atomic grouptransaction: algosdk.Transaction, signer?: TransactionSignerSwapComposer
addMethodCall(methodCall, signer?)Add an ABI method call to the atomic groupmethodCall: MethodCall, signer?: TransactionSignerSwapComposer
addSwapTransactions()Add swap transactions to the group (includes required app opt-ins)NonePromise<SwapComposer>
buildGroup()Build the transaction group and assign group IDsNoneTransactionWithSigner[]
sign()Sign the transaction groupNonePromise<Uint8Array[]>
submit()Sign and submit the transaction groupNonePromise<string[]> (transaction IDs)
execute(waitRounds?)Sign, submit, and wait for confirmationwaitRounds?: number (default: 4)Promise<{ confirmedRound: bigint, txIds: string[], methodResults: ABIResult[] }>
getStatus()Get current status: BUILDING, BUILT, SIGNED, SUBMITTED, or COMMITTEDNoneSwapComposerStatus
count()Get the number of transactions in the groupNonenumber
getInputTransactionId()Get the transaction ID of the user-signed input transaction (available after buildGroup(), sign(), or execute())Nonestring | undefined

Documentation

For more information about the Deflex Order Router protocol, visit the official documentation.

License

MIT

Support

Keywords

algorand

FAQs

Package last updated on 14 Jan 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts