@txnlab/deflex 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -223,6 +223,69 @@ const result = await swap
223
223
  .execute() // Sign and execute entire group
224
224
  ```
225
225
 
226
+ ### Middleware for Custom Asset Requirements
227
+
228
+ 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.
229
+
230
+ Middleware can:
231
+ - Adjust quote parameters (e.g., reduce `maxGroupSize` to account for extra transactions)
232
+ - Add transactions before the swap (e.g., unfreeze account, setup calls)
233
+ - Add transactions after the swap (e.g., tax payments, cleanup calls)
234
+
235
+ ```typescript
236
+ import { DeflexClient } from '@txnlab/deflex'
237
+ import { FirstStageMiddleware } from '@firststage/deflex-middleware' // Example external package
238
+
239
+ // Initialize middleware
240
+ const firstStage = new FirstStageMiddleware({
241
+ contractAppId: 123456,
242
+ })
243
+
244
+ // Pass middleware to DeflexClient
245
+ const deflex = new DeflexClient({
246
+ apiKey: 'your-api-key',
247
+ middleware: [firstStage], // Middleware is applied automatically
248
+ })
249
+
250
+ // Use normally - middleware handles everything
251
+ const quote = await deflex.newQuote({
252
+ fromASAID: 0, // ALGO
253
+ toASAID: 789012, // Custom asset (e.g., MOOJ, DEAL)
254
+ amount: 1_000_000,
255
+ address: userAddress,
256
+ })
257
+
258
+ const swap = await deflex.newSwap({ quote, address, signer, slippage: 1 })
259
+ await swap.execute() // Middleware transactions are automatically included
260
+ ```
261
+
262
+ #### Built-in Middleware
263
+
264
+ 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:
265
+
266
+ ```typescript
267
+ import { DeflexClient, AutoOptOutMiddleware } from '@txnlab/deflex'
268
+
269
+ const autoOptOut = new AutoOptOutMiddleware({
270
+ excludedAssets: [31566704], // Optional: exclude specific assets like USDC
271
+ })
272
+
273
+ const deflex = new DeflexClient({
274
+ apiKey: 'your-api-key',
275
+ middleware: [autoOptOut],
276
+ })
277
+
278
+ // When swapping full balance, opt-out transaction is automatically added
279
+ const quote = await deflex.newQuote({
280
+ fromASAID: someAssetId,
281
+ toASAID: 0,
282
+ amount: fullBalance, // If this matches your full balance, asset will be opted out
283
+ address: userAddress,
284
+ })
285
+ ```
286
+
287
+ For details on creating your own middleware, see [MIDDLEWARE.md](MIDDLEWARE.md).
288
+
226
289
  ### Manual Asset Opt-In Detection
227
290
 
228
291
  If you're not using `autoOptIn: true`, you can manually check if opt-in is needed:
@@ -284,16 +347,17 @@ The main client for interacting with the Deflex API.
284
347
  new DeflexClient(config: DeflexConfigParams)
285
348
  ```
286
349
 
287
- | Option | Description | Type | Default |
288
- | ----------------- | ------------------------------------------------------------ | ------------------ | -------------------------------------- |
289
- | `apiKey` | Your Deflex API key | `string` | **required** |
290
- | `apiBaseUrl` | Base URL for the Deflex API | `string` | `https://deflex.txnlab.dev` |
291
- | `algodUri` | Algod node URI | `string` | `https://mainnet-api.4160.nodely.dev/` |
292
- | `algodToken` | Algod node token | `string` | `''` |
293
- | `algodPort` | Algod node port | `string \| number` | `443` |
294
- | `referrerAddress` | Referrer address for fee sharing (receives 25% of swap fees) | `string` | `undefined` |
295
- | `feeBps` | Fee in basis points (0.15%, max: 300 = 3.00%) | `number` | `15` |
296
- | `autoOptIn` | Auto-detect and add required opt-in transactions | `boolean` | `false` |
350
+ | Option | Description | Type | Default |
351
+ | ----------------- | ------------------------------------------------------------ | --------------------- | -------------------------------------- |
352
+ | `apiKey` | Your Deflex API key | `string` | **required** |
353
+ | `apiBaseUrl` | Base URL for the Deflex API | `string` | `https://deflex.txnlab.dev` |
354
+ | `algodUri` | Algod node URI | `string` | `https://mainnet-api.4160.nodely.dev/` |
355
+ | `algodToken` | Algod node token | `string` | `''` |
356
+ | `algodPort` | Algod node port | `string \| number` | `443` |
357
+ | `referrerAddress` | Referrer address for fee sharing (receives 25% of swap fees) | `string` | `undefined` |
358
+ | `feeBps` | Fee in basis points (0.15%, max: 300 = 3.00%) | `number` | `15` |
359
+ | `autoOptIn` | Auto-detect and add required opt-in transactions | `boolean` | `false` |
360
+ | `middleware` | Array of middleware for custom asset requirements | `SwapMiddleware[]` | `[]` |
297
361
 
298
362
  > **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](https://txnlab.gitbook.io/deflex-api/referral-treasury/referral-program).
299
363
 
package/dist/index.d.ts CHANGED
@@ -342,6 +342,270 @@ interface MethodCall {
342
342
  signer?: TransactionSigner;
343
343
  }
344
344
  //#endregion
345
+ //#region src/middleware.d.ts
346
+ /**
347
+ * Context provided to middleware shouldApply hook
348
+ */
349
+ interface QuoteContext {
350
+ /** Input asset ID (always bigint for precision and future-proofing) */
351
+ readonly fromASAID: bigint;
352
+ /** Output asset ID (always bigint for precision and future-proofing) */
353
+ readonly toASAID: bigint;
354
+ /** Amount to swap (always bigint for precision and future-proofing) */
355
+ readonly amount: bigint;
356
+ /** Quote type */
357
+ readonly type: QuoteType;
358
+ /** Address of the account that will perform the swap (if provided) */
359
+ readonly address?: string;
360
+ /** Algodv2 client instance for making additional queries */
361
+ readonly algodClient: Algodv2;
362
+ }
363
+ /**
364
+ * Context provided to middleware hooks during swap composition
365
+ */
366
+ interface SwapContext {
367
+ /** The quote result from newQuote() */
368
+ readonly quote: DeflexQuote;
369
+ /** The address of the account performing the swap */
370
+ readonly address: string;
371
+ /** Algodv2 client instance for making additional queries/transactions */
372
+ readonly algodClient: Algodv2;
373
+ /** Suggested transaction parameters from the network */
374
+ readonly suggestedParams: SuggestedParams;
375
+ /** Input asset ID (always bigint for precision and future-proofing) */
376
+ readonly fromASAID: bigint;
377
+ /** Output asset ID (always bigint for precision and future-proofing) */
378
+ readonly toASAID: bigint;
379
+ /** Transaction signer for transactions that need to be signed by the user */
380
+ readonly signer: TransactionSigner;
381
+ }
382
+ /**
383
+ * Middleware interface for extending Deflex swap functionality
384
+ *
385
+ * Middleware allows you to modify quote parameters and inject additional transactions
386
+ * into the atomic swap group. This is useful for assets that require special handling,
387
+ * such as those with transfer restrictions, taxes, or custom smart contract logic.
388
+ *
389
+ * @example
390
+ * ```typescript
391
+ * class CustomAssetMiddleware implements SwapMiddleware {
392
+ * readonly name = 'CustomAsset'
393
+ * readonly version = '1.0.0'
394
+ *
395
+ * async shouldApply(context) {
396
+ * return context.fromASAID === CUSTOM_ASSET_ID || context.toASAID === CUSTOM_ASSET_ID
397
+ * }
398
+ *
399
+ * async adjustQuoteParams(params) {
400
+ * // Reduce maxGroupSize to account for extra transactions
401
+ * return { ...params, maxGroupSize: params.maxGroupSize - 3 }
402
+ * }
403
+ *
404
+ * async beforeSwap(context) {
405
+ * // Return transactions to add before the swap
406
+ * return [unfreezeTransaction]
407
+ * }
408
+ *
409
+ * async afterSwap(context) {
410
+ * // Return transactions to add after the swap
411
+ * return [taxTransaction, refreezeTransaction]
412
+ * }
413
+ * }
414
+ * ```
415
+ */
416
+ interface SwapMiddleware {
417
+ /** Unique identifier for the middleware */
418
+ readonly name: string;
419
+ /** Semantic version of the middleware */
420
+ readonly version: string;
421
+ /**
422
+ * Determines if this middleware should be applied to the given swap
423
+ *
424
+ * Called during both quote and swap phases. Use this to check if either
425
+ * the input or output asset requires special handling.
426
+ *
427
+ * @param context - Quote context with asset IDs, amount, type, address, and algod client
428
+ * @returns True if middleware should be applied
429
+ *
430
+ * @example
431
+ * ```typescript
432
+ * async shouldApply(context) {
433
+ * // Check if asset is registered in our smart contract
434
+ * const assetInfo = await this.getAssetInfo(context.fromASAID)
435
+ * return assetInfo !== null
436
+ * }
437
+ * ```
438
+ */
439
+ shouldApply(context: QuoteContext): Promise<boolean>;
440
+ /**
441
+ * Modify quote parameters before fetching the quote
442
+ *
443
+ * **IMPORTANT**: If your middleware adds transactions via `beforeSwap` or `afterSwap`,
444
+ * you MUST reduce `maxGroupSize` accordingly to prevent failures. The Deflex API may
445
+ * return routes that use all 16 available transaction slots.
446
+ *
447
+ * Use this to adjust the quote request based on your asset's requirements.
448
+ * Common adjustments include:
449
+ * - Reducing `maxGroupSize` to account for additional transactions (REQUIRED if adding txns)
450
+ * - Adjusting `amount` to account for fees/taxes
451
+ * - Modifying `disabledProtocols` if certain DEXs are incompatible
452
+ *
453
+ * @param params - Original quote parameters
454
+ * @returns Modified quote parameters
455
+ *
456
+ * @example
457
+ * ```typescript
458
+ * async adjustQuoteParams(params) {
459
+ * const [fromTaxed, toTaxed] = await Promise.all([
460
+ * this.isAssetTaxed(params.fromASAID),
461
+ * this.isAssetTaxed(params.toASAID),
462
+ * ])
463
+ *
464
+ * // 3 extra transactions per taxed asset
465
+ * let maxGroupSize = params.maxGroupSize ?? 16
466
+ * if (fromTaxed) maxGroupSize -= 3
467
+ * if (toTaxed) maxGroupSize -= 3
468
+ *
469
+ * // Adjust amount for input tax
470
+ * let amount = params.amount
471
+ * if (fromTaxed) {
472
+ * const taxRate = await this.getTaxRate(params.fromASAID)
473
+ * amount = this.applyTax(amount, taxRate)
474
+ * }
475
+ *
476
+ * return { ...params, maxGroupSize, amount }
477
+ * }
478
+ * ```
479
+ */
480
+ adjustQuoteParams?(params: FetchQuoteParams): Promise<FetchQuoteParams>;
481
+ /**
482
+ * Add transactions before the swap transactions
483
+ *
484
+ * Called when building the swap transaction group. Transactions are added
485
+ * to the group in the order they appear in the returned array.
486
+ *
487
+ * Transaction order in final group: [beforeSwap] → [swap txns] → [afterSwap]
488
+ *
489
+ * @param context - Swap context with quote, address, and algod client
490
+ * @returns Array of transactions with signers to add before swap
491
+ *
492
+ * @example
493
+ * ```typescript
494
+ * async beforeSwap(context) {
495
+ * const txns: TransactionWithSigner[] = []
496
+ *
497
+ * // Unfreeze user account before swap
498
+ * if (await this.needsUnfreeze(context.fromASAID)) {
499
+ * const unfreezeCall = makeApplicationNoOpTxn(
500
+ * context.address,
501
+ * this.appId,
502
+ * ...,
503
+ * context.suggestedParams
504
+ * )
505
+ *
506
+ * txns.push({
507
+ * txn: unfreezeCall,
508
+ * signer: context.signer, // Use the signer from context
509
+ * })
510
+ * }
511
+ *
512
+ * return txns
513
+ * }
514
+ * ```
515
+ */
516
+ beforeSwap?(context: SwapContext): Promise<TransactionWithSigner[]>;
517
+ /**
518
+ * Add transactions after the swap transactions
519
+ *
520
+ * Called when building the swap transaction group. Transactions are added
521
+ * to the group in the order they appear in the returned array.
522
+ *
523
+ * Transaction order in final group: [beforeSwap] → [swap txns] → [afterSwap]
524
+ *
525
+ * @param context - Swap context with quote, address, and algod client
526
+ * @returns Array of transactions with signers to add after swap
527
+ *
528
+ * @example
529
+ * ```typescript
530
+ * async afterSwap(context) {
531
+ * const txns: TransactionWithSigner[] = []
532
+ *
533
+ * // Pay tax and refreeze account
534
+ * if (await this.isTaxed(context.fromASAID)) {
535
+ * const taxAmount = await this.calculateTax(context)
536
+ * const taxPayment = makeAssetTransferTxn(
537
+ * context.address,
538
+ * this.taxReceiver,
539
+ * taxAmount,
540
+ * context.fromASAID,
541
+ * context.suggestedParams
542
+ * )
543
+ * const refreezeCall = makeApplicationNoOpTxn(
544
+ * context.address,
545
+ * this.appId,
546
+ * ...,
547
+ * context.suggestedParams
548
+ * )
549
+ *
550
+ * txns.push(
551
+ * { txn: taxPayment, signer: context.signer },
552
+ * { txn: refreezeCall, signer: context.signer },
553
+ * )
554
+ * }
555
+ *
556
+ * return txns
557
+ * }
558
+ * ```
559
+ */
560
+ afterSwap?(context: SwapContext): Promise<TransactionWithSigner[]>;
561
+ }
562
+ /**
563
+ * Configuration options for AutoOptOutMiddleware
564
+ */
565
+ interface AutoOptOutConfig {
566
+ /**
567
+ * Array of asset IDs that should be excluded from automatic opt-out behavior
568
+ * @default []
569
+ */
570
+ readonly excludedAssets?: readonly (number | bigint)[];
571
+ }
572
+ /**
573
+ * Middleware that automatically adds an asset opt-out transaction when swapping
574
+ * the full balance of an input asset, leaving it with a zero balance.
575
+ *
576
+ * @example
577
+ * ```typescript
578
+ * import { DeflexClient, AutoOptOutMiddleware } from '@txnlab/deflex'
579
+ *
580
+ * const autoOptOut = new AutoOptOutMiddleware({
581
+ * excludedAssets: [31566704], // Don't auto-opt-out of USDC
582
+ * })
583
+ *
584
+ * const deflex = new DeflexClient({
585
+ * apiKey: 'your-api-key',
586
+ * middleware: [autoOptOut],
587
+ * })
588
+ *
589
+ * // When swapping full balance, opt-out transaction is automatically added
590
+ * const quote = await deflex.newQuote({
591
+ * address: userAddress,
592
+ * fromASAID: someAssetId,
593
+ * toASAID: 0,
594
+ * amount: fullBalance, // If this equals account's full balance, opt-out is added
595
+ * type: 'fixed-input',
596
+ * })
597
+ * ```
598
+ */
599
+ declare class AutoOptOutMiddleware implements SwapMiddleware {
600
+ readonly name = "AutoOptOut";
601
+ readonly version = "1.0.0";
602
+ private readonly excludedAssets;
603
+ constructor(config?: AutoOptOutConfig);
604
+ shouldApply(context: QuoteContext): Promise<boolean>;
605
+ adjustQuoteParams(params: FetchQuoteParams): Promise<FetchQuoteParams>;
606
+ afterSwap(context: SwapContext): Promise<TransactionWithSigner[]>;
607
+ }
608
+ //#endregion
345
609
  //#region src/composer.d.ts
346
610
  /**
347
611
  * A transaction signer function that supports both standard algosdk.TransactionSigner
@@ -381,6 +645,8 @@ interface SwapComposerConfig {
381
645
  readonly address: string;
382
646
  /** Transaction signer function */
383
647
  readonly signer: TransactionSigner | SignerFunction;
648
+ /** Middleware to apply during swap composition */
649
+ readonly middleware?: SwapMiddleware[];
384
650
  }
385
651
  /**
386
652
  * Composer for building and executing atomic swap transaction groups
@@ -407,11 +673,13 @@ declare class SwapComposer {
407
673
  static MAX_GROUP_SIZE: number;
408
674
  /** Whether the swap transactions have been added to the atomic group. */
409
675
  private swapTransactionsAdded;
676
+ private readonly quote;
410
677
  private readonly requiredAppOptIns;
411
678
  private readonly deflexTxns;
412
679
  private readonly algodClient;
413
680
  private readonly address;
414
681
  private readonly signer;
682
+ private readonly middleware;
415
683
  /**
416
684
  * Create a new SwapComposer instance
417
685
  *
@@ -419,11 +687,12 @@ declare class SwapComposer {
419
687
  * this directly, as the factory method handles fetching swap transactions automatically.
420
688
  *
421
689
  * @param config - Configuration for the composer
422
- * @param config.requiredAppOptIns - The quote response from fetchQuote()
690
+ * @param config.quote - The quote response from fetchQuote()
423
691
  * @param config.deflexTxns - The swap transactions from fetchSwapTransactions()
424
692
  * @param config.algodClient - Algodv2 client instance
425
693
  * @param config.address - The address of the account that will sign transactions
426
694
  * @param config.signer - Transaction signer function
695
+ * @param config.middleware - Middleware to apply during swap composition
427
696
  */
