@omnity/ree-client-ts-sdk 0.1.3 โ†’ 0.2.1

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
@@ -1,4 +1,4 @@
1
- # Ree Client TypesSript SDK
1
+ # Ree Client TypeScript SDK
2
2
 
3
3
  A TypeScript SDK for interacting with the Ree protocol on Bitcoin, providing seamless integration with Bitcoin wallets and Rune tokens.
4
4
 
@@ -10,6 +10,7 @@ A TypeScript SDK for interacting with the Ree protocol on Bitcoin, providing sea
10
10
  - ๐Ÿ”ง **TypeScript**: Full type safety and IntelliSense support
11
11
  - ๐Ÿงช **Well Tested**: Comprehensive test coverage
12
12
  - ๐Ÿ“ฆ **Lightweight**: Minimal dependencies and optimized bundle size
13
+ - ๐Ÿ”„ **Multi-Intention Transactions**: Support for complex transactions with multiple operations
13
14
 
14
15
  ## Installation
15
16
 
@@ -25,10 +26,11 @@ npm install @omnity/ree-client-ts-sdk
25
26
  import { ReeClient, Network, type Config } from "@omnity/ree-client-ts-sdk";
26
27
 
27
28
  const config: Config = {
28
- network: Network.Testnet,
29
+ network: Network.Testnet, // or Network.Mainnet
29
30
  maestroApiKey: "your-maestro-api-key",
30
31
  exchangeIdlFactory: yourExchangeIdlFactory,
31
- exchangeCanisterId: "your-canister-id",
32
+ exchangeCanisterId: "your-exchange-canister-id",
33
+ exchangeId: "your-exchange-id",
32
34
  };
33
35
 
34
36
  const client = new ReeClient(config);
@@ -61,32 +63,82 @@ const poolInfo = await client.getPoolInfo("pool-address");
61
63
 
62
64
  ### Creating and Executing Transactions
63
65
 
66
+ #### Simple Single-Pool Transaction
67
+
64
68
  ```typescript
65
- // Create a swap transaction
69
+ // Create a transaction for a single pool operation
66
70
  const transaction = await client.createTransaction({
67
- address: "bc1q...", // Bitcoin address
68
- paymentAddress: "bc1q...", // Payment address
69
- poolAddress: "bc1q...",
70
- sendBtcAmount: BigInt(100000), // 0.001 BTC in satoshis
71
- sendRuneAmount: BigInt(0),
72
- receiveBtcAmount: BigInt(0),
73
- receiveRuneAmount: BigInt(1000),
71
+ address: "bc1q...", // Bitcoin address for runes
72
+ paymentAddress: "bc1q...", // Payment address for BTC
73
+ involvedPoolAddresses: ["bc1q..."], // Pool addresses involved
74
+ involvedRuneIds: ["840000:3"], // Optional: rune IDs if trading runes
74
75
  });
75
76
 
76
- // Build the transaction
77
- const psbt = await transaction.build("swap", BigInt(Date.now()));
77
+ // Add a single intention (e.g., swap BTC for runes)
78
+ transaction.addIntention({
79
+ poolAddress: "bc1q...",
80
+ inputCoins: [
81
+ { id: "0:0", value: BigInt(100000) }, // Send 0.001 BTC
82
+ ],
83
+ outputCoins: [
84
+ { id: "840000:3", value: BigInt(1000) }, // Receive 1000 runes
85
+ ],
86
+ action: "swap",
87
+ nonce: BigInt(1234),
88
+ });
78
89
 
79
- // Sign with your wallet (implementation depends on wallet)
90
+ // Build and execute
91
+ const psbt = await transaction.build();
80
92
  const signedPsbt = await wallet.signPsbt(psbt);
93
+ const result = await transaction.send(signedPsbt.toHex());
94
+ ```
95
+
96
+ #### Advanced Multi-Intention Transaction
97
+
98
+ ```typescript
99
+ // Create a complex transaction with multiple operations
100
+ const transaction = await client.createTransaction({
101
+ address: "bc1q...",
102
+ paymentAddress: "bc1q...",
103
+ involvedPoolAddresses: ["bc1q...pool1", "bc1q...pool2"],
104
+ involvedRuneIds: ["840000:3", "840000:5"],
105
+ });
81
106
 
82
- // Submit the transaction
107
+ // Add multiple intentions in a single transaction
108
+ // Intention 1: Deposit BTC to Pool 1
109
+ transaction.addIntention({
110
+ poolAddress: "bc1q...pool1",
111
+ inputCoins: [
112
+ { id: "0:0", value: BigInt(50000) }, // Deposit 0.0005 BTC
113
+ ],
114
+ outputCoins: [],
115
+ action: "deposit",
116
+ nonce: BigInt(Date.now()),
117
+ });
118
+
119
+ // Intention 2: Swap runes between pools
120
+ transaction.addIntention({
121
+ poolAddress: "bc1q...pool2",
122
+ inputCoins: [
123
+ { id: "840000:3", value: BigInt(500) }, // Send 500 of rune A
124
+ ],
125
+ outputCoins: [
126
+ { id: "840000:5", value: BigInt(250) }, // Receive 250 of rune B
127
+ ],
128
+ action: "swap",
129
+ nonce: BigInt(Date.now() + 1),
130
+ });
131
+
132
+ // Build and execute the multi-intention transaction
133
+ const psbt = await transaction.build();
134
+ const signedPsbt = await wallet.signPsbt(psbt);
83
135
  const result = await transaction.send(signedPsbt.toHex());
84
136
  ```
