This repository was archived by the owner on Jan 14, 2026. It is now read-only.
feat: add middleware system for custom asset support#19
Merged
Conversation
Add plugin architecture to support assets with special transfer requirements (taxes, freeze/unfreeze, smart contract interactions) without modifying core SDK. **Core Changes:** - Add `SwapMiddleware` interface with hooks: - `shouldApply()`: Conditional middleware activation - `adjustQuoteParams()`: Pre-quote parameter adjustments (maxGroupSize, amount) - `beforeSwap()`: Inject transactions before swap - `afterSwap()`: Inject transactions after swap - Add `SwapContext` interface providing quote, address, algodClient, suggestedParams, asset IDs, and signer - Update `DeflexClient` to accept middleware array and apply transformations in `newQuote()` - Update `SwapComposer` to execute middleware hooks during `addSwapTransactions()` **Tests:** - Interface validation and structure tests - Quote parameter adjustment tests (single and chained middleware) - Conditional application via `shouldApply()` - All 121 tests passing Enables external packages for special asset integrations (e.g., First Stage, custom tokenomics) with zero SDK bloat.
Add comprehensive documentation for the middleware system: **MIDDLEWARE.md:** - Complete developer guide for creating middleware packages - Interface documentation with detailed examples - Step-by-step creation guide (setup, implementation, caching, error handling) - Publishing guidelines (package.json, README template) - Critical best practices: - Always adjust maxGroupSize when adding transactions - Disable SDK opt-ins when middleware adds its own - Minimize transactions, cache queries, handle errors gracefully - Complete First Stage example implementation (190 lines) **README.md:** - Add middleware usage section with example - Document middleware config option in API reference table - Link to MIDDLEWARE.md guide Enables developers to create external packages for special asset support (First Stage, custom tokenomics) without SDK modifications.
Replace `main` and `types` fields with modern `exports` field for consistency with ESM-only packages. This follows the same pattern used by the Deflex SDK and provides better control over the package's public API.
Update middleware interface to use `bigint` for asset IDs instead of `number`, aligning with algosdk v3's precision-focused approach and future- proofing for asset IDs that may exceed JavaScript's max safe integer. **Changes:** - `SwapMiddleware.shouldApply()`: Asset ID params changed from `number` to `bigint` - `SwapContext`: Asset ID properties changed from `number` to `bigint` - `DeflexClient.newQuote()`: Changed from `Number()` to `BigInt()` coercion when calling middleware - `SwapComposer`: Changed from passing raw IDs to `BigInt()` coercion in all middleware hook calls - Updated MIDDLEWARE.md documentation with bigint types - Updated First Stage example to use bigint throughout - Updated tests to use bigint literals (`12345n`) **Benefits:** - Consistent with algosdk v3's bigint philosophy - Safer precision handling for large asset IDs - Future-proof: asset IDs are based on creation round and will eventually exceed 2^53 - 1 - Simpler mental model: middleware always receives bigints All 121 tests passing. TypeCheck passing.
Update all middleware documentation examples to consistently use `bigint` for asset IDs and `number | bigint` for app IDs, aligning with the middleware interface changes. **Changes:** - Updated `SwapMiddleware` interface example to show `bigint` params - Updated `CustomAssetMiddleware` implementation examples with `bigint` asset IDs - Updated `FirstStageMiddleware` example with `bigint` asset IDs - Changed `contractAppId` to `number | bigint` (user-facing API flexibility) - Updated caching examples to use `Map<bigint, T>` - Updated all usage examples to show both number and bigint literal options **Rationale:** - **Middleware interface** (internal): `bigint` only for predictable, consistent behavior - **Middleware config** (external): `number | bigint` for developer convenience - Follows same pattern as algosdk transaction functions - App IDs and asset IDs are generated identically and should be treated the same All documentation now accurately reflects the bigint-first approach while maintaining flexibility for developers using middleware packages.
Eliminate duplicate execution of afterSwap hooks and add early validation checkpoint for beforeSwap transactions to fail fast. **Performance improvements:** - Execute `afterSwap` hooks once instead of twice (was called in `getAfterSwapCount()` then again to add transactions) - Removed `getAfterSwapCount()` method entirely - Avoids duplicate network requests if middleware queries contracts in afterSwap hooks **Enhanced validation:** - Added early validation after `beforeSwap` hooks execute - Catches group size overflow before processing swap transactions or calling afterSwap - Accounts for edge case where developers manually add transactions before `addSwapTransactions()` - Provides clearer error messages distinguishing beforeSwap overflow vs total overflow **New execution flow:** 1. Execute `beforeSwap` → validate group size → add to ATC 2. Process swap txns + execute `afterSwap` → validate final group size → add all to ATC All 121 tests passing.
github-actions bot
added a commit
that referenced
this pull request
Nov 6, 2025
# [1.3.0](v1.2.0...v1.3.0) (2025-11-06) ### Features * add middleware system for custom asset support ([#19](#19)) ([f75963c](f75963c))
Contributor
|
🎉 This PR is included in version 1.3.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a middleware/plugin system to the Deflex SDK for supporting Algorand assets with special transfer requirements (taxes, freeze/unfreeze, smart contract interactions, custom tokenomics) without modifying the core SDK.
This enables external developers to create standalone middleware packages for special asset integrations (e.g., First Stage, custom tokenomics systems) that work seamlessly with the SDK.
Changes
Core Implementation
SwapMiddlewareinterface with hooks:shouldApply(): Conditional middleware activation per swapadjustQuoteParams(): Pre-quote parameter adjustments (maxGroupSize,amount)beforeSwap(): Inject transactions before swap transactionsafterSwap(): Inject transactions after swap transactionsSwapContextinterface providing quote, address, algodClient, suggestedParams, asset IDs, and signerDeflexClientto accept middleware array and apply transformations innewQuote()SwapComposerto execute middleware hooks duringaddSwapTransactions()Documentation
Tests
shouldApply()Use Cases
Example Usage
Benefits
✅ Zero SDK bloat: Middleware is opt-in, external packages don't affect bundle size
✅ Composable: Multiple middleware can be chained together
✅ Community-driven: Developers can create and publish their own integrations
✅ Type-safe: Full TypeScript support with exported interfaces
✅ Well-documented: Complete guide with real-world examples
Breaking Changes
None - this is a purely additive feature with backward compatibility.