@flashnet/sdk 0.1.1 → 0.1.2

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.
Files changed (122) hide show
  1. package/README.md +4 -2
  2. package/dist/cjs/index.d.ts.map +1 -0
  3. package/dist/cjs/index.js +56 -0
  4. package/dist/cjs/index.js.map +1 -0
  5. package/dist/cjs/package.json +3 -0
  6. package/dist/cjs/src/api/client.d.ts.map +1 -0
  7. package/dist/cjs/src/api/client.js +90 -0
  8. package/dist/cjs/src/api/client.js.map +1 -0
  9. package/dist/cjs/src/api/typed-endpoints.d.ts.map +1 -0
  10. package/dist/cjs/src/api/typed-endpoints.js +207 -0
  11. package/dist/cjs/src/api/typed-endpoints.js.map +1 -0
  12. package/dist/cjs/src/api/validation.d.ts.map +1 -0
  13. package/dist/cjs/src/api/validation.js +140 -0
  14. package/dist/cjs/src/api/validation.js.map +1 -0
  15. package/dist/cjs/src/client/FlashnetClient.d.ts.map +1 -0
  16. package/dist/cjs/src/client/FlashnetClient.js +804 -0
  17. package/dist/cjs/src/client/FlashnetClient.js.map +1 -0
  18. package/dist/cjs/src/config/index.d.ts.map +1 -0
  19. package/dist/cjs/src/config/index.js +49 -0
  20. package/dist/cjs/src/config/index.js.map +1 -0
  21. package/dist/cjs/src/types/index.d.ts.map +1 -0
  22. package/dist/cjs/src/utils/auth.d.ts.map +1 -0
  23. package/dist/cjs/src/utils/auth.js +89 -0
  24. package/dist/cjs/src/utils/auth.js.map +1 -0
  25. package/dist/cjs/src/utils/index.d.ts.map +1 -0
  26. package/dist/cjs/src/utils/index.js +29 -0
  27. package/dist/cjs/src/utils/index.js.map +1 -0
  28. package/dist/cjs/src/utils/intents.d.ts.map +1 -0
  29. package/dist/cjs/src/utils/intents.js +144 -0
  30. package/dist/cjs/src/utils/intents.js.map +1 -0
  31. package/dist/cjs/src/utils/signer.d.ts.map +1 -0
  32. package/dist/cjs/src/utils/signer.js +38 -0
  33. package/dist/cjs/src/utils/signer.js.map +1 -0
  34. package/dist/cjs/src/utils/spark-address.d.ts.map +1 -0
  35. package/dist/cjs/src/utils/spark-address.js +238 -0
  36. package/dist/cjs/src/utils/spark-address.js.map +1 -0
  37. package/dist/{index.js → esm/index.d.ts} +6 -8
  38. package/dist/esm/index.d.ts.map +1 -0
  39. package/dist/esm/index.js +11 -0
  40. package/dist/esm/index.js.map +1 -0
  41. package/dist/esm/package.json +3 -0
  42. package/dist/esm/src/api/client.d.ts +20 -0
  43. package/dist/esm/src/api/client.d.ts.map +1 -0
  44. package/dist/{src → esm/src}/api/client.js +6 -3
  45. package/dist/esm/src/api/client.js.map +1 -0
  46. package/dist/esm/src/api/typed-endpoints.d.ts +135 -0
  47. package/dist/esm/src/api/typed-endpoints.d.ts.map +1 -0
  48. package/dist/{src → esm/src}/api/typed-endpoints.js +6 -5
  49. package/dist/esm/src/api/typed-endpoints.js.map +1 -0
  50. package/dist/esm/src/api/validation.d.ts +114 -0
  51. package/dist/esm/src/api/validation.d.ts.map +1 -0
  52. package/dist/{src → esm/src}/api/validation.js +12 -10
  53. package/dist/esm/src/api/validation.js.map +1 -0
  54. package/dist/esm/src/client/FlashnetClient.d.ts +216 -0
  55. package/dist/esm/src/client/FlashnetClient.d.ts.map +1 -0
  56. package/dist/{src → esm/src}/client/FlashnetClient.js +14 -12
  57. package/dist/esm/src/client/FlashnetClient.js.map +1 -0
  58. package/dist/esm/src/config/index.d.ts +14 -0
  59. package/dist/esm/src/config/index.d.ts.map +1 -0
  60. package/dist/{src → esm/src}/config/index.js +9 -7
  61. package/dist/esm/src/config/index.js.map +1 -0
  62. package/dist/esm/src/types/index.d.ts +484 -0
  63. package/dist/esm/src/types/index.d.ts.map +1 -0
  64. package/dist/esm/src/utils/auth.d.ts +26 -0
  65. package/dist/esm/src/utils/auth.d.ts.map +1 -0
  66. package/dist/{src → esm/src}/utils/auth.js +4 -2
  67. package/dist/esm/src/utils/auth.js.map +1 -0
  68. package/dist/esm/src/utils/index.d.ts +8 -0
  69. package/dist/esm/src/utils/index.d.ts.map +1 -0
  70. package/dist/esm/src/utils/index.js +18 -0
  71. package/dist/esm/src/utils/index.js.map +1 -0
  72. package/dist/esm/src/utils/intents.d.ts +86 -0
  73. package/dist/esm/src/utils/intents.d.ts.map +1 -0
  74. package/dist/{src → esm/src}/utils/intents.js +11 -9
  75. package/dist/esm/src/utils/intents.js.map +1 -0
  76. package/dist/esm/src/utils/signer.d.ts +29 -0
  77. package/dist/esm/src/utils/signer.d.ts.map +1 -0
  78. package/dist/{src → esm/src}/utils/signer.js +4 -2
  79. package/dist/esm/src/utils/signer.js.map +1 -0
  80. package/dist/esm/src/utils/spark-address.d.ts +60 -0
  81. package/dist/esm/src/utils/spark-address.d.ts.map +1 -0
  82. package/dist/{src → esm/src}/utils/spark-address.js +11 -8
  83. package/dist/esm/src/utils/spark-address.js.map +1 -0
  84. package/package.json +17 -11
  85. package/dist/index.d.ts.map +0 -1
  86. package/dist/index.js.map +0 -1
  87. package/dist/src/api/client.d.ts.map +0 -1
  88. package/dist/src/api/client.js.map +0 -1
  89. package/dist/src/api/typed-endpoints.d.ts.map +0 -1
  90. package/dist/src/api/typed-endpoints.js.map +0 -1
  91. package/dist/src/api/validation.d.ts.map +0 -1
  92. package/dist/src/api/validation.js.map +0 -1
  93. package/dist/src/client/FlashnetClient.d.ts.map +0 -1
  94. package/dist/src/client/FlashnetClient.js.map +0 -1
  95. package/dist/src/config/index.d.ts.map +0 -1
  96. package/dist/src/config/index.js.map +0 -1
  97. package/dist/src/types/index.d.ts.map +0 -1
  98. package/dist/src/types/index.js +0 -2
  99. package/dist/src/types/index.js.map +0 -1
  100. package/dist/src/utils/auth.d.ts.map +0 -1
  101. package/dist/src/utils/auth.js.map +0 -1
  102. package/dist/src/utils/index.d.ts.map +0 -1
  103. package/dist/src/utils/index.js +0 -19
  104. package/dist/src/utils/index.js.map +0 -1
  105. package/dist/src/utils/intents.d.ts.map +0 -1
  106. package/dist/src/utils/intents.js.map +0 -1
  107. package/dist/src/utils/signer.d.ts.map +0 -1
  108. package/dist/src/utils/signer.js.map +0 -1
  109. package/dist/src/utils/spark-address.d.ts.map +0 -1
  110. package/dist/src/utils/spark-address.js.map +0 -1
  111. /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
  112. /package/dist/{src → cjs/src}/api/client.d.ts +0 -0
  113. /package/dist/{src → cjs/src}/api/typed-endpoints.d.ts +0 -0
  114. /package/dist/{src → cjs/src}/api/validation.d.ts +0 -0
  115. /package/dist/{src → cjs/src}/client/FlashnetClient.d.ts +0 -0
  116. /package/dist/{src → cjs/src}/config/index.d.ts +0 -0
  117. /package/dist/{src → cjs/src}/types/index.d.ts +0 -0
  118. /package/dist/{src → cjs/src}/utils/auth.d.ts +0 -0
  119. /package/dist/{src → cjs/src}/utils/index.d.ts +0 -0
  120. /package/dist/{src → cjs/src}/utils/intents.d.ts +0 -0
  121. /package/dist/{src → cjs/src}/utils/signer.d.ts +0 -0
  122. /package/dist/{src → cjs/src}/utils/spark-address.d.ts +0 -0
