@txnlab/deflex 1.0.0-beta.3 → 1.0.0-beta.5

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
@@ -57,18 +57,25 @@ const deflex = new DeflexClient({
57
57
  apiKey: 'your-api-key',
58
58
  })
59
59
 
60
- // Advanced configuration
60
+ // Custom Algod configuration
61
61
  const deflex = new DeflexClient({
62
62
  apiKey: 'your-api-key',
63
63
  algodUri: 'https://mainnet-api.4160.nodely.dev/',
64
64
  algodToken: '',
65
65
  algodPort: 443,
66
- referrerAddress: '<referrer_address>', // Earns 25% of swap fees
67
- feeBps: 15, // 0.15% fee (max: 300 = 3%)
68
66
  autoOptIn: true, // Automatically handle asset opt-ins
69
67
  })
68
+
69
+ // Earn fees with the referral program
70
+ const deflex = new DeflexClient({
71
+ apiKey: 'your-api-key',
72
+ referrerAddress: 'YOUR_ALGORAND_ADDRESS', // Earns 25% of swap fees
73
+ feeBps: 15, // 0.15% fee (max: 300 = 3%)
74
+ })
70
75
  ```
71
76
 
77
+ By providing your Algorand address as the `referrerAddress` when initializing the client, you can earn 25% of the swap fees generated through your integration. Set the `feeBps` parameter to specify the total fee charged to users (default: 0.15%, max: 3.00%). Learn more about the [Deflex Referral Program](https://txnlab.gitbook.io/deflex-api/referral-treasury/referral-program).
78
+
72
79
  ### Get a Swap Quote
73
80
 
74
81
  The [`newQuote()`](#deflexclientnewquote) method returns a [`DeflexQuote`](#deflexquote) object:
@@ -106,7 +113,7 @@ console.log('Transaction IDs:', result.txIds)
106
113
 
107
114
  ### Transaction Signing
108
115
 
109
- The SDK supports two types of transaction signers that must be passed to `newSwap()`:
116
+ The SDK supports both standard `algosdk.TransactionSigner` and ARC-1 compliant signer functions.
110
117
 
111
118
  #### 1. use-wallet Signer (Recommended)
112
119
 
@@ -130,13 +137,26 @@ await swap.execute()
130
137
 
131
138
  #### 2. Custom Signer Function
132
139
 
133
- ```typescript
134
- // Custom signer function signature:
135
- // (txns: Transaction[]) => Promise<Uint8Array[]>
140
+ The SDK accepts custom signer functions that receive the complete transaction group and an array of indexes indicating which transactions need signing:
136
141
 