85
137
 
86
138
  ### React Integration
87
139
 
88
140
  ```tsx
89
- import { ReeProvider, useRee, useBtcBalance } from "@ree-network/ts-sdk";
141
+ import { ReeProvider, useRee, useBtcBalance } from "@omnity/ree-client-ts-sdk";
90
142
 
91
143
  function App() {
92
144
  return (
@@ -97,8 +149,7 @@ function App() {
97
149
  }
98
150
 
99
151
  function WalletComponent() {
100
- const { client, address, updateWallet } = useRee();
101
-
152
+ const { client, address, updateWallet, createTransaction } = useRee();
102
153
  const { balance: btcBalance } = useBtcBalance();
103
154
 
104
155
  const connectWallet = () => {
@@ -108,11 +159,40 @@ function WalletComponent() {
108
159
  });
109
160
  };
110
161
 
162
+ const executeComplexTransaction = async () => {
163
+ // Create transaction with multiple pools
164
+ const tx = await createTransaction({
165
+ involvedPoolAddresses: ["pool1", "pool2"],
166
+ involvedRuneIds: ["840000:3"],
167
+ });
168
+
169
+ // Add multiple intentions
170
+ tx.addIntention({
171
+ poolAddress: "pool1",
172
+ inputCoins: [{ id: "0:0", value: BigInt(100000) }],
173
+ outputCoins: [{ id: "840000:3", value: BigInt(1000) }],
174
+ action: "swap",
175
+ nonce: BigInt(Date.now()),
176
+ });
177
+
178
+ tx.addIntention({
179
+ poolAddress: "pool2",
180
+ inputCoins: [{ id: "840000:3", value: BigInt(500) }],
181
+ outputCoins: [{ id: "0:0", value: BigInt(50000) }],
182
+ action: "swap",
183
+ nonce: BigInt(Date.now() + 1),
184
+ });
185
+
186
+ const psbt = await tx.build();
187
+ // Sign and send...
188
+ };
189
+
111
190
  return (
112
191
  <div>
113
192
  <div>Connected: {address}</div>
114
193
  <div>Balance: {btcBalance} BTC</div>
115
194
  <button onClick={connectWallet}>Connect wallet</button>
195
+ <button onClick={executeComplexTransaction}>Execute Complex Transaction</button>
116
196
  </div>
117
197
  );
118
198
  }
@@ -225,12 +305,48 @@ new ReeClient(config: Config)
225
305
 
226
306
  ### Transaction
227
307
 
228
- Transaction builder for Bitcoin and Rune transactions.
308
+ Transaction builder for Bitcoin and Rune transactions with multi-intention support.
229
309
 
230
310
  #### Methods
231
311
 
232
- - `build(action: string, nonce: bigint, actionParams?: string): Promise<bitcoin.Psbt>` - Build the PSBT
233
- - `send(signedPsbtHex: string): Promise<any>` - Submit the signed transaction to orchestrator
312
+ - `addIntention(intention: Intention): void` - Add an intention to the transaction
313
+ - `build(): Promise<bitcoin.Psbt>` - Build the PSBT with all intentions
314
+ - `send(signedPsbtHex: string): Promise<any>` - Submit the signed transaction
315
+
316
+ #### Intention Structure
317
+
318
+ ```typescript
319
+ interface Intention {
320
+ poolAddress: string; // Target pool address
321
+ inputCoins: CoinBalance[]; // Coins being sent to the pool
322
+ outputCoins: CoinBalance[]; // Coins expected from the pool
323
+ action: string; // Action type (swap, deposit, withdraw, etc.)
324
+ actionParams?: string; // Optional action parameters
325
+ nonce: bigint; // Unique nonce for the intention
326
+ }
327
+
328
+ interface CoinBalance {
329
+ id: string; // Coin ID ("0:0" for BTC, "840000:3" for runes)
330
+ value: bigint; // Amount in smallest unit
331
+ }
332
+ ```
333
+
334
+ ### Multi-Intention Transaction Benefits
335
+
336
+ 1. **Atomic Operations**: All intentions succeed or fail together
337
+ 2. **Gas Efficiency**: Single transaction fee for multiple operations
338
+ 3. **Complex Strategies**: Enable sophisticated trading strategies
339
+ 4. **Cross-Pool Operations**: Interact with multiple pools in one transaction
340
+
341
+ ### Transaction Flow
342
+
343
+ 1. **Create Transaction**: Specify involved pools and runes
344
+ 2. **Add Intentions**: Define each operation you want to perform
345
+ 3. **Build PSBT**: SDK calculates all inputs/outputs and fees
346
+ 4. **Sign**: Use your wallet to sign the transaction
347
+ 5. **Submit**: Send to the network for execution
348
+
349
+ All intentions in a transaction are processed atomically - if any intention fails, the entire transaction is reverted.
234
350
 
235
351
  ### React Hooks
236
352
 
@@ -378,21 +494,30 @@ enum Network {
378
494
 
379
495
  ```typescript