@@ -0,0 +1,804 @@
1
+ 'use strict';
2
+
3
+ var client = require('../api/client.js');
4
+ var typedEndpoints = require('../api/typed-endpoints.js');
5
+ var auth = require('../utils/auth.js');
6
+ var signer = require('../utils/signer.js');
7
+ var sparkAddress = require('../utils/spark-address.js');
8
+ var index = require('../config/index.js');
9
+ var index$1 = require('../utils/index.js');
10
+ var intents = require('../utils/intents.js');
11
+ var sparkSdk = require('@buildonspark/spark-sdk');
12
+
13
+ /**
14
+ * FlashnetClient - A comprehensive client for interacting with Flashnet AMM
15
+ *
16
+ * This client wraps a SparkWallet and provides:
17
+ * - Automatic network detection from the wallet
18
+ * - Automatic authentication
19
+ * - Balance checking before operations
20
+ * - All AMM operations (pools, swaps, liquidity, hosts)
21
+ * - Direct wallet access via client.wallet
22
+ */
23
+ class FlashnetClient {
24
+ _wallet;
25
+ apiClient;
26
+ typedApi;
27
+ authManager;
28
+ network;
29
+ publicKey = "";
30
+ sparkAddress = "";
31
+ isAuthenticated = false;
32
+ /**
33
+ * Get the underlying wallet instance for direct wallet operations
34
+ */
35
+ get wallet() {
36
+ return this._wallet;
37
+ }
38
+ /**
39
+ * Get the network type
40
+ */
41
+ get networkType() {
42
+ return this.network;
43
+ }
44
+ /**
45
+ * Get the wallet's public key
46
+ */
47
+ get pubkey() {
48
+ return this.publicKey;
49
+ }
50
+ /**
51
+ * Get the wallet's Spark address
52
+ */
53
+ get address() {
54
+ return this.sparkAddress;
55
+ }
56
+ /**
57
+ * Create a new FlashnetClient instance
58
+ * @param wallet - The SparkWallet to use
59
+ * @param options - Client options
60
+ */
61
+ constructor(wallet, options = {}) {
62
+ this._wallet = wallet;
63
+ // We'll initialize these in the init method
64
+ // @ts-expect-error - wallet.config is protected
65
+ const networkEnum = wallet.config.getNetwork();
66
+ const networkName = sparkSdk.Network[networkEnum];
67
+ this.network = networkName === "MAINNET" ? "MAINNET" : "REGTEST";
68
+ // panic if mainnet for now
69
+ if (networkName === "MAINNET") {
70
+ throw new Error("Mainnet is not supported yet");
71
+ }
72
+ const config = index.getNetworkConfig(this.network);
73
+ this.apiClient = new client.ApiClient(config);
74
+ this.typedApi = new typedEndpoints.TypedAmmApi(this.apiClient);
75
+ this.authManager = new auth.AuthManager(this.apiClient, "", wallet);
76
+ }
77
+ /**
78
+ * Initialize the client by deducing network and authenticating
79
+ * This is called automatically on first use if not called manually
80
+ */
81
+ async initialize() {
82
+ if (this.isAuthenticated) {
83
+ return;
84
+ }
85
+ // Get wallet details
86
+ this.publicKey = await this._wallet.getIdentityPublicKey();
87
+ this.sparkAddress = await this._wallet.getSparkAddress();
88
+ // Deduce network from spark address
89
+ const detectedNetwork = sparkAddress.getNetworkFromAddress(this.sparkAddress);
90
+ if (!detectedNetwork) {
91
+ throw new Error(`Unable to determine network from spark address: ${this.sparkAddress}`);
92
+ }
93
+ this.network = detectedNetwork;
94
+ // panic if mainnet for now
95
+ if (detectedNetwork === "MAINNET") {
96
+ throw new Error("Mainnet is not supported yet");
97
+ }
98
+ // Reinitialize API client with correct network
99
+ const config = index.getNetworkConfig(this.network);
100
+ this.apiClient = new client.ApiClient(config);
101
+ this.typedApi = new typedEndpoints.TypedAmmApi(this.apiClient);
102
+ this.authManager = new auth.AuthManager(this.apiClient, this.publicKey, signer.createWalletSigner(this._wallet));
103
+ // Authenticate
104
+ const token = await this.authManager.authenticate();
105
+ this.apiClient.setAuthToken(token);
106
+ this.isAuthenticated = true;
107
+ }
108
+ /**
109
+ * Ensure the client is initialized
110
+ */
111
+ async ensureInitialized() {
112
+ if (!this.isAuthenticated) {
113
+ await this.initialize();
114
+ }
115
+ }
116
+ /**
117
+ * Get wallet balance including BTC and token balances
118
+ */
119
+ async getBalance() {
120
+ const balance = await this._wallet.getBalance();
121
+ // Convert the wallet's balance format to our format
122
+ const tokenBalances = new Map();
123
+ if (balance.tokenBalances) {
124
+ for (const [tokenPubkey, tokenData] of balance.tokenBalances.entries()) {
125
+ tokenBalances.set(tokenPubkey, {
126
+ balance: BigInt(tokenData.balance),
127
+ tokenInfo: {
128
+ tokenPublicKey: tokenData.tokenInfo.tokenPublicKey,
129
+ tokenName: tokenData.tokenInfo.tokenName,
130
+ tokenSymbol: tokenData.tokenInfo.tokenSymbol,
131
+ tokenDecimals: tokenData.tokenInfo.tokenDecimals,
132
+ maxSupply: tokenData.tokenInfo.maxSupply,
133
+ },
134
+ });
135
+ }
136
+ }
137
+ return {
138
+ balance: BigInt(balance.balance),
139
+ tokenBalances,
140
+ };
141
+ }
142
+ /**
143
+ * Check if wallet has sufficient balance for an operation
144
+ */
145
+ async checkBalance(requirements) {
146
+ const balance = await this.getBalance();
147
+ // Check BTC balance
148
+ if (requirements.btc && balance.balance < requirements.btc) {
149
+ return {
150
+ sufficient: false,
151
+ message: `Insufficient BTC balance. Required: ${requirements.btc} sats, Available: ${balance.balance} sats`,
152
+ };
153
+ }
154
+ // Check token balances
155
+ if (requirements.tokens) {
156
+ for (const [tokenPubkey, requiredAmount,] of requirements.tokens.entries()) {
157
+ const tokenBalance = balance.tokenBalances.get(tokenPubkey);
158
+ const available = tokenBalance?.balance ?? 0n;
159
+ if (available < requiredAmount) {
160
+ return {
161
+ sufficient: false,
162
+ message: `Insufficient token balance for ${tokenPubkey}. Required: ${requiredAmount}, Available: ${available}`,
163
+ };
164
+ }
165
+ }
166
+ }
167
+ return { sufficient: true };
168
+ }
169
+ // ===== Pool Operations =====
170
+ /**
171
+ * List pools with optional filters
172
+ */
173
+ async listPools(query) {
174
+ await this.ensureInitialized();
175
+ return this.typedApi.listPools(query);
176
+ }
177
+ /**
178
+ * Get detailed information about a specific pool
179
+ */
180
+ async getPool(poolId) {
181
+ await this.ensureInitialized();
182
+ return this.typedApi.getPool(poolId);
183
+ }
184
+ /**
185
+ * Get LP position details for a provider in a pool
186
+ */
187
+ async getLpPosition(poolId, providerPublicKey) {
188
+ await this.ensureInitialized();
189
+ const provider = providerPublicKey || this.publicKey;
190
+ return this.typedApi.getLpPosition(poolId, provider);
191
+ }
192
+ /**
193
+ * Create a constant product pool
194
+ */
195
+ async createConstantProductPool(params) {
196
+ await this.ensureInitialized();
197
+ // Check if we need to add initial liquidity
198
+ if (params.initialLiquidity) {
199
+ const requirements = {
200
+ tokens: new Map(),
201
+ };
202
+ if (params.assetATokenPublicKey === index.BTC_ASSET_PUBKEY) {
203
+ requirements.btc = params.initialLiquidity.assetAAmount;
204
+ }
205
+ else {
206
+ requirements.tokens.set(params.assetATokenPublicKey, params.initialLiquidity.assetAAmount);
207
+ }
208
+ if (params.assetBTokenPublicKey === index.BTC_ASSET_PUBKEY) {
209
+ requirements.btc =
210
+ (requirements.btc || 0n) + params.initialLiquidity.assetBAmount;
211
+ }
212
+ else {
213
+ requirements.tokens.set(params.assetBTokenPublicKey, params.initialLiquidity.assetBAmount);
214
+ }
215
+ const balanceCheck = await this.checkBalance(requirements);
216
+ if (!balanceCheck.sufficient) {
217
+ throw new Error(`Insufficient balance for initial liquidity: ${balanceCheck.message}`);
218
+ }
219
+ }
220
+ // Generate intent
221
+ const nonce = index$1.generateNonce();
222
+ const intentMessage = intents.generateConstantProductPoolInitializationIntentMessage({
223
+ poolOwnerPublicKey: this.publicKey,
224
+ assetATokenPublicKey: params.assetATokenPublicKey,
225
+ assetBTokenPublicKey: params.assetBTokenPublicKey,
226
+ lpFeeRateBps: params.lpFeeRateBps.toString(),
227
+ totalHostFeeRateBps: params.totalHostFeeRateBps.toString(),
228
+ nonce,
229
+ });
230
+ // Sign intent
231
+ const messageHash = new Uint8Array(await crypto.subtle.digest("SHA-256", intentMessage));
232
+ const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
233
+ // Create pool
234
+ const request = {
235
+ poolOwnerPublicKey: this.publicKey,
236
+ assetATokenPublicKey: params.assetATokenPublicKey,
237
+ assetBTokenPublicKey: params.assetBTokenPublicKey,
238
+ lpFeeRateBps: params.lpFeeRateBps.toString(),
239
+ totalHostFeeRateBps: params.totalHostFeeRateBps.toString(),
240
+ integratorNamespace: params.integratorNamespace || "",
241
+ nonce,
242
+ signature: Buffer.from(signature).toString("hex"),
243
+ };
244
+ const response = await this.typedApi.createConstantProductPool(request);
245
+ // Add initial liquidity if specified
246
+ if (params.initialLiquidity && response.poolId) {
247
+ await this.addInitialLiquidity(response.poolId, params.assetATokenPublicKey, params.assetBTokenPublicKey, params.initialLiquidity.assetAAmount, params.initialLiquidity.assetBAmount);
248
+ }
249
+ return response;
250
+ }
251
+ /**
252
+ * Create a single-sided pool with automatic initial deposit
253
+ *
254
+ * This method creates a single-sided pool and automatically handles the initial deposit.
255
+ * The initial reserve amount will be transferred to the pool and confirmed.
256
+ */
257
+ async createSingleSidedPool(params) {
258
+ await this.ensureInitialized();
259
+ // Check balance for initial reserve
260
+ const requirements = {
261
+ tokens: new Map(),
262
+ };
263
+ if (params.assetATokenPublicKey === index.BTC_ASSET_PUBKEY) {
264
+ requirements.btc = BigInt(params.assetAInitialReserve);
265
+ }
266
+ else {
267
+ requirements.tokens.set(params.assetATokenPublicKey, BigInt(params.assetAInitialReserve));
268
+ }
269
+ const balanceCheck = await this.checkBalance(requirements);
270
+ if (!balanceCheck.sufficient) {
271
+ throw new Error(`Insufficient balance for pool creation: ${balanceCheck.message}`);
272
+ }
273
+ // Generate intent
274
+ const nonce = index$1.generateNonce();
275
+ const intentMessage = intents.generatePoolInitializationIntentMessage({
276
+ poolOwnerPublicKey: this.publicKey,
277
+ assetATokenPublicKey: params.assetATokenPublicKey,
278
+ assetBTokenPublicKey: params.assetBTokenPublicKey,
279
+ assetAInitialReserve: params.assetAInitialReserve,
280
+ assetAInitialVirtualReserve: params.assetAInitialVirtualReserve,
281
+ assetBInitialVirtualReserve: params.assetBInitialVirtualReserve,
282
+ threshold: params.threshold,
283
+ lpFeeRateBps: params.lpFeeRateBps.toString(),
284
+ totalHostFeeRateBps: params.totalHostFeeRateBps.toString(),
285
+ nonce,
286
+ });
287
+ const messageHash = new Uint8Array(await crypto.subtle.digest("SHA-256", intentMessage));
288
+ const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
289
+ // Create pool
290
+ const request = {
291
+ poolOwnerPublicKey: this.publicKey,
292
+ assetATokenPublicKey: params.assetATokenPublicKey,
293
+ assetBTokenPublicKey: params.assetBTokenPublicKey,
294
+ assetAInitialReserve: params.assetAInitialReserve,
295
+ assetAInitialVirtualReserve: params.assetAInitialVirtualReserve,
296
+ assetBInitialVirtualReserve: params.assetBInitialVirtualReserve,
297
+ threshold: params.threshold,
298
+ lpFeeRateBps: params.lpFeeRateBps.toString(),
299
+ totalHostFeeRateBps: params.totalHostFeeRateBps.toString(),
300
+ hostNamespace: params.hostNamespace,
301
+ nonce,
302
+ signature: Buffer.from(signature).toString("hex"),
303
+ };
304
+ const createResponse = await this.typedApi.createSingleSidedPool(request);
305
+ // If pool creation was successful, handle the initial deposit
306
+ if (createResponse.poolId) {
307
+ try {
308
+ // Transfer initial reserve to the pool
309
+ const lpSparkAddress = sparkAddress.encodeSparkAddress({
310
+ identityPublicKey: createResponse.poolId,
311
+ network: this.network,
312
+ });
313
+ let assetATransferId;
314
+ if (params.assetATokenPublicKey === index.BTC_ASSET_PUBKEY) {
315
+ const transfer = await this._wallet.transfer({
316
+ amountSats: Number(params.assetAInitialReserve),
317
+ receiverSparkAddress: lpSparkAddress,
318
+ });
319
+ assetATransferId = transfer.id;
320
+ }
321
+ else {
322
+ assetATransferId = await this._wallet.transferTokens({
323
+ tokenPublicKey: params.assetATokenPublicKey,
324
+ tokenAmount: BigInt(params.assetAInitialReserve),
325
+ receiverSparkAddress: lpSparkAddress,
326
+ });
327
+ }
328
+ // Confirm the initial deposit
329
+ const confirmNonce = index$1.generateNonce();
330
+ const confirmIntentMessage = intents.generatePoolConfirmInitialDepositIntentMessage({
331
+ poolOwnerPublicKey: this.publicKey,
332
+ lpIdentityPublicKey: createResponse.poolId,
333
+ assetASparkTransferId: assetATransferId,
334
+ nonce: confirmNonce,
335
+ });
336
+ const confirmMessageHash = new Uint8Array(await crypto.subtle.digest("SHA-256", confirmIntentMessage));
337
+ const confirmSignature = await this._wallet.config.signer.signMessageWithIdentityKey(confirmMessageHash, true);
338
+ const confirmRequest = {
339
+ poolId: createResponse.poolId,
340
+ assetASparkTransferId: assetATransferId,
341
+ nonce: confirmNonce,
342
+ signature: Buffer.from(confirmSignature).toString("hex"),
343
+ poolOwnerPublicKey: this.publicKey,
344
+ };
345
+ const confirmResponse = await this.typedApi.confirmInitialDeposit(confirmRequest);
346
+ if (!confirmResponse.confirmed) {
347
+ throw new Error(`Failed to confirm initial deposit: ${confirmResponse.message}`);
348
+ }
349
+ }
350
+ catch (error) {
351
+ // If initial deposit fails, we should inform the user
352
+ throw new Error(`Pool created with ID ${createResponse.poolId}, but initial deposit failed: ${error instanceof Error ? error.message : String(error)}`);
353
+ }
354
+ }
355
+ return createResponse;
356
+ }
357
+ /**
358
+ * Confirm initial deposit for single-sided pool
359
+ *
360
+ * Note: This is typically handled automatically by createSingleSidedPool().
361
+ * Use this method only if you need to manually confirm a deposit (e.g., after a failed attempt).
362
+ */
363
+ async confirmInitialDeposit(poolId, assetASparkTransferId) {
364
+ await this.ensureInitialized();
365
+ const nonce = index$1.generateNonce();
366
+ const intentMessage = intents.generatePoolConfirmInitialDepositIntentMessage({
367
+ poolOwnerPublicKey: this.publicKey,
368
+ lpIdentityPublicKey: poolId,
369
+ assetASparkTransferId,
370
+ nonce,
371
+ });
372
+ const messageHash = new Uint8Array(await crypto.subtle.digest("SHA-256", intentMessage));
373
+ const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
374
+ const request = {
375
+ poolId,
376
+ assetASparkTransferId,
377
+ nonce,
378
+ signature: Buffer.from(signature).toString("hex"),
379
+ poolOwnerPublicKey: this.publicKey,
380
+ };
381
+ return this.typedApi.confirmInitialDeposit(request);
382
+ }
383
+ // ===== Swap Operations =====
384
+ /**
385
+ * Simulate a swap without executing it
386
+ */
387
+ async simulateSwap(params) {
388
+ await this.ensureInitialized();
389
+ return this.typedApi.simulateSwap(params);
390
+ }
391
+ /**
392
+ * Execute a swap
393
+ */
394
+ async executeSwap(params) {
395
+ await this.ensureInitialized();
396
+ // Check balance
397
+ const requirements = {
398
+ tokens: new Map(),
399
+ };
400
+ if (params.assetInTokenPublicKey === index.BTC_ASSET_PUBKEY) {
401
+ requirements.btc = params.amountIn;
402
+ }
403
+ else {
404
+ requirements.tokens.set(params.assetInTokenPublicKey, params.amountIn);
405
+ }
406
+ const balanceCheck = await this.checkBalance(requirements);
407
+ if (!balanceCheck.sufficient) {
408
+ throw new Error(`Insufficient balance for swap: ${balanceCheck.message}`);
409
+ }
410
+ // Transfer assets to pool
411
+ const lpSparkAddress = sparkAddress.encodeSparkAddress({
412
+ identityPublicKey: params.poolId,
413
+ network: this.network,
414
+ });
415
+ let transferId;
416
+ if (params.assetInTokenPublicKey === index.BTC_ASSET_PUBKEY) {
417
+ const transfer = await this._wallet.transfer({
418
+ amountSats: Number(params.amountIn),
419
+ receiverSparkAddress: lpSparkAddress,
420
+ });
421
+ transferId = transfer.id;
422
+ }
423
+ else {
424
+ transferId = await this._wallet.transferTokens({
425
+ tokenPublicKey: params.assetInTokenPublicKey,
426
+ tokenAmount: params.amountIn,
427
+ receiverSparkAddress: lpSparkAddress,
428
+ });
429
+ }
430
+ // Generate swap intent
431
+ const nonce = index$1.generateNonce();
432
+ const intentMessage = intents.generatePoolSwapIntentMessage({
433
+ userPublicKey: this.publicKey,
434
+ lpIdentityPublicKey: params.poolId,
435
+ assetASparkTransferId: transferId,
436
+ assetInTokenPublicKey: params.assetInTokenPublicKey,
437
+ assetOutTokenPublicKey: params.assetOutTokenPublicKey,
438
+ amountIn: params.amountIn.toString(),
439
+ minAmountOut: params.minAmountOut.toString(),
440
+ maxSlippageBps: params.maxSlippageBps.toString(),
441
+ nonce,
442
+ });
443
+ // Sign intent
444
+ const messageHash = new Uint8Array(await crypto.subtle.digest("SHA-256", intentMessage));
445
+ const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
446
+ const request = {
447
+ userPublicKey: this.publicKey,
448
+ poolId: params.poolId,
449
+ assetInTokenPublicKey: params.assetInTokenPublicKey,
450
+ assetOutTokenPublicKey: params.assetOutTokenPublicKey,
451
+ amountIn: params.amountIn.toString(),
452
+ minAmountOut: params.minAmountOut.toString(),
453
+ maxSlippageBps: params.maxSlippageBps?.toString(),
454
+ assetInSparkTransferId: transferId,
455
+ nonce,
456
+ signature: Buffer.from(signature).toString("hex"),
457
+ };
458
+ const response = await this.typedApi.executeSwap(request);
459
+ // Check if the swap was accepted
460
+ if (!response.accepted) {
461
+ const errorMessage = response.error || "Swap rejected by the AMM";
462
+ const refundInfo = response.refundedAmount
463
+ ? ` Refunded ${response.refundedAmount} of ${response.refundedAssetPublicKey} via transfer ${response.refundTransferId}`
464
+ : "";
465
+ throw new Error(`${errorMessage}.${refundInfo}`);
466
+ }
467
+ return response;
468
+ }
469
+ // ===== Liquidity Operations =====
470
+ /**
471
+ * Simulate adding liquidity
472
+ */
473
+ async simulateAddLiquidity(params) {
474
+ await this.ensureInitialized();
475
+ return this.typedApi.simulateAddLiquidity(params);
476
+ }
477
+ /**
478
+ * Add liquidity to a pool
479
+ */
480
+ async addLiquidity(params) {
481
+ await this.ensureInitialized();
482
+ // Get pool details to know which assets we're dealing with
483
+ const pool = await this.getPool(params.poolId);
484
+ // Check balance
485
+ const requirements = {
486
+ tokens: new Map(),
487
+ };
488
+ if (pool.assetATokenPublicKey === index.BTC_ASSET_PUBKEY) {
489
+ requirements.btc = params.assetAAmount;
490
+ }
491
+ else {
492
+ requirements.tokens.set(pool.assetATokenPublicKey, params.assetAAmount);
493
+ }
494
+ if (pool.assetBTokenPublicKey === index.BTC_ASSET_PUBKEY) {
495
+ requirements.btc = (requirements.btc || 0n) + params.assetBAmount;
496
+ }
497
+ else {
498
+ requirements.tokens.set(pool.assetBTokenPublicKey, params.assetBAmount);
499
+ }
500
+ const balanceCheck = await this.checkBalance(requirements);
501
+ if (!balanceCheck.sufficient) {
502
+ throw new Error(`Insufficient balance for adding liquidity: ${balanceCheck.message}`);
503
+ }
504
+ // Transfer assets to pool
505
+ const lpSparkAddress = sparkAddress.encodeSparkAddress({
506
+ identityPublicKey: params.poolId,
507
+ network: this.network,
508
+ });
509
+ // Transfer asset A
510
+ let assetATransferId;
511
+ if (pool.assetATokenPublicKey === index.BTC_ASSET_PUBKEY) {
512
+ const transfer = await this._wallet.transfer({
513
+ amountSats: Number(params.assetAAmount),
514
+ receiverSparkAddress: lpSparkAddress,
515
+ });
516
+ assetATransferId = transfer.id;
517
+ }
518
+ else {
519
+ assetATransferId = await this._wallet.transferTokens({
520
+ tokenPublicKey: pool.assetATokenPublicKey,
521
+ tokenAmount: params.assetAAmount,
522
+ receiverSparkAddress: lpSparkAddress,
523
+ });
524
+ }
525
+ // Transfer asset B
526
+ let assetBTransferId;
527
+ if (pool.assetBTokenPublicKey === index.BTC_ASSET_PUBKEY) {
528
+ const transfer = await this._wallet.transfer({
529
+ amountSats: Number(params.assetBAmount),
530
+ receiverSparkAddress: lpSparkAddress,
531
+ });
532
+ assetBTransferId = transfer.id;
533
+ }
534
+ else {
535
+ assetBTransferId = await this._wallet.transferTokens({
536
+ tokenPublicKey: pool.assetBTokenPublicKey,
537
+ tokenAmount: params.assetBAmount,
538
+ receiverSparkAddress: lpSparkAddress,
539
+ });
540
+ }
541
+ // Generate add liquidity intent
542
+ const nonce = index$1.generateNonce();
543
+ const intentMessage = intents.generateAddLiquidityIntentMessage({
544
+ userPublicKey: this.publicKey,
545
+ lpIdentityPublicKey: params.poolId,
546
+ assetASparkTransferId: assetATransferId,
547
+ assetBSparkTransferId: assetBTransferId,
548
+ assetAAmount: params.assetAAmount.toString(),
549
+ assetBAmount: params.assetBAmount.toString(),
550
+ nonce,
551
+ });
552
+ // Sign intent
553
+ const messageHash = new Uint8Array(await crypto.subtle.digest("SHA-256", intentMessage));
554
+ const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
555
+ const request = {
556
+ userPublicKey: this.publicKey,
557
+ poolId: params.poolId,
558
+ assetASparkTransferId: assetATransferId,
559
+ assetBSparkTransferId: assetBTransferId,
560
+ assetAAmountToAdd: params.assetAAmount.toString(),
561
+ assetBAmountToAdd: params.assetBAmount.toString(),
562
+ nonce,
563
+ signature: Buffer.from(signature).toString("hex"),
564
+ };
565
+ const response = await this.typedApi.addLiquidity(request);
566
+ // Check if the liquidity addition was accepted
567
+ if (!response.accepted) {
568
+ const errorMessage = response.error || "Add liquidity rejected by the AMM";
569
+ const refundInfo = response.refund
570
+ ? ` Refunds: Asset A: ${response.refund.assetAAmount || 0}, Asset B: ${response.refund.assetBAmount || 0}`
571
+ : "";
572
+ throw new Error(`${errorMessage}.${refundInfo}`);
573
+ }
574
+ return response;
575
+ }
576
+ /**
577
+ * Simulate removing liquidity
578
+ */
579
+ async simulateRemoveLiquidity(params) {
580
+ await this.ensureInitialized();
581
+ return this.typedApi.simulateRemoveLiquidity(params);
582
+ }
583
+ /**
584
+ * Remove liquidity from a pool
585
+ */
586
+ async removeLiquidity(params) {
587
+ await this.ensureInitialized();
588
+ // Check LP token balance
589
+ const position = await this.getLpPosition(params.poolId);
590
+ const lpTokensOwned = BigInt(position.lpTokensOwned);
591
+ const tokensToRemove = BigInt(params.lpTokensToRemove);
592
+ if (lpTokensOwned < tokensToRemove) {
593
+ throw new Error(`Insufficient LP tokens. Owned: ${lpTokensOwned}, Requested: ${tokensToRemove}`);
594
+ }
595
+ // Generate remove liquidity intent
596
+ const nonce = index$1.generateNonce();
597
+ const intentMessage = intents.generateRemoveLiquidityIntentMessage({
598
+ userPublicKey: this.publicKey,
599
+ lpIdentityPublicKey: params.poolId,
600
+ lpTokensToRemove: params.lpTokensToRemove,
601
+ nonce,
602
+ });
603
+ // Sign intent
604
+ const messageHash = new Uint8Array(await crypto.subtle.digest("SHA-256", intentMessage));
605
+ const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
606
+ const request = {
607
+ userPublicKey: this.publicKey,
608
+ poolId: params.poolId,
609
+ lpTokensToRemove: params.lpTokensToRemove,
610
+ nonce,
611
+ signature: Buffer.from(signature).toString("hex"),
612
+ };
613
+ const response = await this.typedApi.removeLiquidity(request);
614
+ // Check if the liquidity removal was accepted
615
+ if (!response.accepted) {
616
+ const errorMessage = response.error || "Remove liquidity rejected by the AMM";
617
+ throw new Error(errorMessage);
618
+ }
619
+ return response;
620
+ }
621
+ // ===== Host Operations =====
622
+ /**
623
+ * Register as a host
624
+ */
625
+ async registerHost(params) {
626
+ await this.ensureInitialized();
627
+ const feeRecipient = params.feeRecipientPublicKey || this.publicKey;
628
+ const nonce = index$1.generateNonce();
629
+ // Generate intent
630
+ const intentMessage = intents.generateRegisterHostIntentMessage({
631
+ namespace: params.namespace,
632
+ minFeeBps: params.minFeeBps,
633
+ feeRecipientPublicKey: feeRecipient,
634
+ nonce,
635
+ });
636
+ // Sign intent
637
+ const messageHash = new Uint8Array(await crypto.subtle.digest("SHA-256", intentMessage));
638
+ const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
639
+ const request = {
640
+ namespace: params.namespace,
641
+ minFeeBps: params.minFeeBps,
642
+ feeRecipientPublicKey: feeRecipient,
643
+ nonce,
644
+ signature: Buffer.from(signature).toString("hex"),
645
+ };
646
+ return this.typedApi.registerHost(request);
647
+ }
648
+ /**
649
+ * Get host information
650
+ */
651
+ async getHost(namespace) {
652
+ await this.ensureInitialized();
653
+ return this.typedApi.getHost(namespace);
654
+ }
655
+ /**
656
+ * Get pool host fees
657
+ */
658
+ async getPoolHostFees(hostNamespace, poolId) {
659
+ await this.ensureInitialized();
660
+ return this.typedApi.getPoolHostFees({ hostNamespace, poolId });
661
+ }
662
+ /**
663
+ * Withdraw host fees
664
+ */
665
+ async withdrawHostFees(params) {
666
+ await this.ensureInitialized();
667
+ const nonce = index$1.generateNonce();
668
+ const intentMessage = intents.generateWithdrawHostFeesIntentMessage({
669
+ hostPublicKey: this.publicKey,
670
+ lpIdentityPublicKey: params.lpIdentityPublicKey,
671
+ assetAAmount: params.assetAAmount,
672
+ assetBAmount: params.assetBAmount,
673
+ nonce,
674
+ });
675
+ // Sign intent
676
+ const messageHash = new Uint8Array(await crypto.subtle.digest("SHA-256", intentMessage));
677
+ const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
678
+ const request = {
679
+ lpIdentityPublicKey: params.lpIdentityPublicKey,
680
+ assetAAmount: params.assetAAmount,
681
+ assetBAmount: params.assetBAmount,
682
+ nonce,
683
+ signature: Buffer.from(signature).toString("hex"),
684
+ };
685
+ const response = await this.typedApi.withdrawHostFees(request);
686
+ // Check if the withdrawal was accepted
687
+ if (!response.accepted) {
688
+ const errorMessage = response.error || "Withdraw host fees rejected by the AMM";
689
+ throw new Error(errorMessage);
690
+ }
691
+ return response;
692
+ }
693
+ // ===== Swap History =====
694
+ /**
695
+ * Get swaps for a specific pool
696
+ */
697
+ async getPoolSwaps(lpPubkey, query) {
698
+ await this.ensureInitialized();
699
+ return this.typedApi.getPoolSwaps(lpPubkey, query);
700
+ }
701
+ /**
702
+ * Get global swaps across all pools
703
+ */
704
+ async getGlobalSwaps(query) {
705
+ await this.ensureInitialized();
706
+ return this.typedApi.getGlobalSwaps(query);
707
+ }
708
+ /**
709
+ * Get swaps for a specific user
710
+ */
711
+ async getUserSwaps(userPublicKey, query) {
712
+ await this.ensureInitialized();
713
+ const user = userPublicKey || this.publicKey;
714
+ return this.typedApi.getUserSwaps(user, query);
715
+ }
716
+ // ===== Status =====
717
+ /**
718
+ * Ping the settlement service
719
+ */
720
+ async ping() {
721
+ await this.ensureInitialized();
722
+ return this.typedApi.ping();
723
+ }
724
+ // ===== Helper Methods =====
725
+ /**
726
+ * Helper method to add initial liquidity after pool creation
727
+ */
728
+ async addInitialLiquidity(poolId, assetATokenPublicKey, assetBTokenPublicKey, assetAAmount, assetBAmount) {
729
+ const lpSparkAddress = sparkAddress.encodeSparkAddress({
730
+ identityPublicKey: poolId,
731
+ network: this.network,
732
+ });
733
+ // Transfer asset A
734
+ let assetATransferId;
735
+ if (assetATokenPublicKey === index.BTC_ASSET_PUBKEY) {
736
+ const transfer = await this._wallet.transfer({
737
+ amountSats: Number(assetAAmount),
738
+ receiverSparkAddress: lpSparkAddress,
739
+ });
740
+ assetATransferId = transfer.id;
741
+ }
742
+ else {
743
+ assetATransferId = await this._wallet.transferTokens({
744
+ tokenPublicKey: assetATokenPublicKey,
745
+ tokenAmount: assetAAmount,
746
+ receiverSparkAddress: lpSparkAddress,
747
+ });
748
+ }
749
+ // Transfer asset B
750
+ let assetBTransferId;
751
+ if (assetBTokenPublicKey === index.BTC_ASSET_PUBKEY) {
752
+ const transfer = await this._wallet.transfer({
753
+ amountSats: Number(assetBAmount),
754
+ receiverSparkAddress: lpSparkAddress,
755
+ });
756
+ assetBTransferId = transfer.id;
757
+ }
758
+ else {
759
+ assetBTransferId = await this._wallet.transferTokens({
760
+ tokenPublicKey: assetBTokenPublicKey,
761
+ tokenAmount: assetBAmount,
762
+ receiverSparkAddress: lpSparkAddress,
763
+ });
764
+ }
765
+ // Add liquidity
766
+ const nonce = index$1.generateNonce();
767
+ const intentMessage = intents.generateAddLiquidityIntentMessage({
768
+ userPublicKey: this.publicKey,
769
+ lpIdentityPublicKey: poolId,
770
+ assetASparkTransferId: assetATransferId,
771
+ assetBSparkTransferId: assetBTransferId,
772
+ assetAAmount: assetAAmount.toString(),
773
+ assetBAmount: assetBAmount.toString(),
774
+ nonce,
775
+ });
776
+ const messageHash = new Uint8Array(await crypto.subtle.digest("SHA-256", intentMessage));
777
+ const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
778
+ const request = {
779
+ userPublicKey: this.publicKey,
780
+ poolId: poolId,
781
+ assetASparkTransferId: assetATransferId,
782
+ assetBSparkTransferId: assetBTransferId,
783
+ assetAAmountToAdd: assetAAmount.toString(),
784
+ assetBAmountToAdd: assetBAmount.toString(),
785
+ nonce,
786
+ signature: Buffer.from(signature).toString("hex"),
787
+ };
788
+ const response = await this.typedApi.addLiquidity(request);
789
+ // Check if the initial liquidity addition was accepted
790
+ if (!response.accepted) {
791
+ const errorMessage = response.error || "Initial liquidity addition rejected by the AMM";
792
+ throw new Error(errorMessage);
793
+ }
794
+ }
795
+ /**
796
+ * Clean up wallet connections
797
+ */
798
+ async cleanup() {
799
+ await this._wallet.cleanupConnections();
800
+ }
801
+ }
802
+
803
+ exports.FlashnetClient = FlashnetClient;
804
+ //# sourceMappingURL=FlashnetClient.js.map