@txnlab/deflex 1.1.0 → 1.3.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 +86 -30
- package/dist/index.d.ts +334 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +164 -86
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts.map
CHANGED
|
@@ -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":";;;;;;AAGY,aAAA,QAAA;EAcC,SAAA,GAAA,WAAqD;EAGrD,MAAA,GAAA,QAAA;EAGA,QAAA,GAAA,UAAA;EAGA,IAAA,GAAA,MAAA;EAGA,KAAA,GAAA,OAAA;EAGA,KAAA,GAAA,OAAA;AAGb;AAGA;AAGA;AAGA;AAGA;;cA9Ba;;
|
|
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, LogicSigAccount, Transaction,
|
|
1
|
+
import { Algodv2, AtomicTransactionComposer, LogicSigAccount, Transaction, decodeUnsignedTransaction, isValidAddress, makeApplicationOptInTxnFromObject, msgpackRawDecode, signLogicSigTransactionObject, signTransaction } from "algosdk";
|
|
2
2
|
|
|
3
3
|
//#region src/constants.ts
|
|
4
4
|
/**
|
|
@@ -68,27 +68,28 @@ let SwapComposerStatus = /* @__PURE__ */ function(SwapComposerStatus$1) {
|
|
|
68
68
|
* @example
|
|
69
69
|
* ```typescript
|
|
70
70
|
* const quote = await deflex.fetchQuote({ ... })
|
|
71
|
-
* const composer = await deflex.newSwap({ quote, address, slippage })
|
|
71
|
+
* const composer = await deflex.newSwap({ quote, address, slippage, signer })
|
|
72
72
|
*
|
|
73
73
|
* await composer
|
|
74
74
|
* .addTransaction(customTxn)
|
|
75
75
|
* .addSwapTransactions()
|
|
76
|
-
* .execute(
|
|
76
|
+
* .execute()
|
|
77
77
|
* ```
|
|
78
78
|
*/
|
|
79
79
|
var SwapComposer = class SwapComposer {
|
|
80
|
+
/** The ATC used to compose the group */
|
|
81
|
+
atc = new AtomicTransactionComposer();
|
|
80
82
|
/** The maximum size of an atomic transaction group. */
|
|
81
|
-
static MAX_GROUP_SIZE =
|
|
82
|
-
|
|
83
|
-
transactions = [];
|
|
83
|
+
static MAX_GROUP_SIZE = AtomicTransactionComposer.MAX_GROUP_SIZE;
|
|
84
|
+
/** Whether the swap transactions have been added to the atomic group. */
|
|
84
85
|
swapTransactionsAdded = false;
|
|
85
|
-
|
|
86
|
-
txIds = [];
|
|
86
|
+
quote;
|
|
87
87
|
requiredAppOptIns;
|
|
88
88
|
deflexTxns;
|
|
89
89
|
algodClient;
|
|
90
90
|
address;
|
|
91
91
|
signer;
|
|
92
|
+
middleware;
|
|
92
93
|
/**
|
|
93
94
|
* Create a new SwapComposer instance
|
|
94
95
|
*
|
|
@@ -96,11 +97,12 @@ var SwapComposer = class SwapComposer {
|
|
|
96
97
|
* this directly, as the factory method handles fetching swap transactions automatically.
|
|
97
98
|
*
|
|
98
99
|
* @param config - Configuration for the composer
|
|
99
|
-
* @param config.
|
|
100
|
+
* @param config.quote - The quote response from fetchQuote()
|
|
100
101
|
* @param config.deflexTxns - The swap transactions from fetchSwapTransactions()
|
|
101
102
|
* @param config.algodClient - Algodv2 client instance
|
|
102
103
|
* @param config.address - The address of the account that will sign transactions
|
|
103
104
|
* @param config.signer - Transaction signer function
|
|
105
|
+
* @param config.middleware - Middleware to apply during swap composition
|
|
104
106
|
*/
|
|
105
107
|
constructor(config) {
|
|
106
108
|
if (!config.quote) throw new Error("Quote is required");
|
|
@@ -108,11 +110,13 @@ var SwapComposer = class SwapComposer {
|
|
|
108
110
|
if (config.deflexTxns.length === 0) throw new Error("Swap transactions array cannot be empty");
|
|
109
111
|
if (!config.algodClient) throw new Error("Algodv2 client instance is required");
|
|
110
112
|
if (!config.signer) throw new Error("Signer is required");
|
|
113
|
+
this.quote = config.quote;
|
|
111
114
|
this.requiredAppOptIns = config.quote.requiredAppOptIns;
|
|
112
115
|
this.deflexTxns = config.deflexTxns;
|
|
113
116
|
this.algodClient = config.algodClient;
|
|
114
117
|
this.address = this.validateAddress(config.address);
|
|
115
118
|
this.signer = config.signer;
|
|
119
|
+
this.middleware = config.middleware ?? [];
|
|
116
120
|
}
|
|
117
121
|
/**
|
|
118
122
|
* Get the status of this composer's transaction group
|
|
@@ -120,7 +124,7 @@ var SwapComposer = class SwapComposer {
|
|
|
120
124
|
* @returns The current status of the transaction group
|
|
121
125
|
*/
|
|
122
126
|
getStatus() {
|
|
123
|
-
return this.
|
|
127
|
+
return this.atc.getStatus();
|
|
124
128
|
}
|
|
125
129
|
/**
|
|
126
130
|
* Get the number of transactions currently in this atomic group
|
|
@@ -128,7 +132,7 @@ var SwapComposer = class SwapComposer {
|
|
|
128
132
|
* @returns The number of transactions in the group
|
|
129
133
|
*/
|
|
130
134
|
count() {
|
|
131
|
-
return this.
|
|
135
|
+
return this.atc.count();
|
|
132
136
|
}
|
|
133
137
|
/**
|
|
134
138
|
* Add a transaction to the atomic group
|
|
@@ -146,17 +150,41 @@ var SwapComposer = class SwapComposer {
|
|
|
146
150
|
* @throws Error if the composer is not in the BUILDING status
|
|
147
151
|
* @throws Error if the maximum group size is exceeded
|
|
148
152
|
*/
|
|
149
|
-
addTransaction(transaction) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
addTransaction(transaction, signer = this.defaultSigner) {
|
|
154
|
+
this.atc.addTransaction({
|
|
155
|
+
txn: transaction,
|
|
156
|
+
signer
|
|
157
|
+
});
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Add a method call to the atomic group
|
|
162
|
+
*
|
|
163
|
+
* The `signer` property in the `methodCall` parameter is optional. If not provided,
|
|
164
|
+
* the signer will default to the one passed as the second parameter, or the
|
|
165
|
+
* configured signer from the constructor if no second parameter is provided.
|
|
166
|
+
*
|
|
167
|
+
* @param methodCall - The method call to add
|
|
168
|
+
* @param signer - The signer to use for the method call (defaults to constructor signer)
|
|
169
|
+
* @returns This composer instance for chaining
|
|
170
|
+
*/
|
|
171
|
+
addMethodCall(methodCall, signer = this.defaultSigner) {
|
|
172
|
+
this.atc.addMethodCall({
|
|
173
|
+
...methodCall,
|
|
174
|
+
signer: methodCall.signer ?? signer
|
|
175
|
+
});
|
|
153
176
|
return this;
|
|
154
177
|
}
|
|
155
178
|
/**
|
|
156
179
|
* Add swap transactions to the atomic group
|
|
157
180
|
*
|
|
158
|
-
* This method automatically processes required app opt-ins
|
|
159
|
-
* 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
|
|
160
188
|
*
|
|
161
189
|
* @returns This composer instance for chaining
|
|
162
190
|
* @throws Error if the swap transactions have already been added
|
|
@@ -165,14 +193,45 @@ var SwapComposer = class SwapComposer {
|
|
|
165
193
|
*/
|
|
166
194
|
async addSwapTransactions() {
|
|
167
195
|
if (this.swapTransactionsAdded) throw new Error("Swap transactions have already been added");
|
|
168
|
-
if (this.
|
|
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);
|
|
169
200
|
const processedTxns = await this.processSwapTransactions();
|
|
170
|
-
|
|
171
|
-
this.
|
|
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}`);
|
|
203
|
+
for (const txnWithSigner of processedTxns) this.atc.addTransaction(txnWithSigner);
|
|
204
|
+
for (const txnWithSigner of afterTxns) this.atc.addTransaction(txnWithSigner);
|
|
172
205
|
this.swapTransactionsAdded = true;
|
|
173
206
|
return this;
|
|
174
207
|
}
|
|
175
208
|
/**
|
|
209
|
+
* Finalize the transaction group by assigning group IDs
|
|
210
|
+
*
|
|
211
|
+
* This method builds the atomic transaction group, assigning group IDs to all transactions
|
|
212
|
+
* if there is more than one transaction. After calling this method, the composer's status
|
|
213
|
+
* will be at least BUILT.
|
|
214
|
+
*
|
|
215
|
+
* @returns Array of transactions with their associated signers
|
|
216
|
+
*
|
|
217
|
+
* @throws Error if the group contains 0 transactions
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* const composer = await deflex.newSwap({ quote, address, slippage, signer })
|
|
222
|
+
* composer.addTransaction(customTxn)
|
|
223
|
+
*
|
|
224
|
+
* // Build the group to inspect transactions before signing
|
|
225
|
+
* const txnsWithSigners = composer.buildGroup()
|
|
226
|
+
* console.log('Group ID:', txnsWithSigners[0].txn.group)
|
|
227
|
+
* console.log('Group length:', txnsWithSigners.length)
|
|
228
|
+
* console.log('Status:', composer.getStatus()) // BUILT
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
buildGroup() {
|
|
232
|
+
return this.atc.buildGroup();
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
176
235
|
* Sign the transaction group
|
|
177
236
|
*
|
|
178
237
|
* Automatically adds swap transactions if not already added, builds the atomic group,
|
|
@@ -186,34 +245,9 @@ var SwapComposer = class SwapComposer {
|
|
|
186
245
|
* ```
|
|
187
246
|
*/
|
|
188
247
|
async sign() {
|
|
189
|
-
if (this.
|
|
248
|
+
if (this.getStatus() >= SwapComposerStatus.SIGNED) return this.atc.gatherSignatures();
|
|
190
249
|
if (!this.swapTransactionsAdded) await this.addSwapTransactions();
|
|
191
|
-
|
|
192
|
-
const txnGroup = [];
|
|
193
|
-
const indexesToSign = [];
|
|
194
|
-
for (let i = 0; i < transactions.length; i++) {
|
|
195
|
-
const item = transactions[i];
|
|
196
|
-
if (!item) continue;
|
|
197
|
-
txnGroup.push(item.txn);
|
|
198
|
-
if (!item.deflexSignature) indexesToSign.push(i);
|
|
199
|
-
}
|
|
200
|
-
const userSignedTxns = (await this.signer(txnGroup, indexesToSign)).filter((txn) => txn !== null);
|
|
201
|
-
const finalSignedTxns = [];
|
|
202
|
-
let userSignedIndex = 0;
|
|
203
|
-
for (const item of transactions) if (item.deflexSignature) {
|
|
204
|
-
const signedTxnBlob = this.signDeflexTransaction(item.txn, item.deflexSignature);
|
|
205
|
-
finalSignedTxns.push(signedTxnBlob);
|
|
206
|
-
} else {
|
|
207
|
-
const userSignedTxn = userSignedTxns[userSignedIndex];
|
|
208
|
-
if (!userSignedTxn) throw new Error(`Missing signature for user transaction at index ${userSignedIndex}`);
|
|
209
|
-
finalSignedTxns.push(userSignedTxn);
|
|
210
|
-
userSignedIndex++;
|
|
211
|
-
}
|
|
212
|
-
const txIds = this.transactions.map((t) => t.txn.txID());
|
|
213
|
-
this.signedTxns = finalSignedTxns;
|
|
214
|
-
this.txIds = txIds;
|
|
215
|
-
this.status = SwapComposerStatus.SIGNED;
|
|
216
|
-
return finalSignedTxns;
|
|
250
|
+
return await this.atc.gatherSignatures();
|
|
217
251
|
}
|
|
218
252
|
/**
|
|
219
253
|
* Submit the signed transactions to the network
|
|
@@ -231,11 +265,8 @@ var SwapComposer = class SwapComposer {
|
|
|
231
265
|
* ```
|
|
232
266
|
*/
|
|
233
267
|
async submit() {
|
|
234
|
-
if (this.
|
|
235
|
-
|
|
236
|
-
await this.algodClient.sendRawTransaction(stxns).do();
|
|
237
|
-
this.status = SwapComposerStatus.SUBMITTED;
|
|
238
|
-
return this.txIds;
|
|
268
|
+
if (!this.swapTransactionsAdded) await this.addSwapTransactions();
|
|
269
|
+
return this.atc.submit(this.algodClient);
|
|
239
270
|
}
|
|
240
271
|
/**
|
|
241
272
|
* Execute the swap
|
|
@@ -256,14 +287,11 @@ var SwapComposer = class SwapComposer {
|
|
|
256
287
|
* ```
|
|
257
288
|
*/
|
|
258
289
|
async execute(waitRounds = DEFAULT_CONFIRMATION_ROUNDS) {
|
|
259
|
-
if (this.
|
|
260
|
-
const
|
|
261
|
-
const confirmedTxnInfo = await waitForConfirmation(this.algodClient, txIds[0], waitRounds);
|
|
262
|
-
this.status = SwapComposerStatus.COMMITTED;
|
|
263
|
-
const confirmedRound = confirmedTxnInfo.confirmedRound;
|
|
290
|
+
if (!this.swapTransactionsAdded) await this.addSwapTransactions();
|
|
291
|
+
const { txIDs,...result } = await this.atc.execute(this.algodClient, waitRounds);
|
|
264
292
|
return {
|
|
265
|
-
|
|
266
|
-
txIds
|
|
293
|
+
...result,
|
|
294
|
+
txIds: txIDs
|
|
267
295
|
};
|
|
268
296
|
}
|
|
269
297
|
/**
|
|
@@ -287,9 +315,12 @@ var SwapComposer = class SwapComposer {
|
|
|
287
315
|
delete txn.group;
|
|
288
316
|
if (deflexTxn.signature !== false) swapTxns.push({
|
|
289
317
|
txn,
|
|
290
|
-
|
|
318
|
+
signer: this.createDeflexSigner(deflexTxn.signature)
|
|
319
|
+
});
|
|
320
|
+
else swapTxns.push({
|
|
321
|
+
txn,
|
|
322
|
+
signer: this.defaultSigner
|
|
291
323
|
});
|
|
292
|
-
else swapTxns.push({ txn });
|
|
293
324
|
} catch (error) {
|
|
294
325
|
throw new Error(`Failed to process swap transaction at index ${i}: ${error instanceof Error ? error.message : String(error)}`);
|
|
295
326
|
}
|
|
@@ -302,32 +333,34 @@ var SwapComposer = class SwapComposer {
|
|
|
302
333
|
async processRequiredAppOptIns() {
|
|
303
334
|
const userApps = (await this.algodClient.accountInformation(this.address).do())?.appsLocalState?.map((app) => Number(app.id)) || [];
|
|
304
335
|
const appsToOptIn = this.requiredAppOptIns.filter((appId) => !userApps.includes(appId));
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
return appOptInTxns.map((txn) => ({ txn }));
|
|
336
|
+
if (appsToOptIn.length === 0) return [];
|
|
337
|
+
const suggestedParams = await this.algodClient.getTransactionParams().do();
|
|
338
|
+
return appsToOptIn.map((appId) => ({
|
|
339
|
+
txn: makeApplicationOptInTxnFromObject({
|
|
340
|
+
sender: this.address,
|
|
341
|
+
appIndex: appId,
|
|
342
|
+
suggestedParams
|
|
343
|
+
}),
|
|
344
|
+
signer: this.defaultSigner
|
|
345
|
+
}));
|
|
318
346
|
}
|
|
319
347
|
/**
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
* The composer's status will be at least BUILT after executing this method.
|
|
348
|
+
* The default signer function that uses the configured signer
|
|
323
349
|
*/
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
350
|
+
defaultSigner = async (txnGroup, indexesToSign) => {
|
|
351
|
+
return (await this.signer(txnGroup, indexesToSign)).filter((txn) => txn !== null);
|
|
352
|
+
};
|
|
353
|
+
/**
|
|
354
|
+
* Creates a TransactionSigner function for Deflex pre-signed transactions
|
|
355
|
+
*/
|
|
356
|
+
createDeflexSigner(signature) {
|
|
357
|
+
return async (txnGroup, indexesToSign) => {
|
|
358
|
+
return indexesToSign.map((i) => {
|
|
359
|
+
const txn = txnGroup[i];
|
|
360
|
+
if (!txn) throw new Error(`Transaction at index ${i} not found`);
|
|
361
|
+
return this.signDeflexTransaction(txn, signature);
|
|
362
|
+
});
|
|
363
|
+
};
|
|
331
364
|
}
|
|
332
365
|
/**
|
|
333
366
|
* Re-signs a Deflex transaction using the provided logic signature or secret key
|
|
@@ -348,6 +381,42 @@ var SwapComposer = class SwapComposer {
|
|
|
348
381
|
throw new Error(`Failed to re-sign transaction: ${error instanceof Error ? error.message : String(error)}`);
|
|
349
382
|
}
|
|
350
383
|
}
|
|
384
|
+
/**
|
|
385
|
+
* Execute middleware hooks (beforeSwap or afterSwap)
|
|
386
|
+
*/
|
|
387
|
+
async executeMiddlewareHooks(hookName) {
|
|
388
|
+
const allTxns = [];
|
|
389
|
+
for (const mw of this.middleware) {
|
|
390
|
+
if (!await mw.shouldApply({
|
|
391
|
+
fromASAID: BigInt(this.quote.fromASAID),
|
|
392
|
+
toASAID: BigInt(this.quote.toASAID)
|
|
393
|
+
}) || !mw[hookName]) continue;
|
|
394
|
+
const context = await this.createSwapContext();
|
|
395
|
+
const txns = await mw[hookName](context);
|
|
396
|
+
allTxns.push(...txns);
|
|
397
|
+
}
|
|
398
|
+
return allTxns;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Create SwapContext for middleware hooks
|
|
402
|
+
*/
|
|
403
|
+
async createSwapContext() {
|
|
404
|
+
const suggestedParams = await this.algodClient.getTransactionParams().do();
|
|
405
|
+
return {
|
|
406
|
+
quote: "createdAt" in this.quote ? this.quote : {
|
|
407
|
+
...this.quote,
|
|
408
|
+
quote: this.quote.quote === "" ? 0n : BigInt(this.quote.quote),
|
|
409
|
+
amount: 0n,
|
|
410
|
+
createdAt: Date.now()
|
|
411
|
+
},
|
|
412
|
+
address: this.address,
|
|
413
|
+
algodClient: this.algodClient,
|
|
414
|
+
suggestedParams,
|
|
415
|
+
fromASAID: BigInt(this.quote.fromASAID),
|
|
416
|
+
toASAID: BigInt(this.quote.toASAID),
|
|
417
|
+
signer: this.defaultSigner
|
|
418
|
+
};
|
|
419
|
+
}
|
|
351
420
|
};
|
|
352
421
|
|
|
353
422
|
//#endregion
|
|
@@ -426,6 +495,7 @@ async function request(url, options) {
|
|
|
426
495
|
var DeflexClient = class {
|
|
427
496
|
config;
|
|
428
497
|
algodClient;
|
|
498
|
+
middleware;
|
|
429
499
|
/**
|
|
430
500
|
* Create a new DeflexClient instance
|
|
431
501
|
*
|
|
@@ -438,6 +508,7 @@ var DeflexClient = class {
|
|
|
438
508
|
* @param config.referrerAddress - Referrer address for fee sharing (receives 25% of swap fees)
|
|
439
509
|
* @param config.feeBps - Fee in basis points (default: 15 = 0.15%, max: 300 = 3.00%)
|
|
440
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: [])
|
|
441
512
|
*/
|
|
442
513
|
constructor(config) {
|
|
443
514
|
this.config = {
|
|
@@ -451,6 +522,7 @@ var DeflexClient = class {
|
|
|
451
522
|
autoOptIn: config.autoOptIn ?? DEFAULT_AUTO_OPT_IN
|
|
452
523
|
};
|
|
453
524
|
this.algodClient = new Algodv2(this.config.algodToken, this.config.algodUri, this.config.algodPort);
|
|
525
|
+
this.middleware = config.middleware ?? [];
|
|
454
526
|
}
|
|
455
527
|
/**
|
|
456
528
|
* Fetch a swap quote from the Deflex API
|
|
@@ -600,7 +672,12 @@ var DeflexClient = class {
|
|
|
600
672
|
* ```
|
|
601
673
|
*/
|
|
602
674
|
async newQuote(params) {
|
|
603
|
-
|
|
675
|
+
let adjustedParams = { ...params };
|
|
676
|
+
for (const mw of this.middleware) if (await mw.shouldApply({
|
|
677
|
+
fromASAID: BigInt(params.fromASAID),
|
|
678
|
+
toASAID: BigInt(params.toASAID)
|
|
679
|
+
}) && mw.adjustQuoteParams) adjustedParams = await mw.adjustQuoteParams(adjustedParams);
|
|
680
|
+
const response = await this.fetchQuote(adjustedParams);
|
|
604
681
|
return {
|
|
605
682
|
...response,
|
|
606
683
|
quote: response.quote === "" ? 0n : BigInt(response.quote),
|
|
@@ -668,7 +745,8 @@ var DeflexClient = class {
|
|
|
668
745
|
})).txns,
|
|
669
746
|
algodClient: this.algodClient,
|
|
670
747
|
address,
|
|
671
|
-
signer
|
|
748
|
+
signer,
|
|
749
|
+
middleware: this.middleware
|
|
672
750
|
});
|
|
673
751
|
}
|
|
674
752
|
/**
|