380
496
  try {
381
- const utxos = await client.getBtcUtxos("bc1q...");
497
+ const transaction = await client.createTransaction({
498
+ address: "bc1q...",
499
+ paymentAddress: "bc1q...",
500
+ involvedPoolAddresses: ["bc1q..."],
501
+ });
502
+
503
+ transaction.addIntention({
504
+ poolAddress: "bc1q...",
505
+ inputCoins: [{ id: "0:0", value: BigInt(100000) }],
506
+ outputCoins: [{ id: "840000:3", value: BigInt(1000) }],
507
+ action: "swap",
508
+ nonce: BigInt(Date.now()),
509
+ });
510
+
511
+ const psbt = await transaction.build();
512
+ const signedPsbt = await wallet.signPsbt(psbt);
513
+ const result = await transaction.send(signedPsbt.toHex());
382
514
  } catch (error) {
383
- console.error("Failed to fetch UTXOs:", error);
384
- }
385
-
386
- // React hook error handling
387
- const { client } = useRee();
388
-
389
- const loadBalance = async () => {
390
- try {
391
- const balance = await client.getBtcBalance("bc1q...");
392
- setBalance(balance);
393
- } catch (error) {
394
- console.error("Failed to load balance:", error);
395
- setError(error.message);
515
+ if (error.message.includes("INSUFFICIENT")) {
516
+ console.error("Insufficient funds:", error);
517
+ } else if (error.message.includes("Pool")) {
518
+ console.error("Pool error:", error);
519
+ } else {
520
+ console.error("Transaction failed:", error);
396
521
  }
397
- };
522
+ }
398
523
  ```
package/dist/index.d.ts CHANGED
@@ -34,7 +34,7 @@ export declare type AddressType = (typeof AddressType)[keyof typeof AddressType]
34
34
 
35
35
  declare function bytesToHex(bytes: Uint8Array): string;
36
36
 
37
- declare type CoinBalance = {
37
+ export declare type CoinBalance = {
38
38
  id: string;
39
39
  value: bigint;
40
40
  };
@@ -53,27 +53,13 @@ declare function getScriptByAddress(address: string, network?: Network): Buffer<
53
53
 
54
54
  declare function hexToBytes(hex: string): Uint8Array;
55
55
 
56
- declare type InputCoin = {
57
- coin: CoinBalance;
58
- from: string;
59
- };
60
-
61
56
  export declare type Intention = {
62
- input_coins: InputCoin[];
63
- output_coins: OutputCoin[];
57
+ inputCoins: CoinBalance[];
58
+ outputCoins: CoinBalance[];
64
59
  action: string;
65
- exchange_id: string;
66
- action_params: string;
67
- pool_utxo_spent: string[];
60
+ actionParams?: string;
61
+ poolAddress: string;
68
62
  nonce: bigint;
69
- pool_utxo_received: string[];
70
- pool_address: string;
71
- };
72
-
73
- export declare type IntentionSet = {
74
- tx_fee_in_sats: bigint;
75
- initiator_address: string;
76
- intentions: Intention[];
77
63
  };
78
64
 
79
65
  declare class Maestro {
@@ -123,11 +109,6 @@ export declare const Network: {
123
109
 
124
110
  export declare type Network = (typeof Network)[keyof typeof Network];
125
111
 
126
- declare type OutputCoin = {
127
- coin: CoinBalance;
128
- to: string;
129
- };
130
-
131
112
  export declare type Pool = {
132
113
  name: string;
133
114
  address: string;
@@ -272,25 +253,17 @@ export declare class ReeClient {
272
253
  getPoolInfo(poolAddress: string): Promise<PoolInfo>;
273
254
  /**
274
255
  * Create a transaction for trading with a liquidity pool
275
- * Supports both BTC-only and BTC-Rune swaps
276
256
  * @param params - Transaction parameters
277
- * @param params.runeId - Optional rune ID for rune swaps
278
- * @param params.poolAddress - Target pool address
279
- * @param params.sendBtcAmount - BTC amount to send
280
- * @param params.sendRuneAmount - Rune amount to send (0 for BTC-only)
281
- * @param params.receiveBtcAmount - Expected BTC to receive
282
- * @param params.receiveRuneAmount - Expected rune amount to receive
283
- * @returns Transaction builder instance
257
+ * @param params.address - Bitcoin address
258
+ * @param params.paymentAddress - Ordinals address
259
+ * @param params.involvedRuneId - Optional rune ID for rune swaps
260
+ * @returns Transaction instance
284
261
  */
285
- createTransaction({ address, paymentAddress, runeId, poolAddress, sendBtcAmount, sendRuneAmount, receiveBtcAmount, receiveRuneAmount, }: {
286
- runeId?: string;
262
+ createTransaction({ address, paymentAddress, involvedRuneIds, involvedPoolAddresses, }: {
287
263
  address: string;
288
264
  paymentAddress: string;
289
- poolAddress: string;
290
- sendBtcAmount: bigint;
291
- sendRuneAmount: bigint;
292
- receiveBtcAmount: bigint;
293
- receiveRuneAmount: bigint;
265
+ involvedRuneIds?: string[];
266
+ involvedPoolAddresses: string[];
294
267
  }): Promise<Transaction>;
295
268
  }
296
269
 
@@ -304,12 +277,8 @@ declare interface ReeContextValue {
304
277
  paymentAddress?: string;
305
278
  }) => void;
306
279
  createTransaction: (params: {
307
- runeId?: string;
308
- poolAddress: string;
309
- sendBtcAmount: bigint;
310
- sendRuneAmount: bigint;
311
- receiveBtcAmount: bigint;
312
- receiveRuneAmount: bigint;
280
+ involvedRuneIds?: string[];
281
+ involvedPoolAddresses: string[];
313
282
  }) => Promise<Transaction>;
314
283
  }
315
284
 
@@ -343,7 +312,10 @@ export declare class Transaction {
343
312
  private userInputUtxoDusts;
344
313
  /** Orchestrator actor for fee estimation */
345
314
  readonly orchestrator: ActorSubclass;
346
- private intentionSet;
315
+ private intentions;
316
+ private txFee;
317
+ private additionalDustNeeded;
318
+ private inputUtxos;
347
319
  constructor(config: TransactionConfig, orchestrator: ActorSubclass);
348
320
  /**
349
321
  * Add a UTXO as transaction input
@@ -376,23 +348,6 @@ export declare class Transaction {
376
348
  * @returns Selected UTXOs that contain enough BTC
377
349
  */
378
350
  private selectBtcUtxos;
379
- /**
380
- * Calculate rune change amount and determine if change is needed
381
- * @param runeId - The rune ID to calculate change for
382
- * @param runeUtxos - UTXOs containing the runes
383
- * @param runeAmount - Amount being sent
384
- * @returns Change calculation result
385
- */
386
- private caclulateRuneChangeAmount;
387
- /**
388
- * Add rune-related outputs to the transaction
389
- * @param runeIdStr - Rune ID string (block:index format)
390
- * @param runeUtxos - UTXOs containing the runes
391
- * @param runeAmount - Amount of runes to transfer
392
- * @param receiveAddress - Address to receive the runes
393
- * @returns Information about whether change output is needed
394
- */
395
- private addRuneOutputs;
396
351
  /**
397
352
  * Add BTC outputs and calculate transaction fees
398
353
  * @param btcUtxos - Available BTC UTXOs
@@ -403,11 +358,60 @@ export declare class Transaction {
403
358
  */
404
359
  private addBtcAndFees;
405
360
  /**
406
- * Build the complete transaction
407
- * Handles both BTC-only and Rune transactions
408
- * @returns Built PSBT and total fee
361
+ * Process all intentions and calculate input/output amounts for the transaction
362
+ * This method handles multiple intentions in a single transaction, calculating:
363
+ * - Pool UTXOs to be consumed as inputs
364
+ * - User rune UTXOs needed for input coins
365
+ * - Final BTC and rune amounts for all parties (user and pools)
366
+ *
367
+ * @returns Object containing calculated amounts for transaction outputs
368
+ * @throws Error if pools have insufficient funds for the requested operations
369
+ */
370
+ private addInputAndCalculateOutputs;
371
+ private addRuneOutputs;
372
+ /**
373
+ * Add an intention to the transaction
374
+ * Multiple intentions can be added to create complex, atomic transactions
375
+ *
376
+ * @param intention - The intention object containing:
377
+ * - poolAddress: Target pool address
378
+ * - inputCoins: Coins being sent to the pool
379
+ * - outputCoins: Coins expected from the pool
380
+ * - action: Action type (swap, deposit, withdraw, etc.)
381
+ * - nonce: Unique identifier for this intention
382
+ *
383
+ * @example
384
+ * ```typescript
385
+ * // Add a swap intention
386
+ * transaction.addIntention({
387
+ * poolAddress: "bc1q...",
388
+ * inputCoins: [{ id: "0:0", value: BigInt(100000) }], // Send BTC
389
+ * outputCoins: [{ id: "840000:3", value: BigInt(1000) }], // Receive runes
390
+ * action: "swap",
391
+ * nonce: BigInt(Date.now()),
392
+ * });
393
+ * ```
409
394
  */
410
- build(action: string, nonce: bigint, actionParams?: string): Promise<bitcoin.Psbt>;
395
+ addIntention(intention: Intention): void;
396
+ /**
397
+ * Build the complete PSBT with all added intentions
398
+ * This method processes all intentions atomically and calculates:
399
+ * - Required inputs from user and pools
400
+ * - Output distributions to user and pools
401
+ * - Transaction fees and change outputs
402
+ * - Runestone for rune transfers
403
+ *
404
+ * @returns Promise resolving to the built PSBT ready for signing
405
+ * @throws Error if insufficient funds or invalid intentions
406
+ *
407
+ * @example
408
+ * ```typescript
409
+ * // After adding intentions
410
+ * const psbt = await transaction.build();
411
+ * const signedPsbt = await wallet.signPsbt(psbt);
412
+ * ```
413
+ */
414
+ build(): Promise<bitcoin.Psbt>;
411
415
  /**
412
416
  * Submit the signed transaction to the orchestrator for execution
413
417
  * This method sends the signed PSBT along with the intention set to the orchestrator canister
@@ -431,15 +435,9 @@ export declare interface TransactionConfig {
431
435
  exchangeId: string;
432
436
  address: string;
433
437
  paymentAddress: string;
434
- poolAddress: string;
435
- runeId?: string;
436
- runeUtxos?: Utxo[];
437
438
  btcUtxos: Utxo[];
438
- poolUtxos: Utxo[];
439
- sendBtcAmount: bigint;
440
- sendRuneAmount: bigint;
441
- receiveBtcAmount: bigint;
442
- receiveRuneAmount: bigint;
439
+ involvedPoolUtxos: Record<string, Utxo[]>;
440
+ involvedRuneUtxos?: Record<string, Utxo[]>;
443
441
  }
444
442
 
445
443
  declare interface UseBalanceOptions {