428
697
  constructor(config: SwapComposerConfig);
429
698
  /**
@@ -470,8 +739,13 @@ declare class SwapComposer {
470
739
  /**
471
740
  * Add swap transactions to the atomic group
472
741
  *
473
- * This method automatically processes required app opt-ins and adds all swap
474
- * transactions from the quote. Can only be called once per composer instance.
742
+ * This method automatically processes required app opt-ins, executes middleware hooks,
743
+ * and adds all swap transactions from the quote. Can only be called once per composer instance.
744
+ *
745
+ * Middleware hooks are executed in this order:
746
+ * 1. beforeSwap() - Add transactions before swap transactions
747
+ * 2. Swap transactions (from API)
748
+ * 3. afterSwap() - Add transactions after swap transactions
475
749
  *
476
750
  * @returns This composer instance for chaining
477
751
  * @throws Error if the swap transactions have already been added
@@ -580,6 +854,10 @@ declare class SwapComposer {
580
854
  * Re-signs a Deflex transaction using the provided logic signature or secret key
581
855
  */
582
856
  private signDeflexTransaction;
857
+ /**
858
+ * Execute middleware hooks (beforeSwap or afterSwap)
859
+ */
860
+ private executeMiddlewareHooks;
583
861
  }
584
862
  //#endregion
585
863
  //#region src/client.d.ts
