Skip to content
This repository was archived by the owner on Jan 14, 2026. It is now read-only.

Commit 1bea32f

Browse files
committed
refactor: move signer to SwapComposer configuration
Move transaction signer from execution method parameters to `SwapComposer` configuration. This improves API ergonomics by establishing a clear "configuration up front, then chainable commands" pattern where all configuration (`quote`, `address`, `slippage`, `signer`) is provided to `newSwap()`, and execution methods (`sign`, `submit`, `execute`) act as simple commands. Changes: - Add `signer` to `SwapComposerConfig` interface as required parameter - Remove `signer` parameter from `sign()`, `submit()`, and `execute()` methods - Update `DeflexClient.newSwap()` to accept signer in config - Update all tests and documentation to reflect new API pattern BREAKING CHANGE: Signer must now be passed to `newSwap()` config instead of to `sign()`, `submit()`, or `execute()` methods.
1 parent 0e281b3 commit 1bea32f

File tree

5 files changed

+226
-206
lines changed

5 files changed

+226
-206
lines changed

README.md

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,19 @@ const deflex = new DeflexClient({
2424
// Get a quote
2525
const quote = await deflex.newQuote({
2626
address: activeAddress,
27-
fromAssetId: 0, // ALGO
27+
fromAssetId: 0, // ALGO
2828
toAssetId: 31566704, // USDC
29-
amount: 1_000_000, // 1 ALGO (in microAlgos)
29+
amount: 1_000_000, // 1 ALGO (in microAlgos)
3030
})
3131

3232
// Execute the swap
3333
const swap = await deflex.newSwap({
3434
quote,
3535
address: activeAddress,
36+
signer: transactionSigner,
3637
slippage: 1, // 1% slippage tolerance
3738
})
38-
const result = await swap.execute(transactionSigner)
39+
const result = await swap.execute()
3940

4041
console.log(`Swap completed in round ${result.confirmedRound}`)
4142
```
@@ -59,8 +60,8 @@ const deflex = new DeflexClient({
5960
algodToken: '',
6061
algodPort: 443,
6162
referrerAddress: '<referrer_address>', // Earns 25% of swap fees
62-
feeBps: 15, // 0.15% fee (max: 300 = 3%)
63-
autoOptIn: true, // Automatically handle asset opt-ins
63+
feeBps: 15, // 0.15% fee (max: 300 = 3%)
64+
autoOptIn: true, // Automatically handle asset opt-ins
6465
})
6566
```
6667

@@ -71,9 +72,9 @@ The [`newQuote()`](#deflexclientnewquote) method returns a [`DeflexQuote`](#defl
7172
```typescript
7273
// Basic quote
7374
const quote = await deflex.newQuote({
74-
fromAssetId: 0, // ALGO
75-
toAssetId: 31566704, // USDC
76-
amount: 1_000_000, // 1 ALGO
75+
fromAssetId: 0, // ALGO
76+
toAssetId: 31566704, // USDC
77+
amount: 1_000_000, // 1 ALGO
7778
address: userAddress, // Required for auto opt-in detection
7879
})
7980
```
@@ -90,17 +91,18 @@ const { activeAddress, transactionSigner } = useWallet()
9091
const swap = await deflex.newSwap({
9192
quote,
9293
address: activeAddress,
94+
signer: transactionSigner,
9395
slippage: 1, // 1% slippage tolerance
9496
})
95-
const result = await swap.execute(transactionSigner)
97+
const result = await swap.execute()
9698

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

101103
### Transaction Signing
102104

103-
The SDK supports two types of transaction signers for the `sign()`, `submit()`, and `execute()` methods:
105+
The SDK supports two types of transaction signers that must be passed to `newSwap()`:
104106

105107
#### 1. use-wallet Signer (Recommended)
106108

@@ -111,7 +113,13 @@ import { useWallet } from '@txnlab/use-wallet-*' // react, vue, solid, or svelte
111113
112114
const { activeAddress, transactionSigner } = useWallet()
113115

114-
await swap.execute(transactionSigner)
116+
const swap = await deflex.newSwap({
117+
quote,
118+
address: activeAddress,
119+
signer: transactionSigner,
120+
slippage: 1,
121+
})
122+
await swap.execute()
115123
```
116124

117125
> **Tip**: The [`@txnlab/use-wallet`](https://github.com/TxnLab/use-wallet) library supports multiple wallet providers (Pera, Defly, Lute, WalletConnect, etc.) and provides a unified interface. Choose the framework-specific adapter for your project: `@txnlab/use-wallet-react`, `@txnlab/use-wallet-vue`, `@txnlab/use-wallet-solid`, or `@txnlab/use-wallet-svelte`.
@@ -120,16 +128,22 @@ await swap.execute(transactionSigner)
120128

121129
```typescript
122130
// Custom signer function signature:
123-
// (txnGroup: Transaction[]) => Promise<Uint8Array[]>
131+
// (txns: Transaction[]) => Promise<Uint8Array[]>
124132

125-
const customSigner = async (txnGroup) => {
133+
const customSigner = async (txns) => {
126134
// Your custom signing logic here
127-
const signedTxns = await yourWalletProvider.signTransactions(txnGroup)
135+
const signedTxns = await yourWalletProvider.signTransactions(txns)
128136

129137
return signedTxns
130138
}
131139

132-
await swap.execute(customSigner)
140+
const swap = await deflex.newSwap({
141+
quote,
142+
address: activeAddress,
143+
signer: customSigner,
144+
slippage: 1,
145+
})
146+
await swap.execute()
133147
```
134148

135149
> **Note**: The custom signer function must return an array of `Uint8Array` where each element is a signed transaction.
@@ -152,14 +166,15 @@ const customTxn2 = new Transaction({...})
152166
const swap = await deflex.newSwap({
153167
quote,
154168
address: activeAddress,
169+
signer: transactionSigner,
155170
slippage: 1,
156171
})
157172

158173
const result = await swap
159174
.addTransaction(customTxn1) // Add transaction before swap
160175
.addSwapTransactions() // Add swap transactions
161176
.addTransaction(customTxn2) // Add transaction after swap
162-
.execute(transactionSigner) // Sign and execute entire group
177+
.execute() // Sign and execute entire group
163178
```
164179

165180
### Manual Asset Opt-In Detection
@@ -202,9 +217,10 @@ try {
202217
const swap = await deflex.newSwap({
203218
quote,
204219
address: activeAddress,
220+
signer: transactionSigner,
205221
slippage: 1,
206222
})
207-
const result = await swap.execute(transactionSigner)
223+
const result = await swap.execute()
208224

209225
console.log('Swap successful:', result)
210226
} catch (error) {
@@ -262,11 +278,12 @@ Returns a [`SwapComposer`](#swapcomposer) instance for building and executing sw
262278
async newSwap(config: SwapComposerConfig): Promise<SwapComposer>
263279
```
264280

265-
| Parameter | Description | Type |
266-
| ---------- | ------------------------------------------------- | ----------------------------------- |
267-
| `quote` | Quote instance or response object | `DeflexQuote \| FetchQuoteResponse` |
268-
| `address` | Signer address | `string` |
269-
| `slippage` | Slippage tolerance as percentage (e.g., 1 for 1%) | `number` |
281+
| Parameter | Description | Type |
282+
| ---------- | ------------------------------------------------- | --------------------------------------------------------------------------------------- |
283+
| `quote` | Quote instance or response object | `DeflexQuote \| FetchQuoteResponse` |
284+
| `address` | Signer address | `string` |
285+
| `slippage` | Slippage tolerance as percentage (e.g., 1 for 1%) | `number` |
286+
| `signer` | Transaction signer function | `algosdk.TransactionSigner \| ((txns: algosdk.Transaction[]) => Promise<Uint8Array[]>)` |
270287

271288
#### DeflexClient.needsAssetOptIn()
272289

@@ -324,6 +341,7 @@ getSlippageAmount(slippage: number): bigint
324341
| `slippage` | Slippage tolerance as percentage (e.g., 1 for 1%) | `number` |
325342

326343
**Example:**
344+
327345
```typescript
328346
const quote = await deflex.newQuote({
329347
fromAssetId: 0,
@@ -341,15 +359,15 @@ console.log(`Minimum you'll receive: ${minOutput}`)
341359

342360
Builder for constructing and executing atomic swap transaction groups, returned by [`newSwap()`](#deflexclientnewswap).
343361

344-
| Method | Description | Parameters | Returns |
345-
| ------------------------------ | ------------------------------------------------------------------------------ | ----------------------------------------------------- | ------------------------------------- |
346-
| `addTransaction(transaction)` | Add a transaction to the atomic group | `transaction: Transaction` | `SwapComposer` |
347-
| `addSwapTransactions()` | Add swap transactions to the group (includes required app opt-ins) | None | `Promise<SwapComposer>` |
348-
| `sign(signer)` | Sign the transaction group | `signer: TransactionSigner` | `Promise<Uint8Array[]>` |
349-
| `submit(signer)` | Sign and submit the transaction group | `signer: TransactionSigner` | `Promise<string[]>` |
350-
| `execute(signer, waitRounds?)` | Sign, submit, and wait for confirmation | `signer: TransactionSigner`<br/>`waitRounds?: number` | `Promise<PendingTransactionResponse>` |
351-
| `getStatus()` | Get current status: `BUILDING`, `BUILT`, `SIGNED`, `SUBMITTED`, or `COMMITTED` | None | `ComposerStatus` |
352-
| `count()` | Get the number of transactions in the group | None | `number` |
362+
| Method | Description | Parameters | Returns |
363+
| ----------------------------- | ------------------------------------------------------------------------------ | ---------------------------------- | ------------------------------------- |
364+
| `addTransaction(transaction)` | Add a transaction to the atomic group | `transaction: algosdk.Transaction` | `SwapComposer` |
365+
| `addSwapTransactions()` | Add swap transactions to the group (includes required app opt-ins) | None | `Promise<SwapComposer>` |
366+
| `sign()` | Sign the transaction group | None | `Promise<Uint8Array[]>` |
367+
| `submit()` | Sign and submit the transaction group | None | `Promise<string[]>` |
368+
| `execute(waitRounds?)` | Sign, submit, and wait for confirmation | `waitRounds?: number` (default: 4) | `Promise<PendingTransactionResponse>` |
369+
| `getStatus()` | Get current status: `BUILDING`, `BUILT`, `SIGNED`, `SUBMITTED`, or `COMMITTED` | None | `ComposerStatus` |
370+
| `count()` | Get the number of transactions in the group | None | `number` |
353371

354372
## Documentation
355373

src/client.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
22
import { isValidAddress } from 'algosdk'
3-
import { SwapComposer } from './composer'
3+
import { SwapComposer, type SignerFunction } from './composer'
44
import {
55
DEFAULT_ALGOD_PORT,
66
DEFAULT_ALGOD_TOKEN,
@@ -336,14 +336,15 @@ export class DeflexClient {
336336
* @param config.quote - The quote response from fetchQuote() or a DeflexQuote instance
337337
* @param config.address - The address of the signer
338338
* @param config.slippage - The slippage tolerance
339+
* @param config.signer - Transaction signer function
339340
* @returns A SwapComposer instance ready for building transaction groups
340341
*
341342
* @example
342343
* ```typescript
343344
* // Basic swap
344345
* const quote = await deflex.newQuote({ ... })
345-
* await deflex.newSwap({ quote, slippage, address })
346-
* .execute(signer)
346+
* await deflex.newSwap({ quote, address, slippage, signer })
347+
* .execute()
347348
* ```
348349
*
349350
* @example
@@ -352,8 +353,9 @@ export class DeflexClient {
352353
* const quote = await deflex.newQuote({ ... })
353354
* const swap = await deflex.newSwap({
354355
* quote,
355-
* slippage,
356356
* address,
357+
* slippage,
358+
* signer,
357359
* })
358360
*
359361
* console.log(swap.getStatus()) // BUILDING
@@ -362,11 +364,11 @@ export class DeflexClient {
362364
* .addTransaction(beforeTxn)
363365
* .addSwapTransactions() // Adds swap transactions to the group
364366
* .addTransaction(afterTxn)
365-
* .sign(signer) // algosdk.TransactionSigner or (txns) => Promise<Uint8Array[]>
367+
* .sign()
366368
*
367369
* console.log(swap.getStatus()) // SIGNED
368370
*
369-
* const result = await swap.execute(signer, waitRounds)
371+
* const result = await swap.execute(waitRounds)
370372
* console.log(result.confirmedRound, result.txIds)
371373
*
372374
* console.log(swap.getStatus()) // COMMITTED
@@ -376,8 +378,9 @@ export class DeflexClient {
376378
quote: DeflexQuote | FetchQuoteResponse
377379
address: string
378380
slippage: number
381+
signer: SignerFunction
379382
}): Promise<SwapComposer> {
380-
const { quote, address, slippage } = config
383+
const { quote, address, slippage, signer } = config
381384

382385
const quoteResponse = quote instanceof DeflexQuote ? quote.response : quote
383386

@@ -393,6 +396,7 @@ export class DeflexClient {
393396
deflexTxns: swapResponse.txns,
394397
algorand: this.algorand,
395398
address,
399+
signer,
396400
})
397401

398402
return composer

0 commit comments

Comments
 (0)