137
- const customSigner = async (txns) => {
138
- // Your custom signing logic here
139
- const signedTxns = await yourWalletProvider.signTransactions(txns)
142
+ ```typescript
143
+ import { Address, encodeUnsignedTransaction, type Transaction } from 'algosdk'
144
+
145
+ // Example: Wrapping an ARC-1 compliant wallet
146
+ const customSigner = async (
147
+ txnGroup: Transaction[],
148
+ indexesToSign: number[],
149
+ ) => {
150
+ // Convert to wallet's expected format
151
+ const walletTxns = txnGroup.map((txn, index) => ({
152
+ txn: Buffer.from(encodeUnsignedTransaction(txn)).toString('base64'),
153
+ signers: indexesToSign.includes(index)
154
+ ? [Address.fromString(activeAddress)]
155
+ : [],
156
+ }))
157
+
158
+ // Sign with wallet provider
159
+ const signedTxns = await walletProvider.signTxns(walletTxns)
140
160
 
141
161
  return signedTxns
142
162
  }
@@ -150,7 +170,11 @@ const swap = await deflex.newSwap({
150
170
  await swap.execute()
151
171
  ```
152
172
 
153
- > **Note**: The custom signer function must return an array of `Uint8Array` where each element is a signed transaction.
173
+ The signer function supports two return patterns:
174
+ - **Pattern 1** (Pera, Defly, algosdk): Returns only the signed transactions as `Uint8Array[]`
175
+ - **Pattern 2** (Lute, ARC-1 compliant): Returns an array matching the transaction group length with `null` for unsigned transactions as `(Uint8Array | null)[]`
176
+
177
+ Both patterns are automatically handled by the SDK.
154
178
 
155
179
  ### Advanced Transaction Composition
156
180
 
@@ -282,12 +306,12 @@ Returns a [`SwapComposer`](#swapcomposer) instance for building and executing sw
282
306
  async newSwap(config: SwapComposerConfig): Promise<SwapComposer>
283
307
  ```
284
308
 
285
- | Parameter | Description | Type |
286
- | ---------- | ------------------------------------------------- | --------------------------------------------------------------------------------------- |
287
- | `quote` | Quote result or raw API response | `DeflexQuote \| FetchQuoteResponse` |
288
- | `address` | Signer address | `string` |
289
- | `slippage` | Slippage tolerance as percentage (e.g., 1 for 1%) | `number` |
290
- | `signer` | Transaction signer function | `algosdk.TransactionSigner \| ((txns: algosdk.Transaction[]) => Promise<Uint8Array[]>)` |
309
+ | Parameter | Description | Type |
310
+ | ---------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
311
+ | `quote` | Quote result or raw API response | `DeflexQuote \| FetchQuoteResponse` |
312
+ | `address` | Signer address | `string` |
313
+ | `slippage` | Slippage tolerance as percentage (e.g., 1 for 1%) | `number` |
314
+ | `signer` | Transaction signer function | `algosdk.TransactionSigner \| ((txnGroup: Transaction[], indexesToSign: number[]) => Promise<(Uint8Array \| null)[]>)` |
291
315
 
292
316
  #### DeflexClient.needsAssetOptIn()
293
317
 
package/dist/index.d.ts CHANGED
@@ -291,13 +291,14 @@ interface SwapTransaction {
291
291
  //#endregion
292
292
  //#region src/composer.d.ts
293
293
  /**
294
- * A signer function for signing transaction groups
294
+ * A transaction signer function that supports both standard algosdk.TransactionSigner
295
+ * and ARC-1 compliant signers that may return null for unsigned transactions.
295
296
  *
296
- * Can be either:
297
- * - A TransactionSigner: algosdk.TransactionSigner
298
- * - A simpler inline function that only accepts the transaction group
297
+ * @param txnGroup - The complete transaction group to sign
298
+ * @param indexesToSign - Array of indexes indicating which transactions need signing
299
+ * @returns Array of signed transactions (may include nulls for ARC-1 compliant wallets)
299
300
  */
300
- type SignerFunction = TransactionSigner | ((txns: Transaction[]) => Promise<Uint8Array[]>);
301
+ type SignerFunction = (txnGroup: Transaction[], indexesToSign: number[]) => Promise<(Uint8Array | null)[]>;
301
302
  /**
302
303
  * Status of the SwapComposer transaction group lifecycle
303
304
  */
@@ -326,7 +327,7 @@ interface SwapComposerConfig {
326
327
  /** The address of the account that will sign transactions */
327
328
  readonly address: string;
328
329
  /** Transaction signer function */
329
- readonly signer: SignerFunction;
330
+ readonly signer: TransactionSigner | SignerFunction;
330
331
  }
331
332
  /**
332
333
  * Composer for building and executing atomic swap transaction groups
@@ -695,7 +696,7 @@ declare class DeflexClient {
695
696
  quote: DeflexQuote | FetchQuoteResponse;
696
697
  address: string;
697
698
  slippage: number;
698
- signer: SignerFunction;
699
+ signer: TransactionSigner | SignerFunction;
699
700
  }): Promise<SwapComposer>;
700
701
  /**
701
702
  * Validates the API key
@@ -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/composer.ts","../src/client.ts","../src/utils.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -190,39 +190,31 @@ var SwapComposer = class SwapComposer {
190
190
  if (this.status >= SwapComposerStatus.SIGNED) return this.signedTxns;
191
191
  if (!this.swapTransactionsAdded) await this.addSwapTransactions();
192
192
  const transactions = this.buildGroup();
193
- const userTransactions = [];
194
- const userTransactionIndexes = [];
195
- const deflexSignedTxns = [];
193
+ const txnGroup = [];
194
+ const indexesToSign = [];
196
195
  for (let i = 0; i < transactions.length; i++) {
197
196
  const item = transactions[i];
198
197
  if (!item) continue;
199
- if (!item.deflexSignature) {
200
- userTransactions.push(item.txn);
201
- userTransactionIndexes.push(userTransactions.length - 1);
202
- } else {
203
- const signedTxnBlob = this.signDeflexTransaction(item.txn, item.deflexSignature);
204
- deflexSignedTxns.push(signedTxnBlob);
205
- }
198
+ txnGroup.push(item.txn);
199
+ if (!item.deflexSignature) indexesToSign.push(i);
206
200
  }
207
- let userSignedTxns = [];
208
- if (userTransactions.length > 0) userSignedTxns = await this.signer(userTransactions, userTransactionIndexes);
209
- const signedTxns = [];
201
+ const userSignedTxns = (await this.signer(txnGroup, indexesToSign)).filter((txn) => txn !== null);
202
+ const finalSignedTxns = [];
210
203
  let userSignedIndex = 0;
211
- let deflexSignedIndex = 0;
212
- for (const item of transactions) if (!item.deflexSignature) {
213
- const signedTxn = userSignedTxns[userSignedIndex];
214
- if (signedTxn) signedTxns.push(signedTxn);
215
- userSignedIndex++;
204
+ for (const item of transactions) if (item.deflexSignature) {
205
+ const signedTxnBlob = this.signDeflexTransaction(item.txn, item.deflexSignature);
206
+ finalSignedTxns.push(signedTxnBlob);
216
207
  } else {
217
- const deflexSignedTxn = deflexSignedTxns[deflexSignedIndex];
218
- if (deflexSignedTxn) signedTxns.push(deflexSignedTxn);
219
- deflexSignedIndex++;
208
+ const userSignedTxn = userSignedTxns[userSignedIndex];
209
+ if (!userSignedTxn) throw new Error(`Missing signature for user transaction at index ${userSignedIndex}`);
210
+ finalSignedTxns.push(userSignedTxn);
211
+ userSignedIndex++;
220
212
  }
221
213
  const txIds = this.transactions.map((t) => t.txn.txID());
222
- this.signedTxns = signedTxns;
214
+ this.signedTxns = finalSignedTxns;
223
215
  this.txIds = txIds;
224
216
  this.status = SwapComposerStatus.SIGNED;
225
- return signedTxns;
217
+ return finalSignedTxns;
226
218
  }
227
219
  /**
228
220
  * Submit the signed transactions to the network
@@ -512,7 +504,7 @@ var DeflexClient = class {
512
504
  url.searchParams.append("disabledProtocols", allDisabledProtocols.join(","));
513
505
  url.searchParams.append("maxGroupSize", maxGroupSize.toString());
514
506
  url.searchParams.append("maxDepth", maxDepth.toString());
515
- url.searchParams.append("optIn", String(includeOptIn));
507
+ if (typeof includeOptIn === "boolean") url.searchParams.append("optIn", String(includeOptIn));
516
508
  if (this.config.referrerAddress) url.searchParams.append("referrerAddress", this.config.referrerAddress);
517
509
  return request(url.toString());
518
510
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["userTransactions: Transaction[]","userTransactionIndexes: number[]","deflexSignedTxns: Uint8Array[]","userSignedTxns: Uint8Array[]","signedTxns: Uint8Array[]","appOptIns: SwapTransaction[]","swapTxns: SwapTransaction[]","appOptInTxns: Transaction[]","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 assignGroupID,\n decodeUnsignedTransaction,\n isValidAddress,\n signLogicSigTransactionObject,\n signTransaction,\n LogicSigAccount,\n makeApplicationOptInTxnFromObject,\n msgpackRawDecode,\n Transaction,\n waitForConfirmation,\n} from 'algosdk'\nimport { DEFAULT_CONFIRMATION_ROUNDS } from './constants'\nimport type {\n FetchQuoteResponse,\n DeflexTransaction,\n SwapTransaction,\n DeflexSignature,\n DeflexQuote,\n} from './types'\nimport type { AlgorandClient } from '@algorandfoundation/algokit-utils'\nimport type { TransactionSigner } from 'algosdk'\n\n/**\n * A signer function for signing transaction groups\n *\n * Can be either:\n * - A TransactionSigner: algosdk.TransactionSigner\n * - A simpler inline function that only accepts the transaction group\n */\nexport type SignerFunction =\n | TransactionSigner\n | ((txns: Transaction[]) => Promise<Uint8Array[]>)\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 /** AlgorandClient instance for blockchain operations */\n readonly algorand: AlgorandClient\n /** The address of the account that will sign transactions */\n readonly address: string\n /** Transaction signer function */\n readonly signer: 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 })\n *\n * await composer\n * .addTransaction(customTxn)\n * .addSwapTransactions()\n * .execute(signer)\n * ```\n */\nexport class SwapComposer {\n /** The maximum size of an atomic transaction group. */\n static MAX_GROUP_SIZE: number = 16\n\n private status: SwapComposerStatus = SwapComposerStatus.BUILDING\n private transactions: SwapTransaction[] = []\n private swapTransactionsAdded = false\n private signedTxns: Uint8Array[] = []\n private txIds: string[] = []\n\n private readonly requiredAppOptIns: number[]\n private readonly deflexTxns: DeflexTransaction[]\n private readonly algorand: AlgorandClient\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.algorand - AlgorandClient instance for blockchain operations\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.algorand) {\n throw new Error('AlgorandClient 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.algorand = config.algorand\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.status\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.transactions.length\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): this {\n if (this.status !== SwapComposerStatus.BUILDING) {\n throw new Error(\n 'Cannot add transactions when composer status is not BUILDING',\n )\n }\n\n if (this.transactions.length === SwapComposer.MAX_GROUP_SIZE) {\n throw new Error(\n `Adding an additional transaction exceeds the maximum atomic group size of ${SwapComposer.MAX_GROUP_SIZE}`,\n )\n }\n\n this.transactions.push({ txn: transaction })\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.status !== 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.transactions.length + 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 this.transactions.push(...processedTxns)\n\n this.swapTransactionsAdded = true\n return this\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.status >= SwapComposerStatus.SIGNED) {\n return this.signedTxns\n }\n\n // Auto-add swap transactions if needed\n if (!this.swapTransactionsAdded) {\n await this.addSwapTransactions()\n }\n\n // Build the transaction group, ensure status is BUILT\n const transactions = this.buildGroup()\n\n // Separate user transactions and pre-signed transactions\n const userTransactions: Transaction[] = []\n const userTransactionIndexes: number[] = []\n const deflexSignedTxns: Uint8Array[] = []\n\n for (let i = 0; i < transactions.length; i++) {\n const item = transactions[i]\n if (!item) continue\n\n if (!item.deflexSignature) {\n // User transaction - needs user signature\n userTransactions.push(item.txn)\n userTransactionIndexes.push(userTransactions.length - 1)\n } else {\n // Pre-signed transaction - re-sign with Deflex signature\n const signedTxnBlob = this.signDeflexTransaction(\n item.txn,\n item.deflexSignature,\n )\n deflexSignedTxns.push(signedTxnBlob)\n }\n }\n\n // Sign user transactions\n let userSignedTxns: Uint8Array[] = []\n if (userTransactions.length > 0) {\n userSignedTxns = await (this.signer as TransactionSigner)(\n userTransactions,\n userTransactionIndexes,\n )\n }\n\n // Combine user-signed and pre-signed transactions in correct order\n const signedTxns: Uint8Array[] = []\n let userSignedIndex = 0\n let deflexSignedIndex = 0\n\n for (const item of transactions) {\n if (!item.deflexSignature) {\n const signedTxn = userSignedTxns[userSignedIndex]\n if (signedTxn) {\n signedTxns.push(signedTxn)\n }\n userSignedIndex++\n } else {\n const deflexSignedTxn = deflexSignedTxns[deflexSignedIndex]\n if (deflexSignedTxn) {\n signedTxns.push(deflexSignedTxn)\n }\n deflexSignedIndex++\n }\n }\n\n const txIds = this.transactions.map((t) => t.txn.txID())\n\n this.signedTxns = signedTxns\n this.txIds = txIds\n this.status = SwapComposerStatus.SIGNED\n\n return signedTxns\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 if (this.status > SwapComposerStatus.SUBMITTED) {\n throw new Error('Transaction group cannot be resubmitted')\n }\n\n const stxns = await this.sign()\n await this.algorand.client.algod.sendRawTransaction(stxns).do()\n\n this.status = SwapComposerStatus.SUBMITTED\n return this.txIds\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 }> {\n if (this.status === SwapComposerStatus.COMMITTED) {\n throw new Error(\n 'Transaction group has already been executed successfully',\n )\n }\n\n const txIds = await this.submit()\n\n const confirmedTxnInfo = await waitForConfirmation(\n this.algorand.client.algod,\n txIds[0]!,\n waitRounds,\n )\n\n this.status = SwapComposerStatus.COMMITTED\n\n const confirmedRound = confirmedTxnInfo.confirmedRound!\n\n return {\n confirmedRound,\n 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<SwapTransaction[]> {\n // Process required app opt-ins\n const appOptIns: SwapTransaction[] = await this.processRequiredAppOptIns()\n\n // Decode and process swap transactions from API\n const swapTxns: SwapTransaction[] = []\n for (let i = 0; i < this.deflexTxns.length; i++) {\n const deflexTxn = this.deflexTxns[i]\n if (!deflexTxn) continue\n\n try {\n // Decode transaction from base64 data\n const txnBytes = Buffer.from(deflexTxn.data, 'base64')\n const txn = decodeUnsignedTransaction(txnBytes)\n\n // Remove group ID (will be reassigned later)\n delete txn.group\n\n if (deflexTxn.signature !== false) {\n // Pre-signed transaction - needs re-signing with provided signature\n swapTxns.push({\n txn,\n deflexSignature: deflexTxn.signature,\n })\n } else {\n // User transaction - needs user signature\n swapTxns.push({\n txn,\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<SwapTransaction[]> {\n // Fetch account information\n const accountInfo = await this.algorand.account.getInformation(this.address)\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 // Create opt-in transactions if needed\n const appOptInTxns: Transaction[] = []\n if (appsToOptIn.length > 0) {\n const suggestedParams = await this.algorand.client.algod\n .getTransactionParams()\n .do()\n\n for (const appId of appsToOptIn) {\n const optInTxn = makeApplicationOptInTxnFromObject({\n sender: this.address,\n appIndex: appId,\n suggestedParams,\n })\n appOptInTxns.push(optInTxn)\n }\n }\n\n return appOptInTxns.map((txn) => ({ txn }))\n }\n\n /**\n * Finalizes the transaction group by assigning group IDs\n *\n * The composer's status will be at least BUILT after executing this method.\n */\n private buildGroup(): SwapTransaction[] {\n if (this.status === SwapComposerStatus.BUILDING) {\n if (this.transactions.length === 0) {\n throw new Error('Cannot build a group with 0 transactions')\n }\n if (this.transactions.length > 1) {\n assignGroupID(this.transactions.map((t) => t.txn))\n }\n this.status = SwapComposerStatus.BUILT\n }\n return this.transactions\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 { AlgorandClient } from '@algorandfoundation/algokit-utils'\nimport { isValidAddress } 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 * 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 baseUrl: string = DEFAULT_API_BASE_URL\n private readonly config: DeflexConfig\n private readonly algorand: AlgorandClient\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.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 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 AlgorandClient\n this.algorand = AlgorandClient.fromConfig({\n algodConfig: {\n server: this.config.algodUri,\n port: this.config.algodPort,\n token: this.config.algodToken,\n },\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.baseUrl}/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 url.searchParams.append('optIn', String(includeOptIn))\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.algorand.account.getInformation(address)\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.baseUrl}/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: 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 algorand: this.algorand,\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":["txnGroup: Transaction[]","indexesToSign: number[]","finalSignedTxns: Uint8Array[]","appOptIns: SwapTransaction[]","swapTxns: SwapTransaction[]","appOptInTxns: Transaction[]","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 assignGroupID,\n decodeUnsignedTransaction,\n isValidAddress,\n signLogicSigTransactionObject,\n signTransaction,\n LogicSigAccount,\n makeApplicationOptInTxnFromObject,\n msgpackRawDecode,\n Transaction,\n waitForConfirmation,\n} from 'algosdk'\nimport { DEFAULT_CONFIRMATION_ROUNDS } from './constants'\nimport type {\n FetchQuoteResponse,\n DeflexTransaction,\n SwapTransaction,\n DeflexSignature,\n DeflexQuote,\n} from './types'\nimport type { AlgorandClient } from '@algorandfoundation/algokit-utils'\nimport type { TransactionSigner } from 'algosdk'\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 /** AlgorandClient instance for blockchain operations */\n readonly algorand: AlgorandClient\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 })\n *\n * await composer\n * .addTransaction(customTxn)\n * .addSwapTransactions()\n * .execute(signer)\n * ```\n */\nexport class SwapComposer {\n /** The maximum size of an atomic transaction group. */\n static MAX_GROUP_SIZE: number = 16\n\n private status: SwapComposerStatus = SwapComposerStatus.BUILDING\n private transactions: SwapTransaction[] = []\n private swapTransactionsAdded = false\n private signedTxns: Uint8Array[] = []\n private txIds: string[] = []\n\n private readonly requiredAppOptIns: number[]\n private readonly deflexTxns: DeflexTransaction[]\n private readonly algorand: AlgorandClient\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.algorand - AlgorandClient instance for blockchain operations\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.algorand) {\n throw new Error('AlgorandClient 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.algorand = config.algorand\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.status\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.transactions.length\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): this {\n if (this.status !== SwapComposerStatus.BUILDING) {\n throw new Error(\n 'Cannot add transactions when composer status is not BUILDING',\n )\n }\n\n if (this.transactions.length === SwapComposer.MAX_GROUP_SIZE) {\n throw new Error(\n `Adding an additional transaction exceeds the maximum atomic group size of ${SwapComposer.MAX_GROUP_SIZE}`,\n )\n }\n\n this.transactions.push({ txn: transaction })\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.status !== 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.transactions.length + 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 this.transactions.push(...processedTxns)\n\n this.swapTransactionsAdded = true\n return this\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.status >= SwapComposerStatus.SIGNED) {\n return this.signedTxns\n }\n\n // Auto-add swap transactions if needed\n if (!this.swapTransactionsAdded) {\n await this.addSwapTransactions()\n }\n\n // Build the transaction group, ensure status is BUILT\n const transactions = this.buildGroup()\n\n // Collect all transactions and identify which ones need user signature\n const txnGroup: Transaction[] = []\n const indexesToSign: number[] = []\n\n for (let i = 0; i < transactions.length; i++) {\n const item = transactions[i]\n if (!item) continue\n\n txnGroup.push(item.txn)\n\n if (!item.deflexSignature) {\n // User transaction - needs user signature\n indexesToSign.push(i)\n }\n }\n\n // Sign all transactions with the complete group\n const signedTxns = await this.signer(txnGroup, indexesToSign)\n\n // Normalize signedTxns - handle both wallet patterns:\n // Pattern 1: Returns only signed txns (length < txnGroup.length)\n // Pattern 2: Returns array matching group length with nulls for non-signed (ARC-1)\n const userSignedTxns = signedTxns.filter(\n (txn): txn is Uint8Array => txn !== null,\n )\n\n // Rebuild complete group in correct order\n const finalSignedTxns: Uint8Array[] = []\n let userSignedIndex = 0\n\n for (const item of transactions) {\n if (item.deflexSignature) {\n // Pre-signed transaction - re-sign with Deflex signature\n const signedTxnBlob = this.signDeflexTransaction(\n item.txn,\n item.deflexSignature,\n )\n finalSignedTxns.push(signedTxnBlob)\n } else {\n // User transaction - use signature from signer\n const userSignedTxn = userSignedTxns[userSignedIndex]\n if (!userSignedTxn) {\n throw new Error(\n `Missing signature for user transaction at index ${userSignedIndex}`,\n )\n }\n finalSignedTxns.push(userSignedTxn)\n userSignedIndex++\n }\n }\n\n const txIds = this.transactions.map((t) => t.txn.txID())\n\n this.signedTxns = finalSignedTxns\n this.txIds = txIds\n this.status = SwapComposerStatus.SIGNED\n\n return finalSignedTxns\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 if (this.status > SwapComposerStatus.SUBMITTED) {\n throw new Error('Transaction group cannot be resubmitted')\n }\n\n const stxns = await this.sign()\n await this.algorand.client.algod.sendRawTransaction(stxns).do()\n\n this.status = SwapComposerStatus.SUBMITTED\n return this.txIds\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 }> {\n if (this.status === SwapComposerStatus.COMMITTED) {\n throw new Error(\n 'Transaction group has already been executed successfully',\n )\n }\n\n const txIds = await this.submit()\n\n const confirmedTxnInfo = await waitForConfirmation(\n this.algorand.client.algod,\n txIds[0]!,\n waitRounds,\n )\n\n this.status = SwapComposerStatus.COMMITTED\n\n const confirmedRound = confirmedTxnInfo.confirmedRound!\n\n return {\n confirmedRound,\n 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<SwapTransaction[]> {\n // Process required app opt-ins\n const appOptIns: SwapTransaction[] = await this.processRequiredAppOptIns()\n\n // Decode and process swap transactions from API\n const swapTxns: SwapTransaction[] = []\n for (let i = 0; i < this.deflexTxns.length; i++) {\n const deflexTxn = this.deflexTxns[i]\n if (!deflexTxn) continue\n\n try {\n // Decode transaction from base64 data\n const txnBytes = Buffer.from(deflexTxn.data, 'base64')\n const txn = decodeUnsignedTransaction(txnBytes)\n\n // Remove group ID (will be reassigned later)\n delete txn.group\n\n if (deflexTxn.signature !== false) {\n // Pre-signed transaction - needs re-signing with provided signature\n swapTxns.push({\n txn,\n deflexSignature: deflexTxn.signature,\n })\n } else {\n // User transaction - needs user signature\n swapTxns.push({\n txn,\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<SwapTransaction[]> {\n // Fetch account information\n const accountInfo = await this.algorand.account.getInformation(this.address)\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 // Create opt-in transactions if needed\n const appOptInTxns: Transaction[] = []\n if (appsToOptIn.length > 0) {\n const suggestedParams = await this.algorand.client.algod\n .getTransactionParams()\n .do()\n\n for (const appId of appsToOptIn) {\n const optInTxn = makeApplicationOptInTxnFromObject({\n sender: this.address,\n appIndex: appId,\n suggestedParams,\n })\n appOptInTxns.push(optInTxn)\n }\n }\n\n return appOptInTxns.map((txn) => ({ txn }))\n }\n\n /**\n * Finalizes the transaction group by assigning group IDs\n *\n * The composer's status will be at least BUILT after executing this method.\n */\n private buildGroup(): SwapTransaction[] {\n if (this.status === SwapComposerStatus.BUILDING) {\n if (this.transactions.length === 0) {\n throw new Error('Cannot build a group with 0 transactions')\n }\n if (this.transactions.length > 1) {\n assignGroupID(this.transactions.map((t) => t.txn))\n }\n this.status = SwapComposerStatus.BUILT\n }\n return this.transactions\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 { AlgorandClient } from '@algorandfoundation/algokit-utils'\nimport { 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 * 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 baseUrl: string = DEFAULT_API_BASE_URL\n private readonly config: DeflexConfig\n private readonly algorand: AlgorandClient\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.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 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 AlgorandClient\n this.algorand = AlgorandClient.fromConfig({\n algodConfig: {\n server: this.config.algodUri,\n port: this.config.algodPort,\n token: this.config.algodToken,\n },\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.baseUrl}/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.algorand.account.getInformation(address)\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.baseUrl}/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 algorand: this.algorand,\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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@txnlab/deflex",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.0.0-beta.5",
4
4
  "description": "TypeScript/JavaScript SDK for Deflex Order Router - smart order routing and DEX aggregation on Algorand",
5
5
  "keywords": [
6
6
  "algorand",