@@ -614,6 +892,7 @@ declare class SwapComposer {
614
892
  declare class DeflexClient {
615
893
  private readonly config;
616
894
  private readonly algodClient;
895
+ private readonly middleware;
617
896
  /**
618
897
  * Create a new DeflexClient instance
619
898
  *
@@ -626,8 +905,11 @@ declare class DeflexClient {
626
905
  * @param config.referrerAddress - Referrer address for fee sharing (receives 25% of swap fees)
627
906
  * @param config.feeBps - Fee in basis points (default: 15 = 0.15%, max: 300 = 3.00%)
628
907
  * @param config.autoOptIn - Automatically detect and add required opt-in transactions (default: false)
908
+ * @param config.middleware - Array of middleware to apply to swaps (default: [])
629
909
  */
630
- constructor(config: DeflexConfigParams);
910
+ constructor(config: DeflexConfigParams & {
911
+ middleware?: SwapMiddleware[];
912
+ });
631
913
  /**
632
914
  * Fetch a swap quote from the Deflex API
633
915
  *
@@ -827,5 +1109,5 @@ declare class HTTPError extends Error {
827
1109
  */
828
1110
  declare function request<T>(url: string, options?: RequestInit): Promise<T>;
829
1111
  //#endregion
830
- export { Asset, DEFAULT_ALGOD_PORT, DEFAULT_ALGOD_TOKEN, DEFAULT_ALGOD_URI, DEFAULT_API_BASE_URL, DEFAULT_AUTO_OPT_IN, DEFAULT_CONFIRMATION_ROUNDS, DEFAULT_FEE_BPS, DEFAULT_MAX_DEPTH, DEFAULT_MAX_GROUP_SIZE, DEPRECATED_PROTOCOLS, DeflexClient, DeflexConfig, DeflexConfigParams, DeflexQuote, DeflexSignature, DeflexTransaction, DexQuote, FetchQuoteParams, FetchQuoteResponse, FetchSwapTxnsBody, FetchSwapTxnsParams, FetchSwapTxnsResponse, HTTPError, MAX_FEE_BPS, MethodCall, PathElement, Profit, Protocol, QuoteType, Route, SignerFunction, SwapComposer, SwapComposerConfig, SwapComposerStatus, SwapTransaction, TxnPayload, request };
1112
+ export { Asset, AutoOptOutConfig, AutoOptOutMiddleware, DEFAULT_ALGOD_PORT, DEFAULT_ALGOD_TOKEN, DEFAULT_ALGOD_URI, DEFAULT_API_BASE_URL, DEFAULT_AUTO_OPT_IN, DEFAULT_CONFIRMATION_ROUNDS, DEFAULT_FEE_BPS, DEFAULT_MAX_DEPTH, DEFAULT_MAX_GROUP_SIZE, DEPRECATED_PROTOCOLS, DeflexClient, DeflexConfig, DeflexConfigParams, DeflexQuote, DeflexSignature, DeflexTransaction, DexQuote, FetchQuoteParams, FetchQuoteResponse, FetchSwapTxnsBody, FetchSwapTxnsParams, FetchSwapTxnsResponse, HTTPError, MAX_FEE_BPS, MethodCall, PathElement, Profit, Protocol, QuoteContext, QuoteType, Route, SignerFunction, SwapComposer, SwapComposerConfig, SwapComposerStatus, SwapContext, SwapMiddleware, SwapTransaction, TxnPayload, request };
831
1113
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/constants.ts","../src/types.ts","../src/composer.ts","../src/client.ts","../src/utils.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/constants.ts","../src/types.ts","../src/middleware.ts","../src/composer.ts","../src/client.ts","../src/utils.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Algodv2, AtomicTransactionComposer, LogicSigAccount, Transaction, decodeUnsignedTransaction, isValidAddress, makeApplicationOptInTxnFromObject, msgpackRawDecode, signLogicSigTransactionObject, signTransaction } from "algosdk";
1
+ import { Algodv2, AtomicTransactionComposer, LogicSigAccount, Transaction, decodeUnsignedTransaction, isValidAddress, makeApplicationOptInTxnFromObject, makeAssetTransferTxnWithSuggestedParamsFromObject, msgpackRawDecode, signLogicSigTransactionObject, signTransaction } from "algosdk";
2
2
 
3
3
  //#region src/constants.ts
4
4
  /**
@@ -83,11 +83,13 @@ var SwapComposer = class SwapComposer {
83
83
  static MAX_GROUP_SIZE = AtomicTransactionComposer.MAX_GROUP_SIZE;
84
84
  /** Whether the swap transactions have been added to the atomic group. */
85
85
  swapTransactionsAdded = false;
86
+ quote;
86
87
  requiredAppOptIns;
87
88
  deflexTxns;
88
89
  algodClient;
89
90
  address;
90
91
  signer;
92
+ middleware;
91
93
  /**
92
94
  * Create a new SwapComposer instance
93
95
  *
@@ -95,11 +97,12 @@ var SwapComposer = class SwapComposer {
95
97
  * this directly, as the factory method handles fetching swap transactions automatically.
96
98
  *
97
99
  * @param config - Configuration for the composer
98
- * @param config.requiredAppOptIns - The quote response from fetchQuote()
100
+ * @param config.quote - The quote response from fetchQuote()
99
101
  * @param config.deflexTxns - The swap transactions from fetchSwapTransactions()
100
102
  * @param config.algodClient - Algodv2 client instance
101
103
  * @param config.address - The address of the account that will sign transactions
102
104
  * @param config.signer - Transaction signer function
105
+ * @param config.middleware - Middleware to apply during swap composition
103
106
  */
104
107
  constructor(config) {
105
108
  if (!config.quote) throw new Error("Quote is required");
@@ -107,11 +110,13 @@ var SwapComposer = class SwapComposer {
107
110
  if (config.deflexTxns.length === 0) throw new Error("Swap transactions array cannot be empty");
108
111
  if (!config.algodClient) throw new Error("Algodv2 client instance is required");
109
112
  if (!config.signer) throw new Error("Signer is required");
113
+ this.quote = config.quote;
110
114
  this.requiredAppOptIns = config.quote.requiredAppOptIns;
111
115
  this.deflexTxns = config.deflexTxns;
112
116
  this.algodClient = config.algodClient;
113
117
  this.address = this.validateAddress(config.address);
114
118
  this.signer = config.signer;
119
+ this.middleware = config.middleware ?? [];
115
120
  }
116
121
  /**
117
122
  * Get the status of this composer's transaction group
@@ -173,8 +178,13 @@ var SwapComposer = class SwapComposer {
173
178
  /**
174
179
  * Add swap transactions to the atomic group
175
180
  *
176
- * This method automatically processes required app opt-ins and adds all swap
177
- * transactions from the quote. Can only be called once per composer instance.
181
+ * This method automatically processes required app opt-ins, executes middleware hooks,
182
+ * and adds all swap transactions from the quote. Can only be called once per composer instance.
183
+ *
184
+ * Middleware hooks are executed in this order:
185
+ * 1. beforeSwap() - Add transactions before swap transactions
186
+ * 2. Swap transactions (from API)
187
+ * 3. afterSwap() - Add transactions after swap transactions
178
188
  *
179
189
  * @returns This composer instance for chaining
180
190
  * @throws Error if the swap transactions have already been added
@@ -184,9 +194,14 @@ var SwapComposer = class SwapComposer {
184
194
  async addSwapTransactions() {
185
195
  if (this.swapTransactionsAdded) throw new Error("Swap transactions have already been added");
186
196
  if (this.getStatus() !== SwapComposerStatus.BUILDING) throw new Error("Cannot add swap transactions when composer status is not BUILDING");
197
+ const beforeTxns = await this.executeMiddlewareHooks("beforeSwap");
198
+ if (this.atc.count() + beforeTxns.length > SwapComposer.MAX_GROUP_SIZE) throw new Error(`Adding beforeSwap transactions exceeds the maximum atomic group size of ${SwapComposer.MAX_GROUP_SIZE}`);
199
+ for (const txnWithSigner of beforeTxns) this.atc.addTransaction(txnWithSigner);
187
200
  const processedTxns = await this.processSwapTransactions();
188
- if (this.atc.count() + processedTxns.length > SwapComposer.MAX_GROUP_SIZE) throw new Error(`Adding swap transactions exceeds the maximum atomic group size of ${SwapComposer.MAX_GROUP_SIZE}`);
201
+ const afterTxns = await this.executeMiddlewareHooks("afterSwap");
202
+ if (this.atc.count() + processedTxns.length + afterTxns.length > SwapComposer.MAX_GROUP_SIZE) throw new Error(`Adding swap transactions exceeds the maximum atomic group size of ${SwapComposer.MAX_GROUP_SIZE}`);
189
203
  for (const txnWithSigner of processedTxns) this.atc.addTransaction(txnWithSigner);
204
+ for (const txnWithSigner of afterTxns) this.atc.addTransaction(txnWithSigner);
190
205
  this.swapTransactionsAdded = true;
191
206
  return this;
192
207
  }
@@ -366,6 +381,42 @@ var SwapComposer = class SwapComposer {
366
381
  throw new Error(`Failed to re-sign transaction: ${error instanceof Error ? error.message : String(error)}`);
367
382
  }
368
383
  }
384
+ /**
385
+ * Execute middleware hooks (beforeSwap or afterSwap)
386
+ */
387
+ async executeMiddlewareHooks(hookName) {
388
+ const allTxns = [];
389
+ const quote = "createdAt" in this.quote ? this.quote : {
390
+ ...this.quote,
391
+ quote: this.quote.quote === "" ? 0n : BigInt(this.quote.quote),
392
+ amount: 0n,
393
+ createdAt: Date.now()
394
+ };
395
+ const quoteContext = {
396
+ fromASAID: BigInt(this.quote.fromASAID),
397
+ toASAID: BigInt(this.quote.toASAID),
398
+ amount: quote.amount,
399
+ type: this.quote.type,
400
+ address: quote.address,
401
+ algodClient: this.algodClient
402
+ };
403
+ for (const mw of this.middleware) {
404
+ if (!await mw.shouldApply(quoteContext) || !mw[hookName]) continue;
405
+ const suggestedParams = await this.algodClient.getTransactionParams().do();
406
+ const swapContext = {
407
+ quote,
408
+ address: this.address,
409
+ algodClient: this.algodClient,
410
+ suggestedParams,
411
+ fromASAID: BigInt(this.quote.fromASAID),
412
+ toASAID: BigInt(this.quote.toASAID),
413
+ signer: this.defaultSigner
414
+ };
415
+ const txns = await mw[hookName](swapContext);
416
+ allTxns.push(...txns);
417
+ }
418
+ return allTxns;
419
+ }
369
420
  };
370
421
 
371
422
  //#endregion
@@ -444,6 +495,7 @@ async function request(url, options) {
444
495
  var DeflexClient = class {
445
496
  config;
446
497
  algodClient;
498
+ middleware;
447
499
  /**
448
500
  * Create a new DeflexClient instance
449
501
  *
@@ -456,6 +508,7 @@ var DeflexClient = class {
456
508
  * @param config.referrerAddress - Referrer address for fee sharing (receives 25% of swap fees)
457
509
  * @param config.feeBps - Fee in basis points (default: 15 = 0.15%, max: 300 = 3.00%)
458
510
  * @param config.autoOptIn - Automatically detect and add required opt-in transactions (default: false)
511
+ * @param config.middleware - Array of middleware to apply to swaps (default: [])
459
512
  */
460
513
  constructor(config) {
461
514
  this.config = {
@@ -469,6 +522,7 @@ var DeflexClient = class {
469
522
  autoOptIn: config.autoOptIn ?? DEFAULT_AUTO_OPT_IN
470
523
  };
471
524
  this.algodClient = new Algodv2(this.config.algodToken, this.config.algodUri, this.config.algodPort);
525
+ this.middleware = config.middleware ?? [];
472
526
  }
473
527
  /**
474
528
  * Fetch a swap quote from the Deflex API
@@ -618,7 +672,17 @@ var DeflexClient = class {
618
672
  * ```
619
673
  */
620
674
  async newQuote(params) {
621
- const response = await this.fetchQuote(params);
675
+ let adjustedParams = { ...params };
676
+ const quoteContext = {
677
+ fromASAID: BigInt(params.fromASAID),
678
+ toASAID: BigInt(params.toASAID),
679
+ amount: BigInt(params.amount),
680
+ type: params.type ?? "fixed-input",
681
+ address: params.address ?? void 0,
682
+ algodClient: this.algodClient
683
+ };
684
+ for (const mw of this.middleware) if (await mw.shouldApply(quoteContext) && mw.adjustQuoteParams) adjustedParams = await mw.adjustQuoteParams(adjustedParams);
685
+ const response = await this.fetchQuote(adjustedParams);
622
686
  return {
623
687
  ...response,
624
688
  quote: response.quote === "" ? 0n : BigInt(response.quote),
@@ -686,7 +750,8 @@ var DeflexClient = class {
686
750
  })).txns,
687
751
  algodClient: this.algodClient,
688
752
  address,
689
- signer
753
+ signer,
754
+ middleware: this.middleware
690
755
  });
691
756
  }
692
757
  /**
@@ -713,5 +778,77 @@ var DeflexClient = class {
713
778
  };
714
779
 
715
780
  //#endregion
716
- export { DEFAULT_ALGOD_PORT, DEFAULT_ALGOD_TOKEN, DEFAULT_ALGOD_URI, DEFAULT_API_BASE_URL, DEFAULT_AUTO_OPT_IN, DEFAULT_CONFIRMATION_ROUNDS, DEFAULT_FEE_BPS, DEFAULT_MAX_DEPTH, DEFAULT_MAX_GROUP_SIZE, DEPRECATED_PROTOCOLS, DeflexClient, HTTPError, MAX_FEE_BPS, Protocol, SwapComposer, SwapComposerStatus, request };
781
+ //#region src/middleware.ts
782
+ /**
783
+ * Middleware that automatically adds an asset opt-out transaction when swapping
784
+ * the full balance of an input asset, leaving it with a zero balance.
785
+ *
786
+ * @example
787
+ * ```typescript
788
+ * import { DeflexClient, AutoOptOutMiddleware } from '@txnlab/deflex'
789
+ *
790
+ * const autoOptOut = new AutoOptOutMiddleware({
791
+ * excludedAssets: [31566704], // Don't auto-opt-out of USDC
792
+ * })
793
+ *
794
+ * const deflex = new DeflexClient({
795
+ * apiKey: 'your-api-key',
796
+ * middleware: [autoOptOut],
797
+ * })
798
+ *
799
+ * // When swapping full balance, opt-out transaction is automatically added
800
+ * const quote = await deflex.newQuote({
801
+ * address: userAddress,
802
+ * fromASAID: someAssetId,
803
+ * toASAID: 0,
804
+ * amount: fullBalance, // If this equals account's full balance, opt-out is added
805
+ * type: 'fixed-input',
806
+ * })
807
+ * ```
808
+ */
809
+ var AutoOptOutMiddleware = class {
810
+ name = "AutoOptOut";
811
+ version = "1.0.0";
812
+ excludedAssets;
813
+ constructor(config = {}) {
814
+ this.excludedAssets = new Set((config.excludedAssets ?? []).map((id) => BigInt(id)));
815
+ }
816
+ async shouldApply(context) {
817
+ if (context.type !== "fixed-input") return false;
818
+ if (!context.address) return false;
819
+ if (context.fromASAID === 0n) return false;
820
+ if (this.excludedAssets.has(context.fromASAID)) return false;
821
+ try {
822
+ const assetHolding = (await context.algodClient.accountInformation(context.address).do()).assets?.find((asset) => asset.assetId === context.fromASAID);
823
+ if (!assetHolding) return false;
824
+ return assetHolding.amount === context.amount;
825
+ } catch (error) {
826
+ console.warn(`AutoOptOutMiddleware: Failed to fetch account info for ${context.address}:`, error);
827
+ return false;
828
+ }
829
+ }
830
+ async adjustQuoteParams(params) {
831
+ const maxGroupSize = (params.maxGroupSize ?? 16) - 1;
832
+ return {
833
+ ...params,
834
+ maxGroupSize
835
+ };
836
+ }
837
+ async afterSwap(context) {
838
+ return [{
839
+ txn: makeAssetTransferTxnWithSuggestedParamsFromObject({
840
+ sender: context.address,
841
+ receiver: context.address,
842
+ amount: 0n,
843
+ assetIndex: context.fromASAID,
844
+ closeRemainderTo: context.address,
845
+ suggestedParams: context.suggestedParams
846
+ }),
847
+ signer: context.signer
848
+ }];
849
+ }
850
+ };
851
+
852
+ //#endregion
853
+ export { AutoOptOutMiddleware, DEFAULT_ALGOD_PORT, DEFAULT_ALGOD_TOKEN, DEFAULT_ALGOD_URI, DEFAULT_API_BASE_URL, DEFAULT_AUTO_OPT_IN, DEFAULT_CONFIRMATION_ROUNDS, DEFAULT_FEE_BPS, DEFAULT_MAX_DEPTH, DEFAULT_MAX_GROUP_SIZE, DEPRECATED_PROTOCOLS, DeflexClient, HTTPError, MAX_FEE_BPS, Protocol, SwapComposer, SwapComposerStatus, request };
717
854
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["swapTxns: TransactionWithSigner[]","status: number","statusText: string","data: unknown","errorData: unknown","body: FetchSwapTxnsBody"],"sources":["../src/constants.ts","../src/composer.ts","../src/utils.ts","../src/client.ts"],"sourcesContent":["/**\n * Supported DEX protocols for swap routing\n */\nexport enum Protocol {\n TinymanV2 = 'TinymanV2',\n Algofi = 'Algofi',\n Algomint = 'Algomint',\n Pact = 'Pact',\n Folks = 'Folks',\n TAlgo = 'TAlgo',\n}\n\n/**\n * Deprecated protocols that are automatically excluded from routing\n *\n * @internal\n */\nexport const DEPRECATED_PROTOCOLS = ['Humble', 'Tinyman'] as const\n\n/** Default Algod node URI for mainnet */\nexport const DEFAULT_ALGOD_URI = 'https://mainnet-api.4160.nodely.dev/'\n\n/** Default Algod node token (empty for public nodes) */\nexport const DEFAULT_ALGOD_TOKEN = ''\n\n/** Default Algod node port */\nexport const DEFAULT_ALGOD_PORT = 443\n\n/** Default Deflex API base URL */\nexport const DEFAULT_API_BASE_URL = 'https://deflex.txnlab.dev/api'\n\n/** Default fee in basis points (0.15%) */\nexport const DEFAULT_FEE_BPS = 15\n\n/** Maximum allowed fee in basis points (3.00%) */\nexport const MAX_FEE_BPS = 300\n\n/** Default maximum transaction group size */\nexport const DEFAULT_MAX_GROUP_SIZE = 16\n\n/** Default maximum routing depth (number of hops) */\nexport const DEFAULT_MAX_DEPTH = 4\n\n/** Default auto opt-in setting (automatic asset/app opt-in detection) */\nexport const DEFAULT_AUTO_OPT_IN = false\n\n/** Default number of rounds to wait for transaction confirmation */\nexport const DEFAULT_CONFIRMATION_ROUNDS = 4\n","import {\n AtomicTransactionComposer,\n decodeUnsignedTransaction,\n isValidAddress,\n LogicSigAccount,\n makeApplicationOptInTxnFromObject,\n msgpackRawDecode,\n signLogicSigTransactionObject,\n signTransaction,\n Transaction,\n type ABIResult,\n type Algodv2,\n type TransactionSigner,\n type TransactionWithSigner,\n} from 'algosdk'\nimport { DEFAULT_CONFIRMATION_ROUNDS } from './constants'\nimport type {\n FetchQuoteResponse,\n DeflexTransaction,\n DeflexSignature,\n DeflexQuote,\n MethodCall,\n} from './types'\n\n/**\n * A transaction signer function that supports both standard algosdk.TransactionSigner\n * and ARC-1 compliant signers that may return null for unsigned transactions.\n *\n * @param txnGroup - The complete transaction group to sign\n * @param indexesToSign - Array of indexes indicating which transactions need signing\n * @returns Array of signed transactions (may include nulls for ARC-1 compliant wallets)\n */\nexport type SignerFunction = (\n txnGroup: Transaction[],\n indexesToSign: number[],\n) => Promise<(Uint8Array | null)[]>\n\n/**\n * Status of the SwapComposer transaction group lifecycle\n */\nexport enum SwapComposerStatus {\n /** The atomic group is still under construction. */\n BUILDING,\n\n /** The atomic group has been finalized, but not yet signed. */\n BUILT,\n\n /** The atomic group has been finalized and signed, but not yet submitted to the network. */\n SIGNED,\n\n /** The atomic group has been finalized, signed, and submitted to the network. */\n SUBMITTED,\n\n /** The atomic group has been finalized, signed, submitted, and successfully committed to a block. */\n COMMITTED,\n}\n\n/**\n * Configuration for creating a SwapComposer instance\n */\nexport interface SwapComposerConfig {\n /** The quote response from fetchQuote() or newQuote() */\n readonly quote: FetchQuoteResponse | DeflexQuote\n /** The swap transactions from fetchSwapTransactions() */\n readonly deflexTxns: DeflexTransaction[]\n /** Algodv2 client instance */\n readonly algodClient: Algodv2\n /** The address of the account that will sign transactions */\n readonly address: string\n /** Transaction signer function */\n readonly signer: TransactionSigner | SignerFunction\n}\n\n/**\n * Composer for building and executing atomic swap transaction groups\n *\n * The SwapComposer allows you to build complex transaction groups by adding custom\n * transactions before and after swap transactions. It handles pre-signed transactions,\n * automatic app opt-ins, and provides a fluent API for transaction group construction.\n *\n * @example\n * ```typescript\n * const quote = await deflex.fetchQuote({ ... })\n * const composer = await deflex.newSwap({ quote, address, slippage, signer })\n *\n * await composer\n * .addTransaction(customTxn)\n * .addSwapTransactions()\n * .execute()\n * ```\n */\nexport class SwapComposer {\n /** The ATC used to compose the group */\n private atc = new AtomicTransactionComposer()\n\n /** The maximum size of an atomic transaction group. */\n static MAX_GROUP_SIZE: number = AtomicTransactionComposer.MAX_GROUP_SIZE\n\n /** Whether the swap transactions have been added to the atomic group. */\n private swapTransactionsAdded = false\n\n private readonly requiredAppOptIns: number[]\n private readonly deflexTxns: DeflexTransaction[]\n private readonly algodClient: Algodv2\n private readonly address: string\n private readonly signer: TransactionSigner | SignerFunction\n\n /**\n * Create a new SwapComposer instance\n *\n * Note: Most developers should use DeflexClient.newSwap() instead of constructing\n * this directly, as the factory method handles fetching swap transactions automatically.\n *\n * @param config - Configuration for the composer\n * @param config.requiredAppOptIns - The quote response from fetchQuote()\n * @param config.deflexTxns - The swap transactions from fetchSwapTransactions()\n * @param config.algodClient - Algodv2 client instance\n * @param config.address - The address of the account that will sign transactions\n * @param config.signer - Transaction signer function\n */\n constructor(config: SwapComposerConfig) {\n // Validate required parameters\n if (!config.quote) {\n throw new Error('Quote is required')\n }\n if (!config.deflexTxns) {\n throw new Error('Swap transactions are required')\n }\n if (config.deflexTxns.length === 0) {\n throw new Error('Swap transactions array cannot be empty')\n }\n if (!config.algodClient) {\n throw new Error('Algodv2 client instance is required')\n }\n if (!config.signer) {\n throw new Error('Signer is required')\n }\n\n this.requiredAppOptIns = config.quote.requiredAppOptIns\n this.deflexTxns = config.deflexTxns\n this.algodClient = config.algodClient\n this.address = this.validateAddress(config.address)\n this.signer = config.signer\n }\n\n /**\n * Get the status of this composer's transaction group\n *\n * @returns The current status of the transaction group\n */\n getStatus(): SwapComposerStatus {\n return this.atc.getStatus() as unknown as SwapComposerStatus\n }\n\n /**\n * Get the number of transactions currently in this atomic group\n *\n * @returns The number of transactions in the group\n */\n count(): number {\n return this.atc.count()\n }\n\n /**\n * Add a transaction to the atomic group\n *\n * Transactions are added in the order methods are called. For example:\n * ```typescript\n * composer\n * .addTransaction(txn1) // Added first\n * .addSwapTransactions() // Added second\n * .addTransaction(txn2) // Added third\n * ```\n *\n * @param transaction - The transaction to add\n * @returns This composer instance for chaining\n * @throws Error if the composer is not in the BUILDING status\n * @throws Error if the maximum group size is exceeded\n */\n addTransaction(transaction: Transaction, signer = this.defaultSigner): this {\n this.atc.addTransaction({ txn: transaction, signer })\n return this\n }\n\n /**\n * Add a method call to the atomic group\n *\n * The `signer` property in the `methodCall` parameter is optional. If not provided,\n * the signer will default to the one passed as the second parameter, or the\n * configured signer from the constructor if no second parameter is provided.\n *\n * @param methodCall - The method call to add\n * @param signer - The signer to use for the method call (defaults to constructor signer)\n * @returns This composer instance for chaining\n */\n addMethodCall(methodCall: MethodCall, signer = this.defaultSigner): this {\n this.atc.addMethodCall({\n ...methodCall,\n signer: methodCall.signer ?? signer,\n })\n return this\n }\n\n /**\n * Add swap transactions to the atomic group\n *\n * This method automatically processes required app opt-ins and adds all swap\n * transactions from the quote. Can only be called once per composer instance.\n *\n * @returns This composer instance for chaining\n * @throws Error if the swap transactions have already been added\n * @throws Error if the composer is not in the BUILDING status\n * @throws Error if the maximum group size is exceeded\n */\n async addSwapTransactions(): Promise<this> {\n if (this.swapTransactionsAdded) {\n throw new Error('Swap transactions have already been added')\n }\n\n if (this.getStatus() !== SwapComposerStatus.BUILDING) {\n throw new Error(\n 'Cannot add swap transactions when composer status is not BUILDING',\n )\n }\n\n const processedTxns = await this.processSwapTransactions()\n const newLength = this.atc.count() + processedTxns.length\n\n if (newLength > SwapComposer.MAX_GROUP_SIZE) {\n throw new Error(\n `Adding swap transactions exceeds the maximum atomic group size of ${SwapComposer.MAX_GROUP_SIZE}`,\n )\n }\n\n for (const txnWithSigner of processedTxns) {\n this.atc.addTransaction(txnWithSigner)\n }\n\n this.swapTransactionsAdded = true\n return this\n }\n\n /**\n * Finalize the transaction group by assigning group IDs\n *\n * This method builds the atomic transaction group, assigning group IDs to all transactions\n * if there is more than one transaction. After calling this method, the composer's status\n * will be at least BUILT.\n *\n * @returns Array of transactions with their associated signers\n *\n * @throws Error if the group contains 0 transactions\n *\n * @example\n * ```typescript\n * const composer = await deflex.newSwap({ quote, address, slippage, signer })\n * composer.addTransaction(customTxn)\n *\n * // Build the group to inspect transactions before signing\n * const txnsWithSigners = composer.buildGroup()\n * console.log('Group ID:', txnsWithSigners[0].txn.group)\n * console.log('Group length:', txnsWithSigners.length)\n * console.log('Status:', composer.getStatus()) // BUILT\n * ```\n */\n buildGroup(): TransactionWithSigner[] {\n return this.atc.buildGroup()\n }\n\n /**\n * Sign the transaction group\n *\n * Automatically adds swap transactions if not already added, builds the atomic group,\n * and signs all transactions using the configured signer.\n *\n * @returns A promise that resolves to an array of signed transaction blobs\n *\n * @example\n * ```typescript\n * const signedTxns = await composer.sign()\n * ```\n */\n async sign(): Promise<Uint8Array[]> {\n if (this.getStatus() >= SwapComposerStatus.SIGNED) {\n return this.atc.gatherSignatures()\n }\n\n // Auto-add swap transactions if needed\n if (!this.swapTransactionsAdded) {\n await this.addSwapTransactions()\n }\n\n return await this.atc.gatherSignatures()\n }\n\n /**\n * Submit the signed transactions to the network\n *\n * This method signs the transaction group (if not already signed) and submits\n * it to the Algorand network. Does not wait for confirmation.\n *\n * @returns The transaction IDs\n * @throws Error if the transaction group has already been submitted\n *\n * @example\n * ```typescript\n * const txIds = await composer.submit()\n * console.log('Submitted transactions:', txIds)\n * ```\n */\n async submit(): Promise<string[]> {\n // Auto-add swap transactions if needed (maintains backward compatibility)\n if (!this.swapTransactionsAdded) {\n await this.addSwapTransactions()\n }\n\n return this.atc.submit(this.algodClient)\n }\n\n /**\n * Execute the swap\n *\n * Signs the transaction group, submits it to the network, and waits for confirmation.\n * This is the primary method for executing swaps and combines sign(), submit(), and\n * waitForConfirmation() into a single call.\n *\n * @param waitRounds - The number of rounds to wait for confirmation (default: 4)\n * @returns Object containing the confirmed round and transaction IDs\n * @throws Error if the transaction group has already been committed\n *\n * @example\n * ```typescript\n * const result = await composer.execute()\n * console.log(`Confirmed in round ${result.confirmedRound}`)\n * console.log('Transaction IDs:', result.txIds)\n * ```\n */\n async execute(waitRounds: number = DEFAULT_CONFIRMATION_ROUNDS): Promise<{\n confirmedRound: bigint\n txIds: string[]\n methodResults: ABIResult[]\n }> {\n // Auto-add swap transactions if needed (maintains backward compatibility)\n if (!this.swapTransactionsAdded) {\n await this.addSwapTransactions()\n }\n\n const { txIDs, ...result } = await this.atc.execute(\n this.algodClient,\n waitRounds,\n )\n\n return {\n ...result,\n txIds: txIDs,\n }\n }\n\n /**\n * Validates an Algorand address\n */\n private validateAddress(address: string): string {\n if (!isValidAddress(address)) {\n throw new Error(`Invalid Algorand address: ${address}`)\n }\n return address\n }\n\n /**\n * Processes app opt-ins and decodes swap transactions from API response\n */\n private async processSwapTransactions(): Promise<TransactionWithSigner[]> {\n const appOptIns = await this.processRequiredAppOptIns()\n\n const swapTxns: TransactionWithSigner[] = []\n for (let i = 0; i < this.deflexTxns.length; i++) {\n const deflexTxn = this.deflexTxns[i]\n if (!deflexTxn) continue\n\n try {\n const txnBytes = Buffer.from(deflexTxn.data, 'base64')\n const txn = decodeUnsignedTransaction(txnBytes)\n delete txn.group\n\n if (deflexTxn.signature !== false) {\n // Pre-signed transaction - use custom Deflex signer\n swapTxns.push({\n txn,\n signer: this.createDeflexSigner(deflexTxn.signature),\n })\n } else {\n // User transaction - use configured signer\n swapTxns.push({\n txn,\n signer: this.defaultSigner,\n })\n }\n } catch (error) {\n throw new Error(\n `Failed to process swap transaction at index ${i}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return [...appOptIns, ...swapTxns]\n }\n\n /**\n * Creates opt-in transactions for apps the user hasn't opted into yet\n */\n private async processRequiredAppOptIns(): Promise<TransactionWithSigner[]> {\n // Fetch account information\n const accountInfo = await this.algodClient\n .accountInformation(this.address)\n .do()\n\n // Check app opt-ins\n const userApps =\n accountInfo?.appsLocalState?.map((app) => Number(app.id)) || []\n const appsToOptIn = this.requiredAppOptIns.filter(\n (appId) => !userApps.includes(appId),\n )\n\n if (appsToOptIn.length === 0) return []\n\n const suggestedParams = await this.algodClient.getTransactionParams().do()\n\n return appsToOptIn.map((appId) => ({\n txn: makeApplicationOptInTxnFromObject({\n sender: this.address,\n appIndex: appId,\n suggestedParams,\n }),\n signer: this.defaultSigner,\n }))\n }\n\n /**\n * The default signer function that uses the configured signer\n */\n private defaultSigner: TransactionSigner = async (\n txnGroup: Transaction[],\n indexesToSign: number[],\n ) => {\n const result = await this.signer(txnGroup, indexesToSign)\n return result.filter((txn): txn is Uint8Array => txn !== null)\n }\n\n /**\n * Creates a TransactionSigner function for Deflex pre-signed transactions\n */\n private createDeflexSigner(signature: DeflexSignature): TransactionSigner {\n return async (\n txnGroup: Transaction[],\n indexesToSign: number[],\n ): Promise<Uint8Array[]> => {\n return indexesToSign.map((i) => {\n const txn = txnGroup[i]\n if (!txn) throw new Error(`Transaction at index ${i} not found`)\n return this.signDeflexTransaction(txn, signature)\n })\n }\n }\n\n /**\n * Re-signs a Deflex transaction using the provided logic signature or secret key\n */\n private signDeflexTransaction(\n transaction: Transaction,\n signature: DeflexSignature,\n ): Uint8Array {\n try {\n if (signature.type === 'logic_signature') {\n // Decode the signature value to extract the logic signature\n const valueArray = signature.value as Record<string, number>\n const valueBytes = new Uint8Array(Object.values(valueArray))\n const decoded = msgpackRawDecode(valueBytes) as {\n lsig?: { l: Uint8Array; arg?: Uint8Array[] }\n }\n\n if (!decoded.lsig) {\n throw new Error('Logic signature structure missing lsig field')\n }\n\n const lsig = decoded.lsig\n const logicSigAccount = new LogicSigAccount(lsig.l, lsig.arg)\n\n const signedTxn = signLogicSigTransactionObject(\n transaction,\n logicSigAccount,\n )\n return signedTxn.blob\n } else if (signature.type === 'secret_key') {\n // Convert signature.value (Record<string, number>) to Uint8Array\n const valueArray = signature.value as Record<string, number>\n const secretKey = new Uint8Array(Object.values(valueArray))\n const signedTxn = signTransaction(transaction, secretKey)\n return signedTxn.blob\n } else {\n throw new Error(`Unsupported signature type: ${signature.type}`)\n }\n } catch (error) {\n throw new Error(\n `Failed to re-sign transaction: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n}\n","/**\n * HTTP error with status code and response data\n */\nexport class HTTPError extends Error {\n constructor(\n public status: number,\n public statusText: string,\n public data: unknown,\n ) {\n super(`HTTP ${status} ${statusText}`)\n this.name = 'HTTPError'\n }\n}\n\n/**\n * Make an HTTP request and parse JSON response\n *\n * Simple wrapper around native fetch for API calls. Throws HTTPError for\n * non-2xx responses.\n *\n * @param url - The URL to request\n * @param options - Fetch options\n * @returns Parsed JSON response\n * @throws HTTPError if the response status is not ok\n */\nexport async function request<T>(\n url: string,\n options?: RequestInit,\n): Promise<T> {\n const response = await fetch(url, options)\n\n if (!response.ok) {\n let errorData: unknown\n\n try {\n errorData = await response.json()\n } catch {\n try {\n errorData = await response.text()\n } catch {\n errorData = 'Failed to parse error response'\n }\n }\n\n throw new HTTPError(\n response.status,\n response.statusText,\n JSON.stringify(errorData),\n )\n }\n\n return response.json() as Promise<T>\n}\n","import { Algodv2, isValidAddress, type TransactionSigner } from 'algosdk'\nimport { SwapComposer, type SignerFunction } from './composer'\nimport {\n DEFAULT_ALGOD_PORT,\n DEFAULT_ALGOD_TOKEN,\n DEFAULT_ALGOD_URI,\n DEFAULT_API_BASE_URL,\n DEFAULT_AUTO_OPT_IN,\n DEFAULT_FEE_BPS,\n DEFAULT_MAX_DEPTH,\n DEFAULT_MAX_GROUP_SIZE,\n DEPRECATED_PROTOCOLS,\n MAX_FEE_BPS,\n} from './constants'\nimport { request } from './utils'\nimport type {\n FetchQuoteResponse,\n FetchSwapTxnsResponse,\n DeflexConfig,\n DeflexConfigParams,\n FetchSwapTxnsParams,\n FetchSwapTxnsBody,\n FetchQuoteParams,\n DeflexQuote,\n} from './types'\n\n/**\n * Client for interacting with the Deflex order router API\n *\n * The DeflexClient provides methods to fetch swap quotes and create transaction composers\n * for executing swaps on the Algorand blockchain. It handles API communication, transaction\n * validation, and automatic asset/app opt-in detection.\n *\n * @example\n * ```typescript\n * const deflex = new DeflexClient({\n * apiKey: 'your-api-key',\n * })\n * ```\n *\n * @example\n * ```typescript\n * const deflex = new DeflexClient({\n * apiKey: 'your-api-key',\n * apiBaseUrl: 'https://deflex.txnlab.dev',\n * algodUri: 'https://mainnet-api.4160.nodely.dev/',\n * algodToken: '',\n * algodPort: 443,\n * referrerAddress: 'REFERRER_ADDRESS...',\n * feeBps: 15,\n * autoOptIn: false,\n * })\n * ```\n */\nexport class DeflexClient {\n private readonly config: DeflexConfig\n private readonly algodClient: Algodv2\n\n /**\n * Create a new DeflexClient instance\n *\n * @param config - Configuration parameters\n * @param config.apiKey - API key for Deflex API (required)\n * @param config.apiBaseUrl - Base URL for the Deflex API (default: https://deflex.txnlab.dev)\n * @param config.algodUri - Algod node URI (default: https://mainnet-api.4160.nodely.dev/)\n * @param config.algodToken - Algod node token (default: '')\n * @param config.algodPort - Algod node port (default: 443)\n * @param config.referrerAddress - Referrer address for fee sharing (receives 25% of swap fees)\n * @param config.feeBps - Fee in basis points (default: 15 = 0.15%, max: 300 = 3.00%)\n * @param config.autoOptIn - Automatically detect and add required opt-in transactions (default: false)\n */\n constructor(config: DeflexConfigParams) {\n // Validate and set config\n this.config = {\n apiKey: this.validateApiKey(config.apiKey),\n apiBaseUrl: config.apiBaseUrl ?? DEFAULT_API_BASE_URL,\n algodUri: config.algodUri ?? DEFAULT_ALGOD_URI,\n algodToken: config.algodToken ?? DEFAULT_ALGOD_TOKEN,\n algodPort: config.algodPort ?? DEFAULT_ALGOD_PORT,\n referrerAddress: config.referrerAddress\n ? this.validateAddress(config.referrerAddress)\n : undefined,\n feeBps: this.validateFeeBps(config.feeBps ?? DEFAULT_FEE_BPS),\n autoOptIn: config.autoOptIn ?? DEFAULT_AUTO_OPT_IN,\n }\n\n // Create Algodv2 client\n this.algodClient = new Algodv2(\n this.config.algodToken,\n this.config.algodUri,\n this.config.algodPort,\n )\n }\n\n /**\n * Fetch a swap quote from the Deflex API\n *\n * Requests optimal swap routing from the Deflex API. The quote includes routing\n * information, price impact, required opt-ins, and an encrypted transaction payload.\n *\n * @param params - Parameters for the quote request\n * @param params.fromASAID - The ID of the asset to swap from\n * @param params.toASAID - The ID of the asset to swap to\n * @param params.amount - The amount of the asset to swap in base units\n * @param params.type - The type of the quote (default: 'fixed-input')\n * @param params.disabledProtocols - List of protocols to disable (default: [])\n * @param params.maxGroupSize - The maximum group size (default: 16)\n * @param params.maxDepth - The maximum depth (default: 4)\n * @param params.address - The address of the account that will perform the swap (recommended when using `config.autoOptIn` or `params.optIn`)\n * @param params.optIn - Whether to include asset opt-in transaction\n * - If true: API reduces maxGroupSize by 1 and includes opt-in (always included, even if not needed)\n * - If false: No opt-in transaction included\n * - If undefined: Falls back to `config.autoOptIn` behavior with account check (if `params.address` is provided)\n * @returns A FetchQuoteResponse object with routing information\n *\n * @example\n * ```typescript\n * const quote = await deflex.fetchQuote({\n * address: 'ABC...',\n * fromASAID: 0, // ALGO\n * toASAID: 31566704, // USDC\n * amount: 1_000_000, // 1 ALGO\n * })\n * ```\n */\n async fetchQuote(params: FetchQuoteParams): Promise<FetchQuoteResponse> {\n const {\n fromASAID,\n toASAID,\n amount,\n type = 'fixed-input',\n disabledProtocols = [],\n maxGroupSize = DEFAULT_MAX_GROUP_SIZE,\n maxDepth = DEFAULT_MAX_DEPTH,\n optIn,\n address,\n } = params\n\n // Always include deprecated protocols in disabled list\n const allDisabledProtocols = [\n ...new Set([...DEPRECATED_PROTOCOLS, ...disabledProtocols]),\n ]\n\n let includeOptIn = optIn\n if (includeOptIn === undefined && this.config.autoOptIn) {\n if (address) {\n includeOptIn = await this.needsAssetOptIn(\n this.validateAddress(address),\n toASAID,\n )\n } else {\n console.warn(\n 'autoOptIn is enabled but no address provided to fetchQuote(). Asset opt-in check skipped.',\n )\n }\n }\n\n const url = new URL(`${this.config.apiBaseUrl}/fetchQuote`)\n\n url.searchParams.append('apiKey', this.config.apiKey)\n url.searchParams.append('algodUri', this.config.algodUri)\n url.searchParams.append('algodToken', this.config.algodToken)\n url.searchParams.append('algodPort', String(this.config.algodPort))\n url.searchParams.append('feeBps', this.config.feeBps.toString())\n url.searchParams.append('fromASAID', BigInt(fromASAID).toString())\n url.searchParams.append('toASAID', BigInt(toASAID).toString())\n url.searchParams.append('amount', BigInt(amount).toString())\n url.searchParams.append('type', type)\n url.searchParams.append('disabledProtocols', allDisabledProtocols.join(','))\n url.searchParams.append('maxGroupSize', maxGroupSize.toString())\n url.searchParams.append('maxDepth', maxDepth.toString())\n\n if (typeof includeOptIn === 'boolean') {\n url.searchParams.append('optIn', String(includeOptIn))\n }\n\n if (this.config.referrerAddress) {\n url.searchParams.append('referrerAddress', this.config.referrerAddress)\n }\n\n return request<FetchQuoteResponse>(url.toString())\n }\n\n /**\n * Check if asset opt-in is required for the output asset\n *\n * Convenience method to determine if an address needs to opt into the output asset\n * of a swap. This is useful when you want to get a quote without requiring wallet\n * connection upfront, but need to know whether to set `optIn: true` in fetchQuote()\n * to ensure proper routing (as opt-ins reduce maxGroupSize by 1).\n *\n * Note: If you enable `config.autoOptIn`, this check is handled automatically when\n * an address is provided to fetchQuote().\n *\n * @param address - The address to check\n * @param assetId - The output asset ID to check\n * @returns True if asset opt-in is required, false otherwise (always false for ALGO)\n *\n * @example\n * ```typescript\n * // Check if opt-in needed for output asset before fetching quote\n * const needsOptIn = await deflex.needsAssetOptIn(userAddress, toAssetId)\n * const quote = await deflex.fetchQuote({\n * fromAssetId,\n * toAssetId,\n * amount,\n * optIn: needsOptIn,\n * })\n * ```\n */\n async needsAssetOptIn(\n address: string,\n assetId: number | bigint,\n ): Promise<boolean> {\n // Fetch account information\n const accountInfo = await this.algodClient.accountInformation(address).do()\n\n // Check if asset opt-in is required\n return (\n BigInt(assetId) !== 0n &&\n accountInfo?.assets?.find(\n (asset) => asset.assetId === BigInt(assetId),\n ) === undefined\n )\n }\n\n /**\n * Fetch swap transactions from the Deflex API\n *\n * Decrypts the quote payload and generates executable swap transactions for the\n * specified signer address with the given slippage tolerance.\n *\n * @param params - Parameters for the swap transaction request\n * @param params.quote - The quote response from fetchQuote()\n * @param params.address - The address of the signer\n * @param params.slippage - The slippage tolerance as a percentage (e.g., 1 for 1%)\n * @returns A FetchSwapTxnsResponse object with transaction data\n */\n async fetchSwapTransactions(\n params: FetchSwapTxnsParams,\n ): Promise<FetchSwapTxnsResponse> {\n const { quote, address, slippage } = params\n\n // Validate signer address\n this.validateAddress(address)\n\n const url = new URL(`${this.config.apiBaseUrl}/fetchExecuteSwapTxns`)\n\n const body: FetchSwapTxnsBody = {\n apiKey: this.config.apiKey,\n address,\n txnPayloadJSON: quote.txnPayload,\n slippage,\n }\n\n return request<FetchSwapTxnsResponse>(url.toString(), {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n })\n }\n\n /**\n * Fetch a quote and return an enhanced quote result\n *\n * This is the recommended way to fetch quotes. It returns an object that\n * extends the raw API response with additional metadata and type normalization.\n *\n * @param params - Parameters for the quote request\n * @param params.fromASAID - The ID of the asset to swap from\n * @param params.toASAID - The ID of the asset to swap to\n * @param params.amount - The amount of the asset to swap in base units\n * @param params.type - The type of the quote (default: 'fixed-input')\n * @param params.disabledProtocols - List of protocols to disable (default: [])\n * @param params.maxGroupSize - The maximum group size (default: 16)\n * @param params.maxDepth - The maximum depth (default: 4)\n * @param params.address - The address of the account that will perform the swap (recommended when using `config.autoOptIn` or `params.optIn`)\n * @param params.optIn - Whether to include asset opt-in transaction\n * @returns A DeflexQuote enhanced quote result\n *\n * @example\n * ```typescript\n * const quote = await deflex.newQuote({\n * address: 'ABC...',\n * fromASAID: 0,\n * toASAID: 31566704,\n * amount: 1_000_000,\n * })\n *\n * console.log(quote.quote) // bigint - quoted amount\n * console.log(quote.fromASAID) // number - input asset ID\n * console.log(quote.toASAID) // number - output asset ID\n * console.log(quote.amount) // bigint - original request amount\n * console.log(quote.createdAt) // number - timestamp\n * ```\n */\n async newQuote(params: FetchQuoteParams): Promise<DeflexQuote> {\n const response = await this.fetchQuote(params)\n\n return {\n ...response,\n quote: response.quote === '' ? 0n : BigInt(response.quote),\n amount: BigInt(params.amount),\n address: params.address ?? undefined,\n createdAt: Date.now(),\n }\n }\n\n /**\n * Create a SwapComposer instance\n *\n * This factory method creates a composer that allows you to add custom transactions\n * before and after the swap transactions, with automatic handling of pre-signed transactions\n * and opt-ins.\n *\n * @param config.quote - The quote result from newQuote() or raw API response from fetchQuote()\n * @param config.address - The address of the signer\n * @param config.slippage - The slippage tolerance\n * @param config.signer - Transaction signer function\n * @returns A SwapComposer instance ready for building transaction groups\n *\n * @example\n * ```typescript\n * // Basic swap\n * const quote = await deflex.newQuote({ ... })\n * await deflex.newSwap({ quote, address, slippage, signer })\n * .execute()\n * ```\n *\n * @example\n * ```typescript\n * // Advanced swap with custom transactions\n * const quote = await deflex.newQuote({ ... })\n * const swap = await deflex.newSwap({\n * quote,\n * address,\n * slippage,\n * signer,\n * })\n *\n * console.log(swap.getStatus()) // BUILDING\n *\n * const signedTxns = await swap\n * .addTransaction(beforeTxn)\n * .addSwapTransactions() // Adds swap transactions to the group\n * .addTransaction(afterTxn)\n * .sign()\n *\n * console.log(swap.getStatus()) // SIGNED\n *\n * const result = await swap.execute(waitRounds)\n * console.log(result.confirmedRound, result.txIds)\n *\n * console.log(swap.getStatus()) // COMMITTED\n * ```\n */\n async newSwap(config: {\n quote: DeflexQuote | FetchQuoteResponse\n address: string\n slippage: number\n signer: TransactionSigner | SignerFunction\n }): Promise<SwapComposer> {\n const { quote, address, slippage, signer } = config\n\n const swapResponse = await this.fetchSwapTransactions({\n quote,\n address,\n slippage,\n })\n\n // Create the composer\n const composer = new SwapComposer({\n quote,\n deflexTxns: swapResponse.txns,\n algodClient: this.algodClient,\n address,\n signer,\n })\n\n return composer\n }\n\n /**\n * Validates the API key\n */\n private validateApiKey(apiKey: string): string {\n if (!apiKey) {\n throw new Error('API key is required')\n }\n return apiKey\n }\n\n /**\n * Validates an Algorand address\n */\n private validateAddress(address: string): string {\n if (!isValidAddress(address)) {\n throw new Error(`Invalid Algorand address: ${address}`)\n }\n return address\n }\n\n /**\n * Validates the fee in basis points (max 300 = 3.00%)\n */\n private validateFeeBps(feeBps: number): number {\n if (feeBps < 0 || feeBps > MAX_FEE_BPS) {\n throw new Error(\n `Invalid fee: ${feeBps} basis points (must be between 0 and ${MAX_FEE_BPS})`,\n )\n }\n return feeBps\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["swapTxns: TransactionWithSigner[]","allTxns: TransactionWithSigner[]","quote: DeflexQuote","quoteContext: QuoteContext","swapContext: SwapContext","status: number","statusText: string","data: unknown","errorData: unknown","body: FetchSwapTxnsBody"],"sources":["../src/constants.ts","../src/composer.ts","../src/utils.ts","../src/client.ts","../src/middleware.ts"],"sourcesContent":["/**\n * Supported DEX protocols for swap routing\n */\nexport enum Protocol {\n TinymanV2 = 'TinymanV2',\n Algofi = 'Algofi',\n Algomint = 'Algomint',\n Pact = 'Pact',\n Folks = 'Folks',\n TAlgo = 'TAlgo',\n}\n\n/**\n * Deprecated protocols that are automatically excluded from routing\n *\n * @internal\n */\nexport const DEPRECATED_PROTOCOLS = ['Humble', 'Tinyman'] as const\n\n/** Default Algod node URI for mainnet */\nexport const DEFAULT_ALGOD_URI = 'https://mainnet-api.4160.nodely.dev/'\n\n/** Default Algod node token (empty for public nodes) */\nexport const DEFAULT_ALGOD_TOKEN = ''\n\n/** Default Algod node port */\nexport const DEFAULT_ALGOD_PORT = 443\n\n/** Default Deflex API base URL */\nexport const DEFAULT_API_BASE_URL = 'https://deflex.txnlab.dev/api'\n\n/** Default fee in basis points (0.15%) */\nexport const DEFAULT_FEE_BPS = 15\n\n/** Maximum allowed fee in basis points (3.00%) */\nexport const MAX_FEE_BPS = 300\n\n/** Default maximum transaction group size */\nexport const DEFAULT_MAX_GROUP_SIZE = 16\n\n/** Default maximum routing depth (number of hops) */\nexport const DEFAULT_MAX_DEPTH = 4\n\n/** Default auto opt-in setting (automatic asset/app opt-in detection) */\nexport const DEFAULT_AUTO_OPT_IN = false\n\n/** Default number of rounds to wait for transaction confirmation */\nexport const DEFAULT_CONFIRMATION_ROUNDS = 4\n","import {\n AtomicTransactionComposer,\n decodeUnsignedTransaction,\n isValidAddress,\n LogicSigAccount,\n makeApplicationOptInTxnFromObject,\n msgpackRawDecode,\n signLogicSigTransactionObject,\n signTransaction,\n Transaction,\n type ABIResult,\n type Algodv2,\n type TransactionSigner,\n type TransactionWithSigner,\n} from 'algosdk'\nimport { DEFAULT_CONFIRMATION_ROUNDS } from './constants'\nimport type { SwapMiddleware, SwapContext, QuoteContext } from './middleware'\nimport type {\n FetchQuoteResponse,\n DeflexTransaction,\n DeflexSignature,\n DeflexQuote,\n MethodCall,\n QuoteType,\n} from './types'\n\n/**\n * A transaction signer function that supports both standard algosdk.TransactionSigner\n * and ARC-1 compliant signers that may return null for unsigned transactions.\n *\n * @param txnGroup - The complete transaction group to sign\n * @param indexesToSign - Array of indexes indicating which transactions need signing\n * @returns Array of signed transactions (may include nulls for ARC-1 compliant wallets)\n */\nexport type SignerFunction = (\n txnGroup: Transaction[],\n indexesToSign: number[],\n) => Promise<(Uint8Array | null)[]>\n\n/**\n * Status of the SwapComposer transaction group lifecycle\n */\nexport enum SwapComposerStatus {\n /** The atomic group is still under construction. */\n BUILDING,\n\n /** The atomic group has been finalized, but not yet signed. */\n BUILT,\n\n /** The atomic group has been finalized and signed, but not yet submitted to the network. */\n SIGNED,\n\n /** The atomic group has been finalized, signed, and submitted to the network. */\n SUBMITTED,\n\n /** The atomic group has been finalized, signed, submitted, and successfully committed to a block. */\n COMMITTED,\n}\n\n/**\n * Configuration for creating a SwapComposer instance\n */\nexport interface SwapComposerConfig {\n /** The quote response from fetchQuote() or newQuote() */\n readonly quote: FetchQuoteResponse | DeflexQuote\n /** The swap transactions from fetchSwapTransactions() */\n readonly deflexTxns: DeflexTransaction[]\n /** Algodv2 client instance */\n readonly algodClient: Algodv2\n /** The address of the account that will sign transactions */\n readonly address: string\n /** Transaction signer function */\n readonly signer: TransactionSigner | SignerFunction\n /** Middleware to apply during swap composition */\n readonly middleware?: SwapMiddleware[]\n}\n\n/**\n * Composer for building and executing atomic swap transaction groups\n *\n * The SwapComposer allows you to build complex transaction groups by adding custom\n * transactions before and after swap transactions. It handles pre-signed transactions,\n * automatic app opt-ins, and provides a fluent API for transaction group construction.\n *\n * @example\n * ```typescript\n * const quote = await deflex.fetchQuote({ ... })\n * const composer = await deflex.newSwap({ quote, address, slippage, signer })\n *\n * await composer\n * .addTransaction(customTxn)\n * .addSwapTransactions()\n * .execute()\n * ```\n */\nexport class SwapComposer {\n /** The ATC used to compose the group */\n private atc = new AtomicTransactionComposer()\n\n /** The maximum size of an atomic transaction group. */\n static MAX_GROUP_SIZE: number = AtomicTransactionComposer.MAX_GROUP_SIZE\n\n /** Whether the swap transactions have been added to the atomic group. */\n private swapTransactionsAdded = false\n\n private readonly quote: FetchQuoteResponse | DeflexQuote\n private readonly requiredAppOptIns: number[]\n private readonly deflexTxns: DeflexTransaction[]\n private readonly algodClient: Algodv2\n private readonly address: string\n private readonly signer: TransactionSigner | SignerFunction\n private readonly middleware: SwapMiddleware[]\n\n /**\n * Create a new SwapComposer instance\n *\n * Note: Most developers should use DeflexClient.newSwap() instead of constructing\n * this directly, as the factory method handles fetching swap transactions automatically.\n *\n * @param config - Configuration for the composer\n * @param config.quote - The quote response from fetchQuote()\n * @param config.deflexTxns - The swap transactions from fetchSwapTransactions()\n * @param config.algodClient - Algodv2 client instance\n * @param config.address - The address of the account that will sign transactions\n * @param config.signer - Transaction signer function\n * @param config.middleware - Middleware to apply during swap composition\n */\n constructor(config: SwapComposerConfig) {\n // Validate required parameters\n if (!config.quote) {\n throw new Error('Quote is required')\n }\n if (!config.deflexTxns) {\n throw new Error('Swap transactions are required')\n }\n if (config.deflexTxns.length === 0) {\n throw new Error('Swap transactions array cannot be empty')\n }\n if (!config.algodClient) {\n throw new Error('Algodv2 client instance is required')\n }\n if (!config.signer) {\n throw new Error('Signer is required')\n }\n\n this.quote = config.quote\n this.requiredAppOptIns = config.quote.requiredAppOptIns\n this.deflexTxns = config.deflexTxns\n this.algodClient = config.algodClient\n this.address = this.validateAddress(config.address)\n this.signer = config.signer\n this.middleware = config.middleware ?? []\n }\n\n /**\n * Get the status of this composer's transaction group\n *\n * @returns The current status of the transaction group\n */\n getStatus(): SwapComposerStatus {\n return this.atc.getStatus() as unknown as SwapComposerStatus\n }\n\n /**\n * Get the number of transactions currently in this atomic group\n *\n * @returns The number of transactions in the group\n */\n count(): number {\n return this.atc.count()\n }\n\n /**\n * Add a transaction to the atomic group\n *\n * Transactions are added in the order methods are called. For example:\n * ```typescript\n * composer\n * .addTransaction(txn1) // Added first\n * .addSwapTransactions() // Added second\n * .addTransaction(txn2) // Added third\n * ```\n *\n * @param transaction - The transaction to add\n * @returns This composer instance for chaining\n * @throws Error if the composer is not in the BUILDING status\n * @throws Error if the maximum group size is exceeded\n */\n addTransaction(transaction: Transaction, signer = this.defaultSigner): this {\n this.atc.addTransaction({ txn: transaction, signer })\n return this\n }\n\n /**\n * Add a method call to the atomic group\n *\n * The `signer` property in the `methodCall` parameter is optional. If not provided,\n * the signer will default to the one passed as the second parameter, or the\n * configured signer from the constructor if no second parameter is provided.\n *\n * @param methodCall - The method call to add\n * @param signer - The signer to use for the method call (defaults to constructor signer)\n * @returns This composer instance for chaining\n */\n addMethodCall(methodCall: MethodCall, signer = this.defaultSigner): this {\n this.atc.addMethodCall({\n ...methodCall,\n signer: methodCall.signer ?? signer,\n })\n return this\n }\n\n /**\n * Add swap transactions to the atomic group\n *\n * This method automatically processes required app opt-ins, executes middleware hooks,\n * and adds all swap transactions from the quote. Can only be called once per composer instance.\n *\n * Middleware hooks are executed in this order:\n * 1. beforeSwap() - Add transactions before swap transactions\n * 2. Swap transactions (from API)\n * 3. afterSwap() - Add transactions after swap transactions\n *\n * @returns This composer instance for chaining\n * @throws Error if the swap transactions have already been added\n * @throws Error if the composer is not in the BUILDING status\n * @throws Error if the maximum group size is exceeded\n */\n async addSwapTransactions(): Promise<this> {\n if (this.swapTransactionsAdded) {\n throw new Error('Swap transactions have already been added')\n }\n\n if (this.getStatus() !== SwapComposerStatus.BUILDING) {\n throw new Error(\n 'Cannot add swap transactions when composer status is not BUILDING',\n )\n }\n\n // Execute beforeSwap middleware hooks\n const beforeTxns = await this.executeMiddlewareHooks('beforeSwap')\n\n // Check total length before adding beforeSwap transactions\n if (this.atc.count() + beforeTxns.length > SwapComposer.MAX_GROUP_SIZE) {\n throw new Error(\n `Adding beforeSwap transactions exceeds the maximum atomic group size of ${SwapComposer.MAX_GROUP_SIZE}`,\n )\n }\n\n for (const txnWithSigner of beforeTxns) {\n this.atc.addTransaction(txnWithSigner)\n }\n\n // Process swap transactions and execute afterSwap hooks\n const processedTxns = await this.processSwapTransactions()\n const afterTxns = await this.executeMiddlewareHooks('afterSwap')\n\n // Check total length before adding swap and afterSwap transactions\n const totalLength =\n this.atc.count() + processedTxns.length + afterTxns.length\n\n if (totalLength > SwapComposer.MAX_GROUP_SIZE) {\n throw new Error(\n `Adding swap transactions exceeds the maximum atomic group size of ${SwapComposer.MAX_GROUP_SIZE}`,\n )\n }\n\n // Add swap transactions\n for (const txnWithSigner of processedTxns) {\n this.atc.addTransaction(txnWithSigner)\n }\n\n // Add afterSwap middleware transactions\n for (const txnWithSigner of afterTxns) {\n this.atc.addTransaction(txnWithSigner)\n }\n\n this.swapTransactionsAdded = true\n return this\n }\n\n /**\n * Finalize the transaction group by assigning group IDs\n *\n * This method builds the atomic transaction group, assigning group IDs to all transactions\n * if there is more than one transaction. After calling this method, the composer's status\n * will be at least BUILT.\n *\n * @returns Array of transactions with their associated signers\n *\n * @throws Error if the group contains 0 transactions\n *\n * @example\n * ```typescript\n * const composer = await deflex.newSwap({ quote, address, slippage, signer })\n * composer.addTransaction(customTxn)\n *\n * // Build the group to inspect transactions before signing\n * const txnsWithSigners = composer.buildGroup()\n * console.log('Group ID:', txnsWithSigners[0].txn.group)\n * console.log('Group length:', txnsWithSigners.length)\n * console.log('Status:', composer.getStatus()) // BUILT\n * ```\n */\n buildGroup(): TransactionWithSigner[] {\n return this.atc.buildGroup()\n }\n\n /**\n * Sign the transaction group\n *\n * Automatically adds swap transactions if not already added, builds the atomic group,\n * and signs all transactions using the configured signer.\n *\n * @returns A promise that resolves to an array of signed transaction blobs\n *\n * @example\n * ```typescript\n * const signedTxns = await composer.sign()\n * ```\n */\n async sign(): Promise<Uint8Array[]> {\n if (this.getStatus() >= SwapComposerStatus.SIGNED) {\n return this.atc.gatherSignatures()\n }\n\n // Auto-add swap transactions if needed\n if (!this.swapTransactionsAdded) {\n await this.addSwapTransactions()\n }\n\n return await this.atc.gatherSignatures()\n }\n\n /**\n * Submit the signed transactions to the network\n *\n * This method signs the transaction group (if not already signed) and submits\n * it to the Algorand network. Does not wait for confirmation.\n *\n * @returns The transaction IDs\n * @throws Error if the transaction group has already been submitted\n *\n * @example\n * ```typescript\n * const txIds = await composer.submit()\n * console.log('Submitted transactions:', txIds)\n * ```\n */\n async submit(): Promise<string[]> {\n // Auto-add swap transactions if needed (maintains backward compatibility)\n if (!this.swapTransactionsAdded) {\n await this.addSwapTransactions()\n }\n\n return this.atc.submit(this.algodClient)\n }\n\n /**\n * Execute the swap\n *\n * Signs the transaction group, submits it to the network, and waits for confirmation.\n * This is the primary method for executing swaps and combines sign(), submit(), and\n * waitForConfirmation() into a single call.\n *\n * @param waitRounds - The number of rounds to wait for confirmation (default: 4)\n * @returns Object containing the confirmed round and transaction IDs\n * @throws Error if the transaction group has already been committed\n *\n * @example\n * ```typescript\n * const result = await composer.execute()\n * console.log(`Confirmed in round ${result.confirmedRound}`)\n * console.log('Transaction IDs:', result.txIds)\n * ```\n */\n async execute(waitRounds: number = DEFAULT_CONFIRMATION_ROUNDS): Promise<{\n confirmedRound: bigint\n txIds: string[]\n methodResults: ABIResult[]\n }> {\n // Auto-add swap transactions if needed (maintains backward compatibility)\n if (!this.swapTransactionsAdded) {\n await this.addSwapTransactions()\n }\n\n const { txIDs, ...result } = await this.atc.execute(\n this.algodClient,\n waitRounds,\n )\n\n return {\n ...result,\n txIds: txIDs,\n }\n }\n\n /**\n * Validates an Algorand address\n */\n private validateAddress(address: string): string {\n if (!isValidAddress(address)) {\n throw new Error(`Invalid Algorand address: ${address}`)\n }\n return address\n }\n\n /**\n * Processes app opt-ins and decodes swap transactions from API response\n */\n private async processSwapTransactions(): Promise<TransactionWithSigner[]> {\n const appOptIns = await this.processRequiredAppOptIns()\n\n const swapTxns: TransactionWithSigner[] = []\n for (let i = 0; i < this.deflexTxns.length; i++) {\n const deflexTxn = this.deflexTxns[i]\n if (!deflexTxn) continue\n\n try {\n const txnBytes = Buffer.from(deflexTxn.data, 'base64')\n const txn = decodeUnsignedTransaction(txnBytes)\n delete txn.group\n\n if (deflexTxn.signature !== false) {\n // Pre-signed transaction - use custom Deflex signer\n swapTxns.push({\n txn,\n signer: this.createDeflexSigner(deflexTxn.signature),\n })\n } else {\n // User transaction - use configured signer\n swapTxns.push({\n txn,\n signer: this.defaultSigner,\n })\n }\n } catch (error) {\n throw new Error(\n `Failed to process swap transaction at index ${i}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return [...appOptIns, ...swapTxns]\n }\n\n /**\n * Creates opt-in transactions for apps the user hasn't opted into yet\n */\n private async processRequiredAppOptIns(): Promise<TransactionWithSigner[]> {\n // Fetch account information\n const accountInfo = await this.algodClient\n .accountInformation(this.address)\n .do()\n\n // Check app opt-ins\n const userApps =\n accountInfo?.appsLocalState?.map((app) => Number(app.id)) || []\n const appsToOptIn = this.requiredAppOptIns.filter(\n (appId) => !userApps.includes(appId),\n )\n\n if (appsToOptIn.length === 0) return []\n\n const suggestedParams = await this.algodClient.getTransactionParams().do()\n\n return appsToOptIn.map((appId) => ({\n txn: makeApplicationOptInTxnFromObject({\n sender: this.address,\n appIndex: appId,\n suggestedParams,\n }),\n signer: this.defaultSigner,\n }))\n }\n\n /**\n * The default signer function that uses the configured signer\n */\n private defaultSigner: TransactionSigner = async (\n txnGroup: Transaction[],\n indexesToSign: number[],\n ) => {\n const result = await this.signer(txnGroup, indexesToSign)\n return result.filter((txn): txn is Uint8Array => txn !== null)\n }\n\n /**\n * Creates a TransactionSigner function for Deflex pre-signed transactions\n */\n private createDeflexSigner(signature: DeflexSignature): TransactionSigner {\n return async (\n txnGroup: Transaction[],\n indexesToSign: number[],\n ): Promise<Uint8Array[]> => {\n return indexesToSign.map((i) => {\n const txn = txnGroup[i]\n if (!txn) throw new Error(`Transaction at index ${i} not found`)\n return this.signDeflexTransaction(txn, signature)\n })\n }\n }\n\n /**\n * Re-signs a Deflex transaction using the provided logic signature or secret key\n */\n private signDeflexTransaction(\n transaction: Transaction,\n signature: DeflexSignature,\n ): Uint8Array {\n try {\n if (signature.type === 'logic_signature') {\n // Decode the signature value to extract the logic signature\n const valueArray = signature.value as Record<string, number>\n const valueBytes = new Uint8Array(Object.values(valueArray))\n const decoded = msgpackRawDecode(valueBytes) as {\n lsig?: { l: Uint8Array; arg?: Uint8Array[] }\n }\n\n if (!decoded.lsig) {\n throw new Error('Logic signature structure missing lsig field')\n }\n\n const lsig = decoded.lsig\n const logicSigAccount = new LogicSigAccount(lsig.l, lsig.arg)\n\n const signedTxn = signLogicSigTransactionObject(\n transaction,\n logicSigAccount,\n )\n return signedTxn.blob\n } else if (signature.type === 'secret_key') {\n // Convert signature.value (Record<string, number>) to Uint8Array\n const valueArray = signature.value as Record<string, number>\n const secretKey = new Uint8Array(Object.values(valueArray))\n const signedTxn = signTransaction(transaction, secretKey)\n return signedTxn.blob\n } else {\n throw new Error(`Unsupported signature type: ${signature.type}`)\n }\n } catch (error) {\n throw new Error(\n `Failed to re-sign transaction: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n /**\n * Execute middleware hooks (beforeSwap or afterSwap)\n */\n private async executeMiddlewareHooks(\n hookName: 'beforeSwap' | 'afterSwap',\n ): Promise<TransactionWithSigner[]> {\n const allTxns: TransactionWithSigner[] = []\n\n // Convert to DeflexQuote if needed\n const quote: DeflexQuote =\n 'createdAt' in this.quote\n ? this.quote\n : {\n ...this.quote,\n quote: this.quote.quote === '' ? 0n : BigInt(this.quote.quote),\n amount: 0n, // Not available in FetchQuoteResponse\n createdAt: Date.now(),\n }\n\n // Create quote context for middleware shouldApply checks\n const quoteContext: QuoteContext = {\n fromASAID: BigInt(this.quote.fromASAID),\n toASAID: BigInt(this.quote.toASAID),\n amount: quote.amount,\n type: this.quote.type as QuoteType,\n address: quote.address,\n algodClient: this.algodClient,\n }\n\n for (const mw of this.middleware) {\n const shouldApply = await mw.shouldApply(quoteContext)\n\n if (!shouldApply || !mw[hookName]) {\n continue\n }\n\n // Create swap context for middleware hooks (only when needed)\n const suggestedParams = await this.algodClient.getTransactionParams().do()\n const swapContext: SwapContext = {\n quote,\n address: this.address,\n algodClient: this.algodClient,\n suggestedParams,\n fromASAID: BigInt(this.quote.fromASAID),\n toASAID: BigInt(this.quote.toASAID),\n signer: this.defaultSigner,\n }\n\n const txns = await mw[hookName](swapContext)\n allTxns.push(...txns)\n }\n\n return allTxns\n }\n}\n","/**\n * HTTP error with status code and response data\n */\nexport class HTTPError extends Error {\n constructor(\n public status: number,\n public statusText: string,\n public data: unknown,\n ) {\n super(`HTTP ${status} ${statusText}`)\n this.name = 'HTTPError'\n }\n}\n\n/**\n * Make an HTTP request and parse JSON response\n *\n * Simple wrapper around native fetch for API calls. Throws HTTPError for\n * non-2xx responses.\n *\n * @param url - The URL to request\n * @param options - Fetch options\n * @returns Parsed JSON response\n * @throws HTTPError if the response status is not ok\n */\nexport async function request<T>(\n url: string,\n options?: RequestInit,\n): Promise<T> {\n const response = await fetch(url, options)\n\n if (!response.ok) {\n let errorData: unknown\n\n try {\n errorData = await response.json()\n } catch {\n try {\n errorData = await response.text()\n } catch {\n errorData = 'Failed to parse error response'\n }\n }\n\n throw new HTTPError(\n response.status,\n response.statusText,\n JSON.stringify(errorData),\n )\n }\n\n return response.json() as Promise<T>\n}\n","import { Algodv2, isValidAddress, type TransactionSigner } from 'algosdk'\nimport { SwapComposer, type SignerFunction } from './composer'\nimport {\n DEFAULT_ALGOD_PORT,\n DEFAULT_ALGOD_TOKEN,\n DEFAULT_ALGOD_URI,\n DEFAULT_API_BASE_URL,\n DEFAULT_AUTO_OPT_IN,\n DEFAULT_FEE_BPS,\n DEFAULT_MAX_DEPTH,\n DEFAULT_MAX_GROUP_SIZE,\n DEPRECATED_PROTOCOLS,\n MAX_FEE_BPS,\n} from './constants'\nimport { request } from './utils'\nimport type { SwapMiddleware } from './middleware'\nimport type {\n FetchQuoteResponse,\n FetchSwapTxnsResponse,\n DeflexConfig,\n DeflexConfigParams,\n FetchSwapTxnsParams,\n FetchSwapTxnsBody,\n FetchQuoteParams,\n DeflexQuote,\n} from './types'\n\n/**\n * Client for interacting with the Deflex order router API\n *\n * The DeflexClient provides methods to fetch swap quotes and create transaction composers\n * for executing swaps on the Algorand blockchain. It handles API communication, transaction\n * validation, and automatic asset/app opt-in detection.\n *\n * @example\n * ```typescript\n * const deflex = new DeflexClient({\n * apiKey: 'your-api-key',\n * })\n * ```\n *\n * @example\n * ```typescript\n * const deflex = new DeflexClient({\n * apiKey: 'your-api-key',\n * apiBaseUrl: 'https://deflex.txnlab.dev',\n * algodUri: 'https://mainnet-api.4160.nodely.dev/',\n * algodToken: '',\n * algodPort: 443,\n * referrerAddress: 'REFERRER_ADDRESS...',\n * feeBps: 15,\n * autoOptIn: false,\n * })\n * ```\n */\nexport class DeflexClient {\n private readonly config: DeflexConfig\n private readonly algodClient: Algodv2\n private readonly middleware: SwapMiddleware[]\n\n /**\n * Create a new DeflexClient instance\n *\n * @param config - Configuration parameters\n * @param config.apiKey - API key for Deflex API (required)\n * @param config.apiBaseUrl - Base URL for the Deflex API (default: https://deflex.txnlab.dev)\n * @param config.algodUri - Algod node URI (default: https://mainnet-api.4160.nodely.dev/)\n * @param config.algodToken - Algod node token (default: '')\n * @param config.algodPort - Algod node port (default: 443)\n * @param config.referrerAddress - Referrer address for fee sharing (receives 25% of swap fees)\n * @param config.feeBps - Fee in basis points (default: 15 = 0.15%, max: 300 = 3.00%)\n * @param config.autoOptIn - Automatically detect and add required opt-in transactions (default: false)\n * @param config.middleware - Array of middleware to apply to swaps (default: [])\n */\n constructor(config: DeflexConfigParams & { middleware?: SwapMiddleware[] }) {\n // Validate and set config\n this.config = {\n apiKey: this.validateApiKey(config.apiKey),\n apiBaseUrl: config.apiBaseUrl ?? DEFAULT_API_BASE_URL,\n algodUri: config.algodUri ?? DEFAULT_ALGOD_URI,\n algodToken: config.algodToken ?? DEFAULT_ALGOD_TOKEN,\n algodPort: config.algodPort ?? DEFAULT_ALGOD_PORT,\n referrerAddress: config.referrerAddress\n ? this.validateAddress(config.referrerAddress)\n : undefined,\n feeBps: this.validateFeeBps(config.feeBps ?? DEFAULT_FEE_BPS),\n autoOptIn: config.autoOptIn ?? DEFAULT_AUTO_OPT_IN,\n }\n\n // Create Algodv2 client\n this.algodClient = new Algodv2(\n this.config.algodToken,\n this.config.algodUri,\n this.config.algodPort,\n )\n\n // Store middleware\n this.middleware = config.middleware ?? []\n }\n\n /**\n * Fetch a swap quote from the Deflex API\n *\n * Requests optimal swap routing from the Deflex API. The quote includes routing\n * information, price impact, required opt-ins, and an encrypted transaction payload.\n *\n * @param params - Parameters for the quote request\n * @param params.fromASAID - The ID of the asset to swap from\n * @param params.toASAID - The ID of the asset to swap to\n * @param params.amount - The amount of the asset to swap in base units\n * @param params.type - The type of the quote (default: 'fixed-input')\n * @param params.disabledProtocols - List of protocols to disable (default: [])\n * @param params.maxGroupSize - The maximum group size (default: 16)\n * @param params.maxDepth - The maximum depth (default: 4)\n * @param params.address - The address of the account that will perform the swap (recommended when using `config.autoOptIn` or `params.optIn`)\n * @param params.optIn - Whether to include asset opt-in transaction\n * - If true: API reduces maxGroupSize by 1 and includes opt-in (always included, even if not needed)\n * - If false: No opt-in transaction included\n * - If undefined: Falls back to `config.autoOptIn` behavior with account check (if `params.address` is provided)\n * @returns A FetchQuoteResponse object with routing information\n *\n * @example\n * ```typescript\n * const quote = await deflex.fetchQuote({\n * address: 'ABC...',\n * fromASAID: 0, // ALGO\n * toASAID: 31566704, // USDC\n * amount: 1_000_000, // 1 ALGO\n * })\n * ```\n */\n async fetchQuote(params: FetchQuoteParams): Promise<FetchQuoteResponse> {\n const {\n fromASAID,\n toASAID,\n amount,\n type = 'fixed-input',\n disabledProtocols = [],\n maxGroupSize = DEFAULT_MAX_GROUP_SIZE,\n maxDepth = DEFAULT_MAX_DEPTH,\n optIn,\n address,\n } = params\n\n // Always include deprecated protocols in disabled list\n const allDisabledProtocols = [\n ...new Set([...DEPRECATED_PROTOCOLS, ...disabledProtocols]),\n ]\n\n let includeOptIn = optIn\n if (includeOptIn === undefined && this.config.autoOptIn) {\n if (address) {\n includeOptIn = await this.needsAssetOptIn(\n this.validateAddress(address),\n toASAID,\n )\n } else {\n console.warn(\n 'autoOptIn is enabled but no address provided to fetchQuote(). Asset opt-in check skipped.',\n )\n }\n }\n\n const url = new URL(`${this.config.apiBaseUrl}/fetchQuote`)\n\n url.searchParams.append('apiKey', this.config.apiKey)\n url.searchParams.append('algodUri', this.config.algodUri)\n url.searchParams.append('algodToken', this.config.algodToken)\n url.searchParams.append('algodPort', String(this.config.algodPort))\n url.searchParams.append('feeBps', this.config.feeBps.toString())\n url.searchParams.append('fromASAID', BigInt(fromASAID).toString())\n url.searchParams.append('toASAID', BigInt(toASAID).toString())\n url.searchParams.append('amount', BigInt(amount).toString())\n url.searchParams.append('type', type)\n url.searchParams.append('disabledProtocols', allDisabledProtocols.join(','))\n url.searchParams.append('maxGroupSize', maxGroupSize.toString())\n url.searchParams.append('maxDepth', maxDepth.toString())\n\n if (typeof includeOptIn === 'boolean') {\n url.searchParams.append('optIn', String(includeOptIn))\n }\n\n if (this.config.referrerAddress) {\n url.searchParams.append('referrerAddress', this.config.referrerAddress)\n }\n\n return request<FetchQuoteResponse>(url.toString())\n }\n\n /**\n * Check if asset opt-in is required for the output asset\n *\n * Convenience method to determine if an address needs to opt into the output asset\n * of a swap. This is useful when you want to get a quote without requiring wallet\n * connection upfront, but need to know whether to set `optIn: true` in fetchQuote()\n * to ensure proper routing (as opt-ins reduce maxGroupSize by 1).\n *\n * Note: If you enable `config.autoOptIn`, this check is handled automatically when\n * an address is provided to fetchQuote().\n *\n * @param address - The address to check\n * @param assetId - The output asset ID to check\n * @returns True if asset opt-in is required, false otherwise (always false for ALGO)\n *\n * @example\n * ```typescript\n * // Check if opt-in needed for output asset before fetching quote\n * const needsOptIn = await deflex.needsAssetOptIn(userAddress, toAssetId)\n * const quote = await deflex.fetchQuote({\n * fromAssetId,\n * toAssetId,\n * amount,\n * optIn: needsOptIn,\n * })\n * ```\n */\n async needsAssetOptIn(\n address: string,\n assetId: number | bigint,\n ): Promise<boolean> {\n // Fetch account information\n const accountInfo = await this.algodClient.accountInformation(address).do()\n\n // Check if asset opt-in is required\n return (\n BigInt(assetId) !== 0n &&\n accountInfo?.assets?.find(\n (asset) => asset.assetId === BigInt(assetId),\n ) === undefined\n )\n }\n\n /**\n * Fetch swap transactions from the Deflex API\n *\n * Decrypts the quote payload and generates executable swap transactions for the\n * specified signer address with the given slippage tolerance.\n *\n * @param params - Parameters for the swap transaction request\n * @param params.quote - The quote response from fetchQuote()\n * @param params.address - The address of the signer\n * @param params.slippage - The slippage tolerance as a percentage (e.g., 1 for 1%)\n * @returns A FetchSwapTxnsResponse object with transaction data\n */\n async fetchSwapTransactions(\n params: FetchSwapTxnsParams,\n ): Promise<FetchSwapTxnsResponse> {\n const { quote, address, slippage } = params\n\n // Validate signer address\n this.validateAddress(address)\n\n const url = new URL(`${this.config.apiBaseUrl}/fetchExecuteSwapTxns`)\n\n const body: FetchSwapTxnsBody = {\n apiKey: this.config.apiKey,\n address,\n txnPayloadJSON: quote.txnPayload,\n slippage,\n }\n\n return request<FetchSwapTxnsResponse>(url.toString(), {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n })\n }\n\n /**\n * Fetch a quote and return an enhanced quote result\n *\n * This is the recommended way to fetch quotes. It returns an object that\n * extends the raw API response with additional metadata and type normalization.\n *\n * @param params - Parameters for the quote request\n * @param params.fromASAID - The ID of the asset to swap from\n * @param params.toASAID - The ID of the asset to swap to\n * @param params.amount - The amount of the asset to swap in base units\n * @param params.type - The type of the quote (default: 'fixed-input')\n * @param params.disabledProtocols - List of protocols to disable (default: [])\n * @param params.maxGroupSize - The maximum group size (default: 16)\n * @param params.maxDepth - The maximum depth (default: 4)\n * @param params.address - The address of the account that will perform the swap (recommended when using `config.autoOptIn` or `params.optIn`)\n * @param params.optIn - Whether to include asset opt-in transaction\n * @returns A DeflexQuote enhanced quote result\n *\n * @example\n * ```typescript\n * const quote = await deflex.newQuote({\n * address: 'ABC...',\n * fromASAID: 0,\n * toASAID: 31566704,\n * amount: 1_000_000,\n * })\n *\n * console.log(quote.quote) // bigint - quoted amount\n * console.log(quote.fromASAID) // number - input asset ID\n * console.log(quote.toASAID) // number - output asset ID\n * console.log(quote.amount) // bigint - original request amount\n * console.log(quote.createdAt) // number - timestamp\n * ```\n */\n async newQuote(params: FetchQuoteParams): Promise<DeflexQuote> {\n // Apply middleware transformations to quote params\n let adjustedParams = { ...params }\n\n // Create quote context for middleware\n const quoteContext = {\n fromASAID: BigInt(params.fromASAID),\n toASAID: BigInt(params.toASAID),\n amount: BigInt(params.amount),\n type: params.type ?? ('fixed-input' as const),\n address: params.address ?? undefined,\n algodClient: this.algodClient,\n }\n\n for (const mw of this.middleware) {\n const shouldApply = await mw.shouldApply(quoteContext)\n\n if (shouldApply && mw.adjustQuoteParams) {\n adjustedParams = await mw.adjustQuoteParams(adjustedParams)\n }\n }\n\n const response = await this.fetchQuote(adjustedParams)\n\n return {\n ...response,\n quote: response.quote === '' ? 0n : BigInt(response.quote),\n amount: BigInt(params.amount),\n address: params.address ?? undefined,\n createdAt: Date.now(),\n }\n }\n\n /**\n * Create a SwapComposer instance\n *\n * This factory method creates a composer that allows you to add custom transactions\n * before and after the swap transactions, with automatic handling of pre-signed transactions\n * and opt-ins.\n *\n * @param config.quote - The quote result from newQuote() or raw API response from fetchQuote()\n * @param config.address - The address of the signer\n * @param config.slippage - The slippage tolerance\n * @param config.signer - Transaction signer function\n * @returns A SwapComposer instance ready for building transaction groups\n *\n * @example\n * ```typescript\n * // Basic swap\n * const quote = await deflex.newQuote({ ... })\n * await deflex.newSwap({ quote, address, slippage, signer })\n * .execute()\n * ```\n *\n * @example\n * ```typescript\n * // Advanced swap with custom transactions\n * const quote = await deflex.newQuote({ ... })\n * const swap = await deflex.newSwap({\n * quote,\n * address,\n * slippage,\n * signer,\n * })\n *\n * console.log(swap.getStatus()) // BUILDING\n *\n * const signedTxns = await swap\n * .addTransaction(beforeTxn)\n * .addSwapTransactions() // Adds swap transactions to the group\n * .addTransaction(afterTxn)\n * .sign()\n *\n * console.log(swap.getStatus()) // SIGNED\n *\n * const result = await swap.execute(waitRounds)\n * console.log(result.confirmedRound, result.txIds)\n *\n * console.log(swap.getStatus()) // COMMITTED\n * ```\n */\n async newSwap(config: {\n quote: DeflexQuote | FetchQuoteResponse\n address: string\n slippage: number\n signer: TransactionSigner | SignerFunction\n }): Promise<SwapComposer> {\n const { quote, address, slippage, signer } = config\n\n const swapResponse = await this.fetchSwapTransactions({\n quote,\n address,\n slippage,\n })\n\n // Create the composer\n const composer = new SwapComposer({\n quote,\n deflexTxns: swapResponse.txns,\n algodClient: this.algodClient,\n address,\n signer,\n middleware: this.middleware,\n })\n\n return composer\n }\n\n /**\n * Validates the API key\n */\n private validateApiKey(apiKey: string): string {\n if (!apiKey) {\n throw new Error('API key is required')\n }\n return apiKey\n }\n\n /**\n * Validates an Algorand address\n */\n private validateAddress(address: string): string {\n if (!isValidAddress(address)) {\n throw new Error(`Invalid Algorand address: ${address}`)\n }\n return address\n }\n\n /**\n * Validates the fee in basis points (max 300 = 3.00%)\n */\n private validateFeeBps(feeBps: number): number {\n if (feeBps < 0 || feeBps > MAX_FEE_BPS) {\n throw new Error(\n `Invalid fee: ${feeBps} basis points (must be between 0 and ${MAX_FEE_BPS})`,\n )\n }\n return feeBps\n }\n}\n","import {\n makeAssetTransferTxnWithSuggestedParamsFromObject,\n type Algodv2,\n type SuggestedParams,\n type TransactionSigner,\n type TransactionWithSigner,\n} from 'algosdk'\nimport type { DeflexQuote, FetchQuoteParams, QuoteType } from './types'\n\n/**\n * Context provided to middleware shouldApply hook\n */\nexport interface QuoteContext {\n /** Input asset ID (always bigint for precision and future-proofing) */\n readonly fromASAID: bigint\n /** Output asset ID (always bigint for precision and future-proofing) */\n readonly toASAID: bigint\n /** Amount to swap (always bigint for precision and future-proofing) */\n readonly amount: bigint\n /** Quote type */\n readonly type: QuoteType\n /** Address of the account that will perform the swap (if provided) */\n readonly address?: string\n /** Algodv2 client instance for making additional queries */\n readonly algodClient: Algodv2\n}\n\n/**\n * Context provided to middleware hooks during swap composition\n */\nexport interface SwapContext {\n /** The quote result from newQuote() */\n readonly quote: DeflexQuote\n /** The address of the account performing the swap */\n readonly address: string\n /** Algodv2 client instance for making additional queries/transactions */\n readonly algodClient: Algodv2\n /** Suggested transaction parameters from the network */\n readonly suggestedParams: SuggestedParams\n /** Input asset ID (always bigint for precision and future-proofing) */\n readonly fromASAID: bigint\n /** Output asset ID (always bigint for precision and future-proofing) */\n readonly toASAID: bigint\n /** Transaction signer for transactions that need to be signed by the user */\n readonly signer: TransactionSigner\n}\n\n/**\n * Middleware interface for extending Deflex swap functionality\n *\n * Middleware allows you to modify quote parameters and inject additional transactions\n * into the atomic swap group. This is useful for assets that require special handling,\n * such as those with transfer restrictions, taxes, or custom smart contract logic.\n *\n * @example\n * ```typescript\n * class CustomAssetMiddleware implements SwapMiddleware {\n * readonly name = 'CustomAsset'\n * readonly version = '1.0.0'\n *\n * async shouldApply(context) {\n * return context.fromASAID === CUSTOM_ASSET_ID || context.toASAID === CUSTOM_ASSET_ID\n * }\n *\n * async adjustQuoteParams(params) {\n * // Reduce maxGroupSize to account for extra transactions\n * return { ...params, maxGroupSize: params.maxGroupSize - 3 }\n * }\n *\n * async beforeSwap(context) {\n * // Return transactions to add before the swap\n * return [unfreezeTransaction]\n * }\n *\n * async afterSwap(context) {\n * // Return transactions to add after the swap\n * return [taxTransaction, refreezeTransaction]\n * }\n * }\n * ```\n */\nexport interface SwapMiddleware {\n /** Unique identifier for the middleware */\n readonly name: string\n\n /** Semantic version of the middleware */\n readonly version: string\n\n /**\n * Determines if this middleware should be applied to the given swap\n *\n * Called during both quote and swap phases. Use this to check if either\n * the input or output asset requires special handling.\n *\n * @param context - Quote context with asset IDs, amount, type, address, and algod client\n * @returns True if middleware should be applied\n *\n * @example\n * ```typescript\n * async shouldApply(context) {\n * // Check if asset is registered in our smart contract\n * const assetInfo = await this.getAssetInfo(context.fromASAID)\n * return assetInfo !== null\n * }\n * ```\n */\n shouldApply(context: QuoteContext): Promise<boolean>\n\n /**\n * Modify quote parameters before fetching the quote\n *\n * **IMPORTANT**: If your middleware adds transactions via `beforeSwap` or `afterSwap`,\n * you MUST reduce `maxGroupSize` accordingly to prevent failures. The Deflex API may\n * return routes that use all 16 available transaction slots.\n *\n * Use this to adjust the quote request based on your asset's requirements.\n * Common adjustments include:\n * - Reducing `maxGroupSize` to account for additional transactions (REQUIRED if adding txns)\n * - Adjusting `amount` to account for fees/taxes\n * - Modifying `disabledProtocols` if certain DEXs are incompatible\n *\n * @param params - Original quote parameters\n * @returns Modified quote parameters\n *\n * @example\n * ```typescript\n * async adjustQuoteParams(params) {\n * const [fromTaxed, toTaxed] = await Promise.all([\n * this.isAssetTaxed(params.fromASAID),\n * this.isAssetTaxed(params.toASAID),\n * ])\n *\n * // 3 extra transactions per taxed asset\n * let maxGroupSize = params.maxGroupSize ?? 16\n * if (fromTaxed) maxGroupSize -= 3\n * if (toTaxed) maxGroupSize -= 3\n *\n * // Adjust amount for input tax\n * let amount = params.amount\n * if (fromTaxed) {\n * const taxRate = await this.getTaxRate(params.fromASAID)\n * amount = this.applyTax(amount, taxRate)\n * }\n *\n * return { ...params, maxGroupSize, amount }\n * }\n * ```\n */\n adjustQuoteParams?(params: FetchQuoteParams): Promise<FetchQuoteParams>\n\n /**\n * Add transactions before the swap transactions\n *\n * Called when building the swap transaction group. Transactions are added\n * to the group in the order they appear in the returned array.\n *\n * Transaction order in final group: [beforeSwap] → [swap txns] → [afterSwap]\n *\n * @param context - Swap context with quote, address, and algod client\n * @returns Array of transactions with signers to add before swap\n *\n * @example\n * ```typescript\n * async beforeSwap(context) {\n * const txns: TransactionWithSigner[] = []\n *\n * // Unfreeze user account before swap\n * if (await this.needsUnfreeze(context.fromASAID)) {\n * const unfreezeCall = makeApplicationNoOpTxn(\n * context.address,\n * this.appId,\n * ...,\n * context.suggestedParams\n * )\n *\n * txns.push({\n * txn: unfreezeCall,\n * signer: context.signer, // Use the signer from context\n * })\n * }\n *\n * return txns\n * }\n * ```\n */\n beforeSwap?(context: SwapContext): Promise<TransactionWithSigner[]>\n\n /**\n * Add transactions after the swap transactions\n *\n * Called when building the swap transaction group. Transactions are added\n * to the group in the order they appear in the returned array.\n *\n * Transaction order in final group: [beforeSwap] → [swap txns] → [afterSwap]\n *\n * @param context - Swap context with quote, address, and algod client\n * @returns Array of transactions with signers to add after swap\n *\n * @example\n * ```typescript\n * async afterSwap(context) {\n * const txns: TransactionWithSigner[] = []\n *\n * // Pay tax and refreeze account\n * if (await this.isTaxed(context.fromASAID)) {\n * const taxAmount = await this.calculateTax(context)\n * const taxPayment = makeAssetTransferTxn(\n * context.address,\n * this.taxReceiver,\n * taxAmount,\n * context.fromASAID,\n * context.suggestedParams\n * )\n * const refreezeCall = makeApplicationNoOpTxn(\n * context.address,\n * this.appId,\n * ...,\n * context.suggestedParams\n * )\n *\n * txns.push(\n * { txn: taxPayment, signer: context.signer },\n * { txn: refreezeCall, signer: context.signer },\n * )\n * }\n *\n * return txns\n * }\n * ```\n */\n afterSwap?(context: SwapContext): Promise<TransactionWithSigner[]>\n}\n\n/**\n * Configuration options for AutoOptOutMiddleware\n */\nexport interface AutoOptOutConfig {\n /**\n * Array of asset IDs that should be excluded from automatic opt-out behavior\n * @default []\n */\n readonly excludedAssets?: readonly (number | bigint)[]\n}\n\n/**\n * Middleware that automatically adds an asset opt-out transaction when swapping\n * the full balance of an input asset, leaving it with a zero balance.\n *\n * @example\n * ```typescript\n * import { DeflexClient, AutoOptOutMiddleware } from '@txnlab/deflex'\n *\n * const autoOptOut = new AutoOptOutMiddleware({\n * excludedAssets: [31566704], // Don't auto-opt-out of USDC\n * })\n *\n * const deflex = new DeflexClient({\n * apiKey: 'your-api-key',\n * middleware: [autoOptOut],\n * })\n *\n * // When swapping full balance, opt-out transaction is automatically added\n * const quote = await deflex.newQuote({\n * address: userAddress,\n * fromASAID: someAssetId,\n * toASAID: 0,\n * amount: fullBalance, // If this equals account's full balance, opt-out is added\n * type: 'fixed-input',\n * })\n * ```\n */\nexport class AutoOptOutMiddleware implements SwapMiddleware {\n readonly name = 'AutoOptOut'\n readonly version = '1.0.0'\n\n private readonly excludedAssets: Set<bigint>\n\n constructor(config: AutoOptOutConfig = {}) {\n this.excludedAssets = new Set(\n (config.excludedAssets ?? []).map((id) => BigInt(id)),\n )\n }\n\n async shouldApply(context: QuoteContext): Promise<boolean> {\n // Only apply for fixed-input swaps\n if (context.type !== 'fixed-input') {\n return false\n }\n\n // Must have an address to check balance\n if (!context.address) {\n return false\n }\n\n // Don't opt-out of ALGO (asset ID 0)\n if (context.fromASAID === 0n) {\n return false\n }\n\n // Check if asset is in excluded list\n if (this.excludedAssets.has(context.fromASAID)) {\n return false\n }\n\n try {\n // Get account info to check current balance\n const accountInfo = await context.algodClient\n .accountInformation(context.address)\n .do()\n\n // Find the asset in account's holdings\n const assetHolding = accountInfo.assets?.find(\n (asset) => asset.assetId === context.fromASAID,\n )\n\n // If asset not found, don't opt-out\n if (!assetHolding) {\n return false\n }\n\n // Check if swap amount equals current balance\n return assetHolding.amount === context.amount\n } catch (error) {\n // If we can't fetch account info, don't apply middleware\n console.warn(\n `AutoOptOutMiddleware: Failed to fetch account info for ${context.address}:`,\n error,\n )\n return false\n }\n }\n\n async adjustQuoteParams(params: FetchQuoteParams): Promise<FetchQuoteParams> {\n // Reduce maxGroupSize by 1 to make room for the opt-out transaction\n const maxGroupSize = (params.maxGroupSize ?? 16) - 1\n\n return {\n ...params,\n maxGroupSize,\n }\n }\n\n async afterSwap(context: SwapContext): Promise<TransactionWithSigner[]> {\n // Create asset opt-out transaction (send 0 amount with closeRemainderTo = sender)\n const optOutTxn = makeAssetTransferTxnWithSuggestedParamsFromObject({\n sender: context.address,\n receiver: context.address,\n amount: 0n,\n assetIndex: context.fromASAID,\n closeRemainderTo: context.address,\n suggestedParams: context.suggestedParams,\n })\n\n return [\n {\n txn: optOutTxn,\n signer: context.signer,\n },\n ]\n }\n}\n"],"mappings":";;;;;;AAGA,IAAY,gDAAL;AACL;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQF,MAAa,uBAAuB,CAAC,UAAU,UAAU;;AAGzD,MAAa,oBAAoB;;AAGjC,MAAa,sBAAsB;;AAGnC,MAAa,qBAAqB;;AAGlC,MAAa,uBAAuB;;AAGpC,MAAa,kBAAkB;;AAG/B,MAAa,cAAc;;AAG3B,MAAa,yBAAyB;;AAGtC,MAAa,oBAAoB;;AAGjC,MAAa,sBAAsB;;AAGnC,MAAa,8BAA8B;;;;;;;ACL3C,IAAY,oEAAL;;AAEL;;AAGA;;AAGA;;AAGA;;AAGA;;;;;;;;;;;;;;;;;;;;;AAuCF,IAAa,eAAb,MAAa,aAAa;;CAExB,AAAQ,MAAM,IAAI,2BAA2B;;CAG7C,OAAO,iBAAyB,0BAA0B;;CAG1D,AAAQ,wBAAwB;CAEhC,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;;;;;;;;;;;;;;;CAgBjB,YAAY,QAA4B;AAEtC,MAAI,CAAC,OAAO,MACV,OAAM,IAAI,MAAM,oBAAoB;AAEtC,MAAI,CAAC,OAAO,WACV,OAAM,IAAI,MAAM,iCAAiC;AAEnD,MAAI,OAAO,WAAW,WAAW,EAC/B,OAAM,IAAI,MAAM,0CAA0C;AAE5D,MAAI,CAAC,OAAO,YACV,OAAM,IAAI,MAAM,sCAAsC;AAExD,MAAI,CAAC,OAAO,OACV,OAAM,IAAI,MAAM,qBAAqB;AAGvC,OAAK,QAAQ,OAAO;AACpB,OAAK,oBAAoB,OAAO,MAAM;AACtC,OAAK,aAAa,OAAO;AACzB,OAAK,cAAc,OAAO;AAC1B,OAAK,UAAU,KAAK,gBAAgB,OAAO,QAAQ;AACnD,OAAK,SAAS,OAAO;AACrB,OAAK,aAAa,OAAO,cAAc,EAAE;;;;;;;CAQ3C,YAAgC;AAC9B,SAAO,KAAK,IAAI,WAAW;;;;;;;CAQ7B,QAAgB;AACd,SAAO,KAAK,IAAI,OAAO;;;;;;;;;;;;;;;;;;CAmBzB,eAAe,aAA0B,SAAS,KAAK,eAAqB;AAC1E,OAAK,IAAI,eAAe;GAAE,KAAK;GAAa;GAAQ,CAAC;AACrD,SAAO;;;;;;;;;;;;;CAcT,cAAc,YAAwB,SAAS,KAAK,eAAqB;AACvE,OAAK,IAAI,cAAc;GACrB,GAAG;GACH,QAAQ,WAAW,UAAU;GAC9B,CAAC;AACF,SAAO;;;;;;;;;;;;;;;;;;CAmBT,MAAM,sBAAqC;AACzC,MAAI,KAAK,sBACP,OAAM,IAAI,MAAM,4CAA4C;AAG9D,MAAI,KAAK,WAAW,KAAK,mBAAmB,SAC1C,OAAM,IAAI,MACR,oEACD;EAIH,MAAM,aAAa,MAAM,KAAK,uBAAuB,aAAa;AAGlE,MAAI,KAAK,IAAI,OAAO,GAAG,WAAW,SAAS,aAAa,eACtD,OAAM,IAAI,MACR,2EAA2E,aAAa,iBACzF;AAGH,OAAK,MAAM,iBAAiB,WAC1B,MAAK,IAAI,eAAe,cAAc;EAIxC,MAAM,gBAAgB,MAAM,KAAK,yBAAyB;EAC1D,MAAM,YAAY,MAAM,KAAK,uBAAuB,YAAY;AAMhE,MAFE,KAAK,IAAI,OAAO,GAAG,cAAc,SAAS,UAAU,SAEpC,aAAa,eAC7B,OAAM,IAAI,MACR,qEAAqE,aAAa,iBACnF;AAIH,OAAK,MAAM,iBAAiB,cAC1B,MAAK,IAAI,eAAe,cAAc;AAIxC,OAAK,MAAM,iBAAiB,UAC1B,MAAK,IAAI,eAAe,cAAc;AAGxC,OAAK,wBAAwB;AAC7B,SAAO;;;;;;;;;;;;;;;;;;;;;;;;;CA0BT,aAAsC;AACpC,SAAO,KAAK,IAAI,YAAY;;;;;;;;;;;;;;;CAgB9B,MAAM,OAA8B;AAClC,MAAI,KAAK,WAAW,IAAI,mBAAmB,OACzC,QAAO,KAAK,IAAI,kBAAkB;AAIpC,MAAI,CAAC,KAAK,sBACR,OAAM,KAAK,qBAAqB;AAGlC,SAAO,MAAM,KAAK,IAAI,kBAAkB;;;;;;;;;;;;;;;;;CAkB1C,MAAM,SAA4B;AAEhC,MAAI,CAAC,KAAK,sBACR,OAAM,KAAK,qBAAqB;AAGlC,SAAO,KAAK,IAAI,OAAO,KAAK,YAAY;;;;;;;;;;;;;;;;;;;;CAqB1C,MAAM,QAAQ,aAAqB,6BAIhC;AAED,MAAI,CAAC,KAAK,sBACR,OAAM,KAAK,qBAAqB;EAGlC,MAAM,EAAE,MAAO,GAAG,WAAW,MAAM,KAAK,IAAI,QAC1C,KAAK,aACL,WACD;AAED,SAAO;GACL,GAAG;GACH,OAAO;GACR;;;;;CAMH,AAAQ,gBAAgB,SAAyB;AAC/C,MAAI,CAAC,eAAe,QAAQ,CAC1B,OAAM,IAAI,MAAM,6BAA6B,UAAU;AAEzD,SAAO;;;;;CAMT,MAAc,0BAA4D;EACxE,MAAM,YAAY,MAAM,KAAK,0BAA0B;EAEvD,MAAMA,WAAoC,EAAE;AAC5C,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,WAAW,QAAQ,KAAK;GAC/C,MAAM,YAAY,KAAK,WAAW;AAClC,OAAI,CAAC,UAAW;AAEhB,OAAI;IAEF,MAAM,MAAM,0BADK,OAAO,KAAK,UAAU,MAAM,SAAS,CACP;AAC/C,WAAO,IAAI;AAEX,QAAI,UAAU,cAAc,MAE1B,UAAS,KAAK;KACZ;KACA,QAAQ,KAAK,mBAAmB,UAAU,UAAU;KACrD,CAAC;QAGF,UAAS,KAAK;KACZ;KACA,QAAQ,KAAK;KACd,CAAC;YAEG,OAAO;AACd,UAAM,IAAI,MACR,+CAA+C,EAAE,IAAI,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAC5G;;;AAIL,SAAO,CAAC,GAAG,WAAW,GAAG,SAAS;;;;;CAMpC,MAAc,2BAA6D;EAOzE,MAAM,YALc,MAAM,KAAK,YAC5B,mBAAmB,KAAK,QAAQ,CAChC,IAAI,GAIQ,gBAAgB,KAAK,QAAQ,OAAO,IAAI,GAAG,CAAC,IAAI,EAAE;EACjE,MAAM,cAAc,KAAK,kBAAkB,QACxC,UAAU,CAAC,SAAS,SAAS,MAAM,CACrC;AAED,MAAI,YAAY,WAAW,EAAG,QAAO,EAAE;EAEvC,MAAM,kBAAkB,MAAM,KAAK,YAAY,sBAAsB,CAAC,IAAI;AAE1E,SAAO,YAAY,KAAK,WAAW;GACjC,KAAK,kCAAkC;IACrC,QAAQ,KAAK;IACb,UAAU;IACV;IACD,CAAC;GACF,QAAQ,KAAK;GACd,EAAE;;;;;CAML,AAAQ,gBAAmC,OACzC,UACA,kBACG;AAEH,UADe,MAAM,KAAK,OAAO,UAAU,cAAc,EAC3C,QAAQ,QAA2B,QAAQ,KAAK;;;;;CAMhE,AAAQ,mBAAmB,WAA+C;AACxE,SAAO,OACL,UACA,kBAC0B;AAC1B,UAAO,cAAc,KAAK,MAAM;IAC9B,MAAM,MAAM,SAAS;AACrB,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,wBAAwB,EAAE,YAAY;AAChE,WAAO,KAAK,sBAAsB,KAAK,UAAU;KACjD;;;;;;CAON,AAAQ,sBACN,aACA,WACY;AACZ,MAAI;AACF,OAAI,UAAU,SAAS,mBAAmB;IAExC,MAAM,aAAa,UAAU;IAE7B,MAAM,UAAU,iBADG,IAAI,WAAW,OAAO,OAAO,WAAW,CAAC,CAChB;AAI5C,QAAI,CAAC,QAAQ,KACX,OAAM,IAAI,MAAM,+CAA+C;IAGjE,MAAM,OAAO,QAAQ;AAOrB,WAJkB,8BAChB,aAHsB,IAAI,gBAAgB,KAAK,GAAG,KAAK,IAAI,CAK5D,CACgB;cACR,UAAU,SAAS,cAAc;IAE1C,MAAM,aAAa,UAAU;AAG7B,WADkB,gBAAgB,aADhB,IAAI,WAAW,OAAO,OAAO,WAAW,CAAC,CACF,CACxC;SAEjB,OAAM,IAAI,MAAM,+BAA+B,UAAU,OAAO;WAE3D,OAAO;AACd,SAAM,IAAI,MACR,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACzF;;;;;;CAOL,MAAc,uBACZ,UACkC;EAClC,MAAMC,UAAmC,EAAE;EAG3C,MAAMC,QACJ,eAAe,KAAK,QAChB,KAAK,QACL;GACE,GAAG,KAAK;GACR,OAAO,KAAK,MAAM,UAAU,KAAK,KAAK,OAAO,KAAK,MAAM,MAAM;GAC9D,QAAQ;GACR,WAAW,KAAK,KAAK;GACtB;EAGP,MAAMC,eAA6B;GACjC,WAAW,OAAO,KAAK,MAAM,UAAU;GACvC,SAAS,OAAO,KAAK,MAAM,QAAQ;GACnC,QAAQ,MAAM;GACd,MAAM,KAAK,MAAM;GACjB,SAAS,MAAM;GACf,aAAa,KAAK;GACnB;AAED,OAAK,MAAM,MAAM,KAAK,YAAY;AAGhC,OAAI,CAFgB,MAAM,GAAG,YAAY,aAAa,IAElC,CAAC,GAAG,UACtB;GAIF,MAAM,kBAAkB,MAAM,KAAK,YAAY,sBAAsB,CAAC,IAAI;GAC1E,MAAMC,cAA2B;IAC/B;IACA,SAAS,KAAK;IACd,aAAa,KAAK;IAClB;IACA,WAAW,OAAO,KAAK,MAAM,UAAU;IACvC,SAAS,OAAO,KAAK,MAAM,QAAQ;IACnC,QAAQ,KAAK;IACd;GAED,MAAM,OAAO,MAAM,GAAG,UAAU,YAAY;AAC5C,WAAQ,KAAK,GAAG,KAAK;;AAGvB,SAAO;;;;;;;;;ACplBX,IAAa,YAAb,cAA+B,MAAM;CACnC,YACE,AAAOC,QACP,AAAOC,YACP,AAAOC,MACP;AACA,QAAM,QAAQ,OAAO,GAAG,aAAa;EAJ9B;EACA;EACA;AAGP,OAAK,OAAO;;;;;;;;;;;;;;AAehB,eAAsB,QACpB,KACA,SACY;CACZ,MAAM,WAAW,MAAM,MAAM,KAAK,QAAQ;AAE1C,KAAI,CAAC,SAAS,IAAI;EAChB,IAAIC;AAEJ,MAAI;AACF,eAAY,MAAM,SAAS,MAAM;UAC3B;AACN,OAAI;AACF,gBAAY,MAAM,SAAS,MAAM;WAC3B;AACN,gBAAY;;;AAIhB,QAAM,IAAI,UACR,SAAS,QACT,SAAS,YACT,KAAK,UAAU,UAAU,CAC1B;;AAGH,QAAO,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACIxB,IAAa,eAAb,MAA0B;CACxB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;;;;;;;;;;;;;;;CAgBjB,YAAY,QAAgE;AAE1E,OAAK,SAAS;GACZ,QAAQ,KAAK,eAAe,OAAO,OAAO;GAC1C,YAAY,OAAO,cAAc;GACjC,UAAU,OAAO,YAAY;GAC7B,YAAY,OAAO,cAAc;GACjC,WAAW,OAAO,aAAa;GAC/B,iBAAiB,OAAO,kBACpB,KAAK,gBAAgB,OAAO,gBAAgB,GAC5C;GACJ,QAAQ,KAAK,eAAe,OAAO,UAAU,gBAAgB;GAC7D,WAAW,OAAO,aAAa;GAChC;AAGD,OAAK,cAAc,IAAI,QACrB,KAAK,OAAO,YACZ,KAAK,OAAO,UACZ,KAAK,OAAO,UACb;AAGD,OAAK,aAAa,OAAO,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkC3C,MAAM,WAAW,QAAuD;EACtE,MAAM,EACJ,WACA,SACA,QACA,OAAO,eACP,oBAAoB,EAAE,EACtB,eAAe,wBACf,WAAW,mBACX,OACA,YACE;EAGJ,MAAM,uBAAuB,CAC3B,GAAG,IAAI,IAAI,CAAC,GAAG,sBAAsB,GAAG,kBAAkB,CAAC,CAC5D;EAED,IAAI,eAAe;AACnB,MAAI,iBAAiB,UAAa,KAAK,OAAO,UAC5C,KAAI,QACF,gBAAe,MAAM,KAAK,gBACxB,KAAK,gBAAgB,QAAQ,EAC7B,QACD;MAED,SAAQ,KACN,4FACD;EAIL,MAAM,MAAM,IAAI,IAAI,GAAG,KAAK,OAAO,WAAW,aAAa;AAE3D,MAAI,aAAa,OAAO,UAAU,KAAK,OAAO,OAAO;AACrD,MAAI,aAAa,OAAO,YAAY,KAAK,OAAO,SAAS;AACzD,MAAI,aAAa,OAAO,cAAc,KAAK,OAAO,WAAW;AAC7D,MAAI,aAAa,OAAO,aAAa,OAAO,KAAK,OAAO,UAAU,CAAC;AACnE,MAAI,aAAa,OAAO,UAAU,KAAK,OAAO,OAAO,UAAU,CAAC;AAChE,MAAI,aAAa,OAAO,aAAa,OAAO,UAAU,CAAC,UAAU,CAAC;AAClE,MAAI,aAAa,OAAO,WAAW,OAAO,QAAQ,CAAC,UAAU,CAAC;AAC9D,MAAI,aAAa,OAAO,UAAU,OAAO,OAAO,CAAC,UAAU,CAAC;AAC5D,MAAI,aAAa,OAAO,QAAQ,KAAK;AACrC,MAAI,aAAa,OAAO,qBAAqB,qBAAqB,KAAK,IAAI,CAAC;AAC5E,MAAI,aAAa,OAAO,gBAAgB,aAAa,UAAU,CAAC;AAChE,MAAI,aAAa,OAAO,YAAY,SAAS,UAAU,CAAC;AAExD,MAAI,OAAO,iBAAiB,UAC1B,KAAI,aAAa,OAAO,SAAS,OAAO,aAAa,CAAC;AAGxD,MAAI,KAAK,OAAO,gBACd,KAAI,aAAa,OAAO,mBAAmB,KAAK,OAAO,gBAAgB;AAGzE,SAAO,QAA4B,IAAI,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BpD,MAAM,gBACJ,SACA,SACkB;EAElB,MAAM,cAAc,MAAM,KAAK,YAAY,mBAAmB,QAAQ,CAAC,IAAI;AAG3E,SACE,OAAO,QAAQ,KAAK,MACpB,aAAa,QAAQ,MAClB,UAAU,MAAM,YAAY,OAAO,QAAQ,CAC7C,KAAK;;;;;;;;;;;;;;CAgBV,MAAM,sBACJ,QACgC;EAChC,MAAM,EAAE,OAAO,SAAS,aAAa;AAGrC,OAAK,gBAAgB,QAAQ;EAE7B,MAAM,MAAM,IAAI,IAAI,GAAG,KAAK,OAAO,WAAW,uBAAuB;EAErE,MAAMC,OAA0B;GAC9B,QAAQ,KAAK,OAAO;GACpB;GACA,gBAAgB,MAAM;GACtB;GACD;AAED,SAAO,QAA+B,IAAI,UAAU,EAAE;GACpD,QAAQ;GACR,SAAS,EACP,gBAAgB,oBACjB;GACD,MAAM,KAAK,UAAU,KAAK;GAC3B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCJ,MAAM,SAAS,QAAgD;EAE7D,IAAI,iBAAiB,EAAE,GAAG,QAAQ;EAGlC,MAAM,eAAe;GACnB,WAAW,OAAO,OAAO,UAAU;GACnC,SAAS,OAAO,OAAO,QAAQ;GAC/B,QAAQ,OAAO,OAAO,OAAO;GAC7B,MAAM,OAAO,QAAS;GACtB,SAAS,OAAO,WAAW;GAC3B,aAAa,KAAK;GACnB;AAED,OAAK,MAAM,MAAM,KAAK,WAGpB,KAFoB,MAAM,GAAG,YAAY,aAAa,IAEnC,GAAG,kBACpB,kBAAiB,MAAM,GAAG,kBAAkB,eAAe;EAI/D,MAAM,WAAW,MAAM,KAAK,WAAW,eAAe;AAEtD,SAAO;GACL,GAAG;GACH,OAAO,SAAS,UAAU,KAAK,KAAK,OAAO,SAAS,MAAM;GAC1D,QAAQ,OAAO,OAAO,OAAO;GAC7B,SAAS,OAAO,WAAW;GAC3B,WAAW,KAAK,KAAK;GACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmDH,MAAM,QAAQ,QAKY;EACxB,MAAM,EAAE,OAAO,SAAS,UAAU,WAAW;AAkB7C,SATiB,IAAI,aAAa;GAChC;GACA,aATmB,MAAM,KAAK,sBAAsB;IACpD;IACA;IACA;IACD,CAAC,EAKyB;GACzB,aAAa,KAAK;GAClB;GACA;GACA,YAAY,KAAK;GAClB,CAAC;;;;;CAQJ,AAAQ,eAAe,QAAwB;AAC7C,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,sBAAsB;AAExC,SAAO;;;;;CAMT,AAAQ,gBAAgB,SAAyB;AAC/C,MAAI,CAAC,eAAe,QAAQ,CAC1B,OAAM,IAAI,MAAM,6BAA6B,UAAU;AAEzD,SAAO;;;;;CAMT,AAAQ,eAAe,QAAwB;AAC7C,MAAI,SAAS,KAAK,SAAS,YACzB,OAAM,IAAI,MACR,gBAAgB,OAAO,uCAAuC,YAAY,GAC3E;AAEH,SAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1KX,IAAa,uBAAb,MAA4D;CAC1D,AAAS,OAAO;CAChB,AAAS,UAAU;CAEnB,AAAiB;CAEjB,YAAY,SAA2B,EAAE,EAAE;AACzC,OAAK,iBAAiB,IAAI,KACvB,OAAO,kBAAkB,EAAE,EAAE,KAAK,OAAO,OAAO,GAAG,CAAC,CACtD;;CAGH,MAAM,YAAY,SAAyC;AAEzD,MAAI,QAAQ,SAAS,cACnB,QAAO;AAIT,MAAI,CAAC,QAAQ,QACX,QAAO;AAIT,MAAI,QAAQ,cAAc,GACxB,QAAO;AAIT,MAAI,KAAK,eAAe,IAAI,QAAQ,UAAU,CAC5C,QAAO;AAGT,MAAI;GAOF,MAAM,gBALc,MAAM,QAAQ,YAC/B,mBAAmB,QAAQ,QAAQ,CACnC,IAAI,EAG0B,QAAQ,MACtC,UAAU,MAAM,YAAY,QAAQ,UACtC;AAGD,OAAI,CAAC,aACH,QAAO;AAIT,UAAO,aAAa,WAAW,QAAQ;WAChC,OAAO;AAEd,WAAQ,KACN,0DAA0D,QAAQ,QAAQ,IAC1E,MACD;AACD,UAAO;;;CAIX,MAAM,kBAAkB,QAAqD;EAE3E,MAAM,gBAAgB,OAAO,gBAAgB,MAAM;AAEnD,SAAO;GACL,GAAG;GACH;GACD;;CAGH,MAAM,UAAU,SAAwD;AAWtE,SAAO,CACL;GACE,KAXc,kDAAkD;IAClE,QAAQ,QAAQ;IAChB,UAAU,QAAQ;IAClB,QAAQ;IACR,YAAY,QAAQ;IACpB,kBAAkB,QAAQ;IAC1B,iBAAiB,QAAQ;IAC1B,CAAC;GAKE,QAAQ,QAAQ;GACjB,CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@txnlab/deflex",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "TypeScript/JavaScript SDK for Deflex Order Router - smart order routing and DEX aggregation on Algorand",
5
5
  "keywords": [
6
6
  "algorand",