@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.
- package/README.md +4 -2
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +56 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/src/api/client.d.ts.map +1 -0
- package/dist/cjs/src/api/client.js +90 -0
- package/dist/cjs/src/api/client.js.map +1 -0
- package/dist/cjs/src/api/typed-endpoints.d.ts.map +1 -0
- package/dist/cjs/src/api/typed-endpoints.js +207 -0
- package/dist/cjs/src/api/typed-endpoints.js.map +1 -0
- package/dist/cjs/src/api/validation.d.ts.map +1 -0
- package/dist/cjs/src/api/validation.js +140 -0
- package/dist/cjs/src/api/validation.js.map +1 -0
- package/dist/cjs/src/client/FlashnetClient.d.ts.map +1 -0
- package/dist/cjs/src/client/FlashnetClient.js +804 -0
- package/dist/cjs/src/client/FlashnetClient.js.map +1 -0
- package/dist/cjs/src/config/index.d.ts.map +1 -0
- package/dist/cjs/src/config/index.js +49 -0
- package/dist/cjs/src/config/index.js.map +1 -0
- package/dist/cjs/src/types/index.d.ts.map +1 -0
- package/dist/cjs/src/utils/auth.d.ts.map +1 -0
- package/dist/cjs/src/utils/auth.js +89 -0
- package/dist/cjs/src/utils/auth.js.map +1 -0
- package/dist/cjs/src/utils/index.d.ts.map +1 -0
- package/dist/cjs/src/utils/index.js +29 -0
- package/dist/cjs/src/utils/index.js.map +1 -0
- package/dist/cjs/src/utils/intents.d.ts.map +1 -0
- package/dist/cjs/src/utils/intents.js +144 -0
- package/dist/cjs/src/utils/intents.js.map +1 -0
- package/dist/cjs/src/utils/signer.d.ts.map +1 -0
- package/dist/cjs/src/utils/signer.js +38 -0
- package/dist/cjs/src/utils/signer.js.map +1 -0
- package/dist/cjs/src/utils/spark-address.d.ts.map +1 -0
- package/dist/cjs/src/utils/spark-address.js +238 -0
- package/dist/cjs/src/utils/spark-address.js.map +1 -0
- package/dist/{index.js → esm/index.d.ts} +6 -8
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/src/api/client.d.ts +20 -0
- package/dist/esm/src/api/client.d.ts.map +1 -0
- package/dist/{src → esm/src}/api/client.js +6 -3
- package/dist/esm/src/api/client.js.map +1 -0
- package/dist/esm/src/api/typed-endpoints.d.ts +135 -0
- package/dist/esm/src/api/typed-endpoints.d.ts.map +1 -0
- package/dist/{src → esm/src}/api/typed-endpoints.js +6 -5
- package/dist/esm/src/api/typed-endpoints.js.map +1 -0
- package/dist/esm/src/api/validation.d.ts +114 -0
- package/dist/esm/src/api/validation.d.ts.map +1 -0
- package/dist/{src → esm/src}/api/validation.js +12 -10
- package/dist/esm/src/api/validation.js.map +1 -0
- package/dist/esm/src/client/FlashnetClient.d.ts +216 -0
- package/dist/esm/src/client/FlashnetClient.d.ts.map +1 -0
- package/dist/{src → esm/src}/client/FlashnetClient.js +14 -12
- package/dist/esm/src/client/FlashnetClient.js.map +1 -0
- package/dist/esm/src/config/index.d.ts +14 -0
- package/dist/esm/src/config/index.d.ts.map +1 -0
- package/dist/{src → esm/src}/config/index.js +9 -7
- package/dist/esm/src/config/index.js.map +1 -0
- package/dist/esm/src/types/index.d.ts +484 -0
- package/dist/esm/src/types/index.d.ts.map +1 -0
- package/dist/esm/src/utils/auth.d.ts +26 -0
- package/dist/esm/src/utils/auth.d.ts.map +1 -0
- package/dist/{src → esm/src}/utils/auth.js +4 -2
- package/dist/esm/src/utils/auth.js.map +1 -0
- package/dist/esm/src/utils/index.d.ts +8 -0
- package/dist/esm/src/utils/index.d.ts.map +1 -0
- package/dist/esm/src/utils/index.js +18 -0
- package/dist/esm/src/utils/index.js.map +1 -0
- package/dist/esm/src/utils/intents.d.ts +86 -0
- package/dist/esm/src/utils/intents.d.ts.map +1 -0
- package/dist/{src → esm/src}/utils/intents.js +11 -9
- package/dist/esm/src/utils/intents.js.map +1 -0
- package/dist/esm/src/utils/signer.d.ts +29 -0
- package/dist/esm/src/utils/signer.d.ts.map +1 -0
- package/dist/{src → esm/src}/utils/signer.js +4 -2
- package/dist/esm/src/utils/signer.js.map +1 -0
- package/dist/esm/src/utils/spark-address.d.ts +60 -0
- package/dist/esm/src/utils/spark-address.d.ts.map +1 -0
- package/dist/{src → esm/src}/utils/spark-address.js +11 -8
- package/dist/esm/src/utils/spark-address.js.map +1 -0
- package/package.json +17 -11
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/src/api/client.d.ts.map +0 -1
- package/dist/src/api/client.js.map +0 -1
- package/dist/src/api/typed-endpoints.d.ts.map +0 -1
- package/dist/src/api/typed-endpoints.js.map +0 -1
- package/dist/src/api/validation.d.ts.map +0 -1
- package/dist/src/api/validation.js.map +0 -1
- package/dist/src/client/FlashnetClient.d.ts.map +0 -1
- package/dist/src/client/FlashnetClient.js.map +0 -1
- package/dist/src/config/index.d.ts.map +0 -1
- package/dist/src/config/index.js.map +0 -1
- package/dist/src/types/index.d.ts.map +0 -1
- package/dist/src/types/index.js +0 -2
- package/dist/src/types/index.js.map +0 -1
- package/dist/src/utils/auth.d.ts.map +0 -1
- package/dist/src/utils/auth.js.map +0 -1
- package/dist/src/utils/index.d.ts.map +0 -1
- package/dist/src/utils/index.js +0 -19
- package/dist/src/utils/index.js.map +0 -1
- package/dist/src/utils/intents.d.ts.map +0 -1
- package/dist/src/utils/intents.js.map +0 -1
- package/dist/src/utils/signer.d.ts.map +0 -1
- package/dist/src/utils/signer.js.map +0 -1
- package/dist/src/utils/spark-address.d.ts.map +0 -1
- package/dist/src/utils/spark-address.js.map +0 -1
- /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
- /package/dist/{src → cjs/src}/api/client.d.ts +0 -0
- /package/dist/{src → cjs/src}/api/typed-endpoints.d.ts +0 -0
- /package/dist/{src → cjs/src}/api/validation.d.ts +0 -0
- /package/dist/{src → cjs/src}/client/FlashnetClient.d.ts +0 -0
- /package/dist/{src → cjs/src}/config/index.d.ts +0 -0
- /package/dist/{src → cjs/src}/types/index.d.ts +0 -0
- /package/dist/{src → cjs/src}/utils/auth.d.ts +0 -0
- /package/dist/{src → cjs/src}/utils/index.d.ts +0 -0
- /package/dist/{src → cjs/src}/utils/intents.d.ts +0 -0
- /package/dist/{src → cjs/src}/utils/signer.d.ts +0 -0
- /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
|