@flashnet/sdk 0.4.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +17 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/src/api/typed-endpoints.d.ts +70 -0
- package/dist/cjs/src/api/typed-endpoints.d.ts.map +1 -1
- package/dist/cjs/src/api/typed-endpoints.js +106 -11
- package/dist/cjs/src/api/typed-endpoints.js.map +1 -1
- package/dist/cjs/src/client/FlashnetClient.d.ts +182 -3
- package/dist/cjs/src/client/FlashnetClient.d.ts.map +1 -1
- package/dist/cjs/src/client/FlashnetClient.js +608 -31
- package/dist/cjs/src/client/FlashnetClient.js.map +1 -1
- package/dist/cjs/src/config/index.js +1 -1
- package/dist/cjs/src/types/errors.js +11 -11
- package/dist/cjs/src/types/index.d.ts +414 -0
- package/dist/cjs/src/types/index.d.ts.map +1 -1
- package/dist/cjs/src/types/index.js +1 -1
- package/dist/cjs/src/utils/index.d.ts +1 -0
- package/dist/cjs/src/utils/index.d.ts.map +1 -1
- package/dist/cjs/src/utils/index.js.map +1 -1
- package/dist/cjs/src/utils/intents.d.ts +91 -0
- package/dist/cjs/src/utils/intents.d.ts.map +1 -1
- package/dist/cjs/src/utils/intents.js +117 -0
- package/dist/cjs/src/utils/intents.js.map +1 -1
- package/dist/cjs/src/utils/spark-address.js +2 -2
- package/dist/cjs/src/utils/tick-math.d.ts +240 -0
- package/dist/cjs/src/utils/tick-math.d.ts.map +1 -0
- package/dist/cjs/src/utils/tick-math.js +299 -0
- package/dist/cjs/src/utils/tick-math.js.map +1 -0
- package/dist/cjs/src/utils/tokenAddress.js +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/src/api/typed-endpoints.d.ts +70 -0
- package/dist/esm/src/api/typed-endpoints.d.ts.map +1 -1
- package/dist/esm/src/api/typed-endpoints.js +106 -11
- package/dist/esm/src/api/typed-endpoints.js.map +1 -1
- package/dist/esm/src/client/FlashnetClient.d.ts +182 -3
- package/dist/esm/src/client/FlashnetClient.d.ts.map +1 -1
- package/dist/esm/src/client/FlashnetClient.js +609 -32
- package/dist/esm/src/client/FlashnetClient.js.map +1 -1
- package/dist/esm/src/config/index.js +1 -1
- package/dist/esm/src/types/errors.js +11 -11
- package/dist/esm/src/types/index.d.ts +414 -0
- package/dist/esm/src/types/index.d.ts.map +1 -1
- package/dist/esm/src/types/index.js +1 -1
- package/dist/esm/src/utils/index.d.ts +1 -0
- package/dist/esm/src/utils/index.d.ts.map +1 -1
- package/dist/esm/src/utils/index.js.map +1 -1
- package/dist/esm/src/utils/intents.d.ts +91 -0
- package/dist/esm/src/utils/intents.d.ts.map +1 -1
- package/dist/esm/src/utils/intents.js +112 -1
- package/dist/esm/src/utils/intents.js.map +1 -1
- package/dist/esm/src/utils/spark-address.js +2 -2
- package/dist/esm/src/utils/tick-math.d.ts +240 -0
- package/dist/esm/src/utils/tick-math.d.ts.map +1 -0
- package/dist/esm/src/utils/tick-math.js +287 -0
- package/dist/esm/src/utils/tick-math.js.map +1 -0
- package/dist/esm/src/utils/tokenAddress.js +1 -1
- package/package.json +6 -3
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var sha256 = require('fast-sha256');
|
|
3
4
|
var client = require('../api/client.js');
|
|
4
5
|
var typedEndpoints = require('../api/typed-endpoints.js');
|
|
5
6
|
var index$1 = require('../config/index.js');
|
|
6
7
|
var index = require('../types/index.js');
|
|
7
8
|
var index$2 = require('../utils/index.js');
|
|
8
9
|
var auth = require('../utils/auth.js');
|
|
9
|
-
var sha256 = require('fast-sha256');
|
|
10
10
|
var hex = require('../utils/hex.js');
|
|
11
11
|
var intents = require('../utils/intents.js');
|
|
12
12
|
var sparkAddress = require('../utils/spark-address.js');
|
|
@@ -220,8 +220,7 @@ class FlashnetClient {
|
|
|
220
220
|
}
|
|
221
221
|
/**
|
|
222
222
|
* Convert a token identifier into the raw hex string form expected by the Flashnet backend.
|
|
223
|
-
*
|
|
224
|
-
* If it is in Bech32m human-readable form, it is decoded to hex.
|
|
223
|
+
* Handles BTC constant, hex strings, and Bech32m human-readable format.
|
|
225
224
|
*/
|
|
226
225
|
toHexTokenIdentifier(tokenIdentifier) {
|
|
227
226
|
if (tokenIdentifier === index$1.BTC_ASSET_PUBKEY) {
|
|
@@ -306,7 +305,7 @@ class FlashnetClient {
|
|
|
306
305
|
}
|
|
307
306
|
}
|
|
308
307
|
}
|
|
309
|
-
//
|
|
308
|
+
// Pool Operations
|
|
310
309
|
/**
|
|
311
310
|
* List pools with optional filters
|
|
312
311
|
*/
|
|
@@ -569,7 +568,7 @@ class FlashnetClient {
|
|
|
569
568
|
};
|
|
570
569
|
return this.typedApi.confirmInitialDeposit(request);
|
|
571
570
|
}
|
|
572
|
-
//
|
|
571
|
+
// Swap Operations
|
|
573
572
|
/**
|
|
574
573
|
* Simulate a swap without executing it
|
|
575
574
|
*/
|
|
@@ -818,7 +817,7 @@ class FlashnetClient {
|
|
|
818
817
|
return response;
|
|
819
818
|
}, [initialTransferId], firstPoolId);
|
|
820
819
|
}
|
|
821
|
-
//
|
|
820
|
+
// Liquidity Operations
|
|
822
821
|
/**
|
|
823
822
|
* Simulate adding liquidity
|
|
824
823
|
*/
|
|
@@ -969,7 +968,7 @@ class FlashnetClient {
|
|
|
969
968
|
}
|
|
970
969
|
return response;
|
|
971
970
|
}
|
|
972
|
-
//
|
|
971
|
+
// Host Operations
|
|
973
972
|
/**
|
|
974
973
|
* Register as a host
|
|
975
974
|
*/
|
|
@@ -1115,7 +1114,7 @@ class FlashnetClient {
|
|
|
1115
1114
|
await this.ensureInitialized();
|
|
1116
1115
|
return this.typedApi.getIntegratorFees();
|
|
1117
1116
|
}
|
|
1118
|
-
//
|
|
1117
|
+
// Escrow Operations
|
|
1119
1118
|
/**
|
|
1120
1119
|
* Creates a new escrow contract.
|
|
1121
1120
|
* This is the first step in a two-step process: create, then fund.
|
|
@@ -1254,7 +1253,7 @@ class FlashnetClient {
|
|
|
1254
1253
|
await this.ensureInitialized();
|
|
1255
1254
|
return this.typedApi.getEscrow(escrowId);
|
|
1256
1255
|
}
|
|
1257
|
-
//
|
|
1256
|
+
// Swap History
|
|
1258
1257
|
/**
|
|
1259
1258
|
* Get swaps for a specific pool
|
|
1260
1259
|
*/
|
|
@@ -1277,7 +1276,7 @@ class FlashnetClient {
|
|
|
1277
1276
|
const user = userPublicKey || this.publicKey;
|
|
1278
1277
|
return this.typedApi.getUserSwaps(user, query);
|
|
1279
1278
|
}
|
|
1280
|
-
//
|
|
1279
|
+
// Clawback
|
|
1281
1280
|
/**
|
|
1282
1281
|
* Request clawback of a stuck inbound transfer to an LP wallet
|
|
1283
1282
|
*/
|
|
@@ -1462,7 +1461,7 @@ class FlashnetClient {
|
|
|
1462
1461
|
throw flashnetError;
|
|
1463
1462
|
}
|
|
1464
1463
|
}
|
|
1465
|
-
//
|
|
1464
|
+
// Clawback Monitor
|
|
1466
1465
|
/**
|
|
1467
1466
|
* Start a background job that periodically polls for clawbackable transfers
|
|
1468
1467
|
* and automatically claws them back.
|
|
@@ -1596,7 +1595,7 @@ class FlashnetClient {
|
|
|
1596
1595
|
},
|
|
1597
1596
|
};
|
|
1598
1597
|
}
|
|
1599
|
-
//
|
|
1598
|
+
// Token Address Operations
|
|
1600
1599
|
/**
|
|
1601
1600
|
* Encode a token identifier into a human-readable token address using the client's Spark network
|
|
1602
1601
|
* @param tokenIdentifier - Token identifier as hex string or Uint8Array
|
|
@@ -1631,8 +1630,8 @@ class FlashnetClient {
|
|
|
1631
1630
|
decodeLegacyTokenAddress(address) {
|
|
1632
1631
|
return tokenAddress.decodeSparkHumanReadableTokenIdentifier(address, this.sparkNetwork);
|
|
1633
1632
|
}
|
|
1634
|
-
//
|
|
1635
|
-
//
|
|
1633
|
+
// Status
|
|
1634
|
+
// Config Inspection
|
|
1636
1635
|
/**
|
|
1637
1636
|
* Get raw feature status list (cached briefly)
|
|
1638
1637
|
*/
|
|
@@ -1693,7 +1692,7 @@ class FlashnetClient {
|
|
|
1693
1692
|
await this.ensureInitialized();
|
|
1694
1693
|
return this.typedApi.ping();
|
|
1695
1694
|
}
|
|
1696
|
-
//
|
|
1695
|
+
// Helper Methods
|
|
1697
1696
|
/**
|
|
1698
1697
|
* Performs asset transfer using generalized asset address for both BTC and tokens.
|
|
1699
1698
|
*/
|
|
@@ -1793,7 +1792,7 @@ class FlashnetClient {
|
|
|
1793
1792
|
throw new Error(errorMessage);
|
|
1794
1793
|
}
|
|
1795
1794
|
}
|
|
1796
|
-
//
|
|
1795
|
+
// Lightning Payment with Token
|
|
1797
1796
|
/**
|
|
1798
1797
|
* Get a quote for paying a Lightning invoice with a token.
|
|
1799
1798
|
* This calculates the optimal pool and token amount needed.
|
|
@@ -1809,7 +1808,18 @@ class FlashnetClient {
|
|
|
1809
1808
|
// Decode the invoice to get the amount
|
|
1810
1809
|
const invoiceAmountSats = await this.decodeInvoiceAmount(invoice);
|
|
1811
1810
|
if (!invoiceAmountSats || invoiceAmountSats <= 0) {
|
|
1812
|
-
throw new
|
|
1811
|
+
throw new errors.FlashnetError("Unable to decode invoice amount. Zero-amount invoices are not supported for token payments.", {
|
|
1812
|
+
response: {
|
|
1813
|
+
errorCode: "FSAG-1002",
|
|
1814
|
+
errorCategory: "Validation",
|
|
1815
|
+
message: "Unable to decode invoice amount. Zero-amount invoices are not supported for token payments.",
|
|
1816
|
+
requestId: "",
|
|
1817
|
+
timestamp: new Date().toISOString(),
|
|
1818
|
+
service: "sdk",
|
|
1819
|
+
severity: "Error",
|
|
1820
|
+
remediation: "Provide a valid BOLT11 invoice with a non-zero amount.",
|
|
1821
|
+
},
|
|
1822
|
+
});
|
|
1813
1823
|
}
|
|
1814
1824
|
// Get Lightning fee estimate
|
|
1815
1825
|
const lightningFeeEstimate = await this.getLightningFeeEstimate(invoice);
|
|
@@ -1828,9 +1838,19 @@ class FlashnetClient {
|
|
|
1828
1838
|
// Check BTC minimum (output from swap)
|
|
1829
1839
|
const btcMinAmount = minAmounts.get(index$1.BTC_ASSET_PUBKEY.toLowerCase());
|
|
1830
1840
|
if (btcMinAmount && totalBtcNeeded < btcMinAmount) {
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1841
|
+
const msg = `Invoice amount too small. Minimum BTC output is ${btcMinAmount} sats, but invoice + lightning fee totals only ${totalBtcNeeded} sats.`;
|
|
1842
|
+
throw new errors.FlashnetError(msg, {
|
|
1843
|
+
response: {
|
|
1844
|
+
errorCode: "FSAG-1003",
|
|
1845
|
+
errorCategory: "Validation",
|
|
1846
|
+
message: msg,
|
|
1847
|
+
requestId: "",
|
|
1848
|
+
timestamp: new Date().toISOString(),
|
|
1849
|
+
service: "sdk",
|
|
1850
|
+
severity: "Error",
|
|
1851
|
+
remediation: `Use an invoice of at least ${btcMinAmount} sats.`,
|
|
1852
|
+
},
|
|
1853
|
+
});
|
|
1834
1854
|
}
|
|
1835
1855
|
// Find the best pool to swap token -> BTC
|
|
1836
1856
|
const poolQuote = await this.findBestPoolForTokenToBtc(tokenAddress, totalBtcNeeded.toString(), options?.integratorFeeRateBps);
|
|
@@ -1839,9 +1859,19 @@ class FlashnetClient {
|
|
|
1839
1859
|
const tokenMinAmount = minAmounts.get(tokenHex);
|
|
1840
1860
|
if (tokenMinAmount &&
|
|
1841
1861
|
BigInt(poolQuote.tokenAmountRequired) < tokenMinAmount) {
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1862
|
+
const msg = `Token amount too small. Minimum input is ${tokenMinAmount} units, but calculated amount is only ${poolQuote.tokenAmountRequired} units.`;
|
|
1863
|
+
throw new errors.FlashnetError(msg, {
|
|
1864
|
+
response: {
|
|
1865
|
+
errorCode: "FSAG-1003",
|
|
1866
|
+
errorCategory: "Validation",
|
|
1867
|
+
message: msg,
|
|
1868
|
+
requestId: "",
|
|
1869
|
+
timestamp: new Date().toISOString(),
|
|
1870
|
+
service: "sdk",
|
|
1871
|
+
severity: "Error",
|
|
1872
|
+
remediation: "Use a larger invoice amount.",
|
|
1873
|
+
},
|
|
1874
|
+
});
|
|
1845
1875
|
}
|
|
1846
1876
|
// Calculate the BTC variable fee adjustment (how much extra we're requesting)
|
|
1847
1877
|
const btcVariableFeeAdjustment = Number(totalBtcNeeded - baseBtcNeeded);
|
|
@@ -2075,6 +2105,8 @@ class FlashnetClient {
|
|
|
2075
2105
|
const tokenHex = this.toHexTokenIdentifier(tokenAddress);
|
|
2076
2106
|
const btcHex = index$1.BTC_ASSET_PUBKEY;
|
|
2077
2107
|
// Find all pools that have this token paired with BTC
|
|
2108
|
+
// Note: The API may return the same pool for both filter combinations,
|
|
2109
|
+
// so we need to deduplicate and determine tokenIsAssetA from actual pool data
|
|
2078
2110
|
const poolsWithTokenAsA = await this.listPools({
|
|
2079
2111
|
assetAAddress: tokenHex,
|
|
2080
2112
|
assetBAddress: btcHex,
|
|
@@ -2083,17 +2115,57 @@ class FlashnetClient {
|
|
|
2083
2115
|
assetAAddress: btcHex,
|
|
2084
2116
|
assetBAddress: tokenHex,
|
|
2085
2117
|
});
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2118
|
+
// Deduplicate pools by poolId and determine tokenIsAssetA from actual pool addresses
|
|
2119
|
+
const poolMap = new Map();
|
|
2120
|
+
for (const p of [...poolsWithTokenAsA.pools, ...poolsWithTokenAsB.pools]) {
|
|
2121
|
+
if (!poolMap.has(p.lpPublicKey)) {
|
|
2122
|
+
// Determine tokenIsAssetA from actual pool asset addresses, not from which query returned it
|
|
2123
|
+
const tokenIsAssetA = p.assetAAddress?.toLowerCase() === tokenHex.toLowerCase();
|
|
2124
|
+
poolMap.set(p.lpPublicKey, { pool: p, tokenIsAssetA });
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
const allPools = Array.from(poolMap.values()).map(({ pool, tokenIsAssetA }) => ({
|
|
2128
|
+
...pool,
|
|
2129
|
+
tokenIsAssetA,
|
|
2130
|
+
}));
|
|
2090
2131
|
if (allPools.length === 0) {
|
|
2091
|
-
throw new
|
|
2132
|
+
throw new errors.FlashnetError(`No liquidity pool found for token ${tokenAddress} paired with BTC`, {
|
|
2133
|
+
response: {
|
|
2134
|
+
errorCode: "FSAG-4001",
|
|
2135
|
+
errorCategory: "Business",
|
|
2136
|
+
message: `No liquidity pool found for token ${tokenAddress} paired with BTC`,
|
|
2137
|
+
requestId: "",
|
|
2138
|
+
timestamp: new Date().toISOString(),
|
|
2139
|
+
service: "sdk",
|
|
2140
|
+
severity: "Error",
|
|
2141
|
+
},
|
|
2142
|
+
});
|
|
2143
|
+
}
|
|
2144
|
+
// Pre-check: Get minimum amounts to provide clear error if invoice is too small
|
|
2145
|
+
const minAmounts = await this.getMinAmountsMap();
|
|
2146
|
+
const btcMinAmount = minAmounts.get(index$1.BTC_ASSET_PUBKEY.toLowerCase());
|
|
2147
|
+
// Check if the BTC amount needed is below the minimum
|
|
2148
|
+
if (btcMinAmount && BigInt(btcAmountNeeded) < btcMinAmount) {
|
|
2149
|
+
const msg = `Invoice amount too small. Minimum ${btcMinAmount} sats required, but invoice only requires ${btcAmountNeeded} sats.`;
|
|
2150
|
+
throw new errors.FlashnetError(msg, {
|
|
2151
|
+
response: {
|
|
2152
|
+
errorCode: "FSAG-1003",
|
|
2153
|
+
errorCategory: "Validation",
|
|
2154
|
+
message: msg,
|
|
2155
|
+
requestId: "",
|
|
2156
|
+
timestamp: new Date().toISOString(),
|
|
2157
|
+
service: "sdk",
|
|
2158
|
+
severity: "Error",
|
|
2159
|
+
remediation: `Use an invoice with at least ${btcMinAmount} sats.`,
|
|
2160
|
+
},
|
|
2161
|
+
});
|
|
2092
2162
|
}
|
|
2093
2163
|
// Find the best pool (lowest token cost for the required BTC)
|
|
2094
2164
|
let bestPool = null;
|
|
2095
2165
|
let bestTokenAmount = BigInt(Number.MAX_SAFE_INTEGER);
|
|
2096
2166
|
let bestSimulation = null;
|
|
2167
|
+
// Track errors for each pool to provide better diagnostics
|
|
2168
|
+
const poolErrors = [];
|
|
2097
2169
|
for (const pool of allPools) {
|
|
2098
2170
|
try {
|
|
2099
2171
|
// Get pool details for reserves
|
|
@@ -2127,12 +2199,53 @@ class FlashnetClient {
|
|
|
2127
2199
|
warningMessage: simulation.warningMessage,
|
|
2128
2200
|
};
|
|
2129
2201
|
}
|
|
2202
|
+
else {
|
|
2203
|
+
// Simulation output was insufficient
|
|
2204
|
+
const btcReserve = pool.tokenIsAssetA
|
|
2205
|
+
? poolDetails.assetBReserve
|
|
2206
|
+
: poolDetails.assetAReserve;
|
|
2207
|
+
poolErrors.push({
|
|
2208
|
+
poolId: pool.lpPublicKey,
|
|
2209
|
+
error: `Simulation output (${simulation.amountOut} sats) < required (${btcAmountNeeded} sats)`,
|
|
2210
|
+
btcReserve,
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2130
2213
|
}
|
|
2131
2214
|
}
|
|
2132
|
-
catch {
|
|
2215
|
+
catch (e) {
|
|
2216
|
+
// Capture pool errors for diagnostics
|
|
2217
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
2218
|
+
poolErrors.push({
|
|
2219
|
+
poolId: pool.lpPublicKey,
|
|
2220
|
+
error: errorMessage,
|
|
2221
|
+
});
|
|
2222
|
+
}
|
|
2133
2223
|
}
|
|
2134
2224
|
if (!bestPool || !bestSimulation) {
|
|
2135
|
-
|
|
2225
|
+
let errorMessage = `No pool has sufficient liquidity for ${btcAmountNeeded} sats`;
|
|
2226
|
+
if (poolErrors.length > 0) {
|
|
2227
|
+
const details = poolErrors
|
|
2228
|
+
.map((pe) => {
|
|
2229
|
+
const reserveInfo = pe.btcReserve
|
|
2230
|
+
? ` (BTC reserve: ${pe.btcReserve})`
|
|
2231
|
+
: "";
|
|
2232
|
+
return ` - Pool ${pe.poolId.slice(0, 12)}...${reserveInfo}: ${pe.error}`;
|
|
2233
|
+
})
|
|
2234
|
+
.join("\n");
|
|
2235
|
+
errorMessage += `\n\nPool evaluation details:\n${details}`;
|
|
2236
|
+
}
|
|
2237
|
+
throw new errors.FlashnetError(errorMessage, {
|
|
2238
|
+
response: {
|
|
2239
|
+
errorCode: "FSAG-4201",
|
|
2240
|
+
errorCategory: "Business",
|
|
2241
|
+
message: errorMessage,
|
|
2242
|
+
requestId: "",
|
|
2243
|
+
timestamp: new Date().toISOString(),
|
|
2244
|
+
service: "sdk",
|
|
2245
|
+
severity: "Error",
|
|
2246
|
+
remediation: "Try a smaller amount or wait for more liquidity.",
|
|
2247
|
+
},
|
|
2248
|
+
});
|
|
2136
2249
|
}
|
|
2137
2250
|
const poolDetails = await this.getPool(bestPool.lpPublicKey);
|
|
2138
2251
|
return {
|
|
@@ -2381,7 +2494,7 @@ class FlashnetClient {
|
|
|
2381
2494
|
async cleanup() {
|
|
2382
2495
|
await this._wallet.cleanupConnections();
|
|
2383
2496
|
}
|
|
2384
|
-
//
|
|
2497
|
+
// Config and Policy Enforcement Helpers
|
|
2385
2498
|
async ensureAmmOperationAllowed(requiredFeature) {
|
|
2386
2499
|
await this.ensurePingOk();
|
|
2387
2500
|
const featureMap = await this.getFeatureStatusMap();
|
|
@@ -2561,6 +2674,470 @@ ${relaxed.toString()} (50% relaxed), provided minAmountOut ${minAmountOut.toStri
|
|
|
2561
2674
|
throw new Error(`Asset B is not allowed for pool creation: ${assetBHex}`);
|
|
2562
2675
|
}
|
|
2563
2676
|
}
|
|
2677
|
+
// V3 Concentrated Liquidity Operations
|
|
2678
|
+
/**
|
|
2679
|
+
* Create a V3 concentrated liquidity pool
|
|
2680
|
+
*
|
|
2681
|
+
* Concentrated liquidity pools allow LPs to provide liquidity within specific
|
|
2682
|
+
* price ranges (tick ranges) for higher capital efficiency.
|
|
2683
|
+
*
|
|
2684
|
+
* @param params Pool creation parameters
|
|
2685
|
+
* @param params.assetAAddress - Address of asset A (base asset)
|
|
2686
|
+
* @param params.assetBAddress - Address of asset B (quote asset)
|
|
2687
|
+
* @param params.tickSpacing - Tick spacing (common values: 10, 60, 200)
|
|
2688
|
+
* @param params.initialPrice - Initial price of asset A in terms of asset B
|
|
2689
|
+
* @param params.lpFeeRateBps - LP fee rate in basis points
|
|
2690
|
+
* @param params.hostFeeRateBps - Host fee rate in basis points
|
|
2691
|
+
* @param params.hostNamespace - Optional host namespace
|
|
2692
|
+
* @param params.poolOwnerPublicKey - Optional pool owner (defaults to wallet pubkey)
|
|
2693
|
+
*/
|
|
2694
|
+
async createConcentratedPool(params) {
|
|
2695
|
+
await this.ensureInitialized();
|
|
2696
|
+
await this.ensureAmmOperationAllowed("allow_pool_creation");
|
|
2697
|
+
await this.assertAllowedAssetBForPoolCreation(this.toHexTokenIdentifier(params.assetBAddress));
|
|
2698
|
+
const poolOwnerPublicKey = params.poolOwnerPublicKey ?? this.publicKey;
|
|
2699
|
+
// Generate intent
|
|
2700
|
+
const nonce = index$2.generateNonce();
|
|
2701
|
+
const intentMessage = intents.generateCreateConcentratedPoolIntentMessage({
|
|
2702
|
+
poolOwnerPublicKey,
|
|
2703
|
+
assetAAddress: this.toHexTokenIdentifier(params.assetAAddress),
|
|
2704
|
+
assetBAddress: this.toHexTokenIdentifier(params.assetBAddress),
|
|
2705
|
+
tickSpacing: params.tickSpacing,
|
|
2706
|
+
initialPrice: params.initialPrice,
|
|
2707
|
+
lpFeeRateBps: params.lpFeeRateBps.toString(),
|
|
2708
|
+
hostFeeRateBps: params.hostFeeRateBps.toString(),
|
|
2709
|
+
nonce,
|
|
2710
|
+
});
|
|
2711
|
+
// Sign intent
|
|
2712
|
+
const messageHash = sha256__default.default(intentMessage);
|
|
2713
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
2714
|
+
const request = {
|
|
2715
|
+
poolOwnerPublicKey,
|
|
2716
|
+
assetAAddress: this.toHexTokenIdentifier(params.assetAAddress),
|
|
2717
|
+
assetBAddress: this.toHexTokenIdentifier(params.assetBAddress),
|
|
2718
|
+
tickSpacing: params.tickSpacing,
|
|
2719
|
+
initialPrice: params.initialPrice,
|
|
2720
|
+
lpFeeRateBps: params.lpFeeRateBps.toString(),
|
|
2721
|
+
hostFeeRateBps: params.hostFeeRateBps.toString(),
|
|
2722
|
+
hostNamespace: params.hostNamespace,
|
|
2723
|
+
nonce,
|
|
2724
|
+
signature: hex.getHexFromUint8Array(signature),
|
|
2725
|
+
};
|
|
2726
|
+
return this.typedApi.createConcentratedPool(request);
|
|
2727
|
+
}
|
|
2728
|
+
/**
|
|
2729
|
+
* Add liquidity to a V3 concentrated position
|
|
2730
|
+
*
|
|
2731
|
+
* Increases liquidity within a specific tick range. If the position doesn't exist,
|
|
2732
|
+
* a new position is created.
|
|
2733
|
+
*
|
|
2734
|
+
* @param params Position parameters
|
|
2735
|
+
* @param params.poolId - Pool ID (LP identity public key)
|
|
2736
|
+
* @param params.tickLower - Lower tick of the position
|
|
2737
|
+
* @param params.tickUpper - Upper tick of the position
|
|
2738
|
+
* @param params.amountADesired - Desired amount of asset A to add
|
|
2739
|
+
* @param params.amountBDesired - Desired amount of asset B to add
|
|
2740
|
+
* @param params.amountAMin - Minimum amount of asset A (slippage protection)
|
|
2741
|
+
* @param params.amountBMin - Minimum amount of asset B (slippage protection)
|
|
2742
|
+
* @param params.useFreeBalanceA - If true, use free balance from pool for asset A instead of Spark transfer
|
|
2743
|
+
* @param params.useFreeBalanceB - If true, use free balance from pool for asset B instead of Spark transfer
|
|
2744
|
+
* @param params.retainExcessInBalance - If true, retain any excess amounts in pool free balance instead of refunding via Spark
|
|
2745
|
+
*/
|
|
2746
|
+
async increaseLiquidity(params) {
|
|
2747
|
+
await this.ensureInitialized();
|
|
2748
|
+
await this.ensureAmmOperationAllowed("allow_add_liquidity");
|
|
2749
|
+
// Get pool details to know asset addresses
|
|
2750
|
+
const pool = await this.getPool(params.poolId);
|
|
2751
|
+
// Transfer assets to pool (unless using free balance)
|
|
2752
|
+
const lpSparkAddress = sparkAddress.encodeSparkAddressNew({
|
|
2753
|
+
identityPublicKey: params.poolId,
|
|
2754
|
+
network: this.sparkNetwork,
|
|
2755
|
+
});
|
|
2756
|
+
let assetATransferId = "";
|
|
2757
|
+
let assetBTransferId = "";
|
|
2758
|
+
const transferIds = [];
|
|
2759
|
+
// Transfer asset A if not using free balance
|
|
2760
|
+
if (!params.useFreeBalanceA && BigInt(params.amountADesired) > 0n) {
|
|
2761
|
+
assetATransferId = await this.transferAsset({
|
|
2762
|
+
receiverSparkAddress: lpSparkAddress,
|
|
2763
|
+
assetAddress: pool.assetAAddress,
|
|
2764
|
+
amount: params.amountADesired,
|
|
2765
|
+
}, "Insufficient balance for adding V3 liquidity (Asset A): ");
|
|
2766
|
+
transferIds.push(assetATransferId);
|
|
2767
|
+
}
|
|
2768
|
+
// Transfer asset B if not using free balance
|
|
2769
|
+
if (!params.useFreeBalanceB && BigInt(params.amountBDesired) > 0n) {
|
|
2770
|
+
assetBTransferId = await this.transferAsset({
|
|
2771
|
+
receiverSparkAddress: lpSparkAddress,
|
|
2772
|
+
assetAddress: pool.assetBAddress,
|
|
2773
|
+
amount: params.amountBDesired,
|
|
2774
|
+
}, "Insufficient balance for adding V3 liquidity (Asset B): ");
|
|
2775
|
+
transferIds.push(assetBTransferId);
|
|
2776
|
+
}
|
|
2777
|
+
const executeIncrease = async () => {
|
|
2778
|
+
// Generate intent
|
|
2779
|
+
const nonce = index$2.generateNonce();
|
|
2780
|
+
const intentMessage = intents.generateIncreaseLiquidityIntentMessage({
|
|
2781
|
+
userPublicKey: this.publicKey,
|
|
2782
|
+
lpIdentityPublicKey: params.poolId,
|
|
2783
|
+
tickLower: params.tickLower,
|
|
2784
|
+
tickUpper: params.tickUpper,
|
|
2785
|
+
assetASparkTransferId: assetATransferId,
|
|
2786
|
+
assetBSparkTransferId: assetBTransferId,
|
|
2787
|
+
amountADesired: params.amountADesired,
|
|
2788
|
+
amountBDesired: params.amountBDesired,
|
|
2789
|
+
amountAMin: params.amountAMin,
|
|
2790
|
+
amountBMin: params.amountBMin,
|
|
2791
|
+
nonce,
|
|
2792
|
+
});
|
|
2793
|
+
// Sign intent
|
|
2794
|
+
const messageHash = sha256__default.default(intentMessage);
|
|
2795
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
2796
|
+
const request = {
|
|
2797
|
+
poolId: params.poolId,
|
|
2798
|
+
tickLower: params.tickLower,
|
|
2799
|
+
tickUpper: params.tickUpper,
|
|
2800
|
+
assetASparkTransferId: assetATransferId,
|
|
2801
|
+
assetBSparkTransferId: assetBTransferId,
|
|
2802
|
+
amountADesired: params.amountADesired,
|
|
2803
|
+
amountBDesired: params.amountBDesired,
|
|
2804
|
+
amountAMin: params.amountAMin,
|
|
2805
|
+
amountBMin: params.amountBMin,
|
|
2806
|
+
useFreeBalanceA: params.useFreeBalanceA,
|
|
2807
|
+
useFreeBalanceB: params.useFreeBalanceB,
|
|
2808
|
+
retainExcessInBalance: params.retainExcessInBalance,
|
|
2809
|
+
nonce,
|
|
2810
|
+
signature: hex.getHexFromUint8Array(signature),
|
|
2811
|
+
};
|
|
2812
|
+
const response = await this.typedApi.increaseLiquidity(request);
|
|
2813
|
+
if (!response.accepted) {
|
|
2814
|
+
const errorMessage = response.error || "Increase liquidity rejected by the AMM";
|
|
2815
|
+
const hasRefund = !!(response.amountARefund || response.amountBRefund);
|
|
2816
|
+
const refundInfo = hasRefund
|
|
2817
|
+
? ` Refunds: Asset A: ${response.amountARefund || "0"}, Asset B: ${response.amountBRefund || "0"}`
|
|
2818
|
+
: "";
|
|
2819
|
+
throw new errors.FlashnetError(`${errorMessage}.${refundInfo}`, {
|
|
2820
|
+
response: {
|
|
2821
|
+
errorCode: hasRefund ? "FSAG-4203" : "UNKNOWN",
|
|
2822
|
+
errorCategory: hasRefund ? "Business" : "System",
|
|
2823
|
+
message: `${errorMessage}.${refundInfo}`,
|
|
2824
|
+
requestId: response.requestId || "",
|
|
2825
|
+
timestamp: new Date().toISOString(),
|
|
2826
|
+
service: "amm-gateway",
|
|
2827
|
+
severity: "Error",
|
|
2828
|
+
},
|
|
2829
|
+
httpStatus: 400,
|
|
2830
|
+
transferIds: hasRefund ? [] : transferIds,
|
|
2831
|
+
lpIdentityPublicKey: params.poolId,
|
|
2832
|
+
});
|
|
2833
|
+
}
|
|
2834
|
+
return response;
|
|
2835
|
+
};
|
|
2836
|
+
// Execute with auto-clawback if we made transfers
|
|
2837
|
+
if (transferIds.length > 0) {
|
|
2838
|
+
return this.executeWithAutoClawback(executeIncrease, transferIds, params.poolId);
|
|
2839
|
+
}
|
|
2840
|
+
return executeIncrease();
|
|
2841
|
+
}
|
|
2842
|
+
/**
|
|
2843
|
+
* Remove liquidity from a V3 concentrated position
|
|
2844
|
+
*
|
|
2845
|
+
* Decreases liquidity from a specific tick range position.
|
|
2846
|
+
*
|
|
2847
|
+
* @param params Position parameters
|
|
2848
|
+
* @param params.poolId - Pool ID (LP identity public key)
|
|
2849
|
+
* @param params.tickLower - Lower tick of the position
|
|
2850
|
+
* @param params.tickUpper - Upper tick of the position
|
|
2851
|
+
* @param params.liquidityToRemove - Amount of liquidity to remove (use "0" to remove all)
|
|
2852
|
+
* @param params.amountAMin - Minimum amount of asset A to receive (slippage protection)
|
|
2853
|
+
* @param params.amountBMin - Minimum amount of asset B to receive (slippage protection)
|
|
2854
|
+
* @param params.retainInBalance - If true, retain withdrawn assets in pool free balance instead of sending via Spark
|
|
2855
|
+
*/
|
|
2856
|
+
async decreaseLiquidity(params) {
|
|
2857
|
+
await this.ensureInitialized();
|
|
2858
|
+
await this.ensureAmmOperationAllowed("allow_withdraw_liquidity");
|
|
2859
|
+
// Generate intent
|
|
2860
|
+
const nonce = index$2.generateNonce();
|
|
2861
|
+
const intentMessage = intents.generateDecreaseLiquidityIntentMessage({
|
|
2862
|
+
userPublicKey: this.publicKey,
|
|
2863
|
+
lpIdentityPublicKey: params.poolId,
|
|
2864
|
+
tickLower: params.tickLower,
|
|
2865
|
+
tickUpper: params.tickUpper,
|
|
2866
|
+
liquidityToRemove: params.liquidityToRemove,
|
|
2867
|
+
amountAMin: params.amountAMin,
|
|
2868
|
+
amountBMin: params.amountBMin,
|
|
2869
|
+
nonce,
|
|
2870
|
+
});
|
|
2871
|
+
// Sign intent
|
|
2872
|
+
const messageHash = sha256__default.default(intentMessage);
|
|
2873
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
2874
|
+
const request = {
|
|
2875
|
+
poolId: params.poolId,
|
|
2876
|
+
tickLower: params.tickLower,
|
|
2877
|
+
tickUpper: params.tickUpper,
|
|
2878
|
+
liquidityToRemove: params.liquidityToRemove,
|
|
2879
|
+
amountAMin: params.amountAMin,
|
|
2880
|
+
amountBMin: params.amountBMin,
|
|
2881
|
+
retainInBalance: params.retainInBalance,
|
|
2882
|
+
nonce,
|
|
2883
|
+
signature: hex.getHexFromUint8Array(signature),
|
|
2884
|
+
};
|
|
2885
|
+
const response = await this.typedApi.decreaseLiquidity(request);
|
|
2886
|
+
if (!response.accepted) {
|
|
2887
|
+
const errorMessage = response.error || "Decrease liquidity rejected by the AMM";
|
|
2888
|
+
throw new Error(errorMessage);
|
|
2889
|
+
}
|
|
2890
|
+
return response;
|
|
2891
|
+
}
|
|
2892
|
+
/**
|
|
2893
|
+
* Collect accumulated fees from a V3 position
|
|
2894
|
+
*
|
|
2895
|
+
* Collects fees earned from trading activity without removing liquidity.
|
|
2896
|
+
*
|
|
2897
|
+
* @param params Position parameters
|
|
2898
|
+
* @param params.poolId - Pool ID (LP identity public key)
|
|
2899
|
+
* @param params.tickLower - Lower tick of the position
|
|
2900
|
+
* @param params.tickUpper - Upper tick of the position
|
|
2901
|
+
* @param params.retainInBalance - If true, retain collected fees in pool free balance instead of sending via Spark
|
|
2902
|
+
*/
|
|
2903
|
+
async collectFees(params) {
|
|
2904
|
+
await this.ensureInitialized();
|
|
2905
|
+
await this.ensureAmmOperationAllowed("allow_withdraw_fees");
|
|
2906
|
+
// Generate intent
|
|
2907
|
+
const nonce = index$2.generateNonce();
|
|
2908
|
+
const intentMessage = intents.generateCollectFeesIntentMessage({
|
|
2909
|
+
userPublicKey: this.publicKey,
|
|
2910
|
+
lpIdentityPublicKey: params.poolId,
|
|
2911
|
+
tickLower: params.tickLower,
|
|
2912
|
+
tickUpper: params.tickUpper,
|
|
2913
|
+
nonce,
|
|
2914
|
+
});
|
|
2915
|
+
// Sign intent
|
|
2916
|
+
const messageHash = sha256__default.default(intentMessage);
|
|
2917
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
2918
|
+
const request = {
|
|
2919
|
+
poolId: params.poolId,
|
|
2920
|
+
tickLower: params.tickLower,
|
|
2921
|
+
tickUpper: params.tickUpper,
|
|
2922
|
+
retainInBalance: params.retainInBalance,
|
|
2923
|
+
nonce,
|
|
2924
|
+
signature: hex.getHexFromUint8Array(signature),
|
|
2925
|
+
};
|
|
2926
|
+
const response = await this.typedApi.collectFees(request);
|
|
2927
|
+
if (!response.accepted) {
|
|
2928
|
+
const errorMessage = response.error || "Collect fees rejected by the AMM";
|
|
2929
|
+
throw new Error(errorMessage);
|
|
2930
|
+
}
|
|
2931
|
+
return response;
|
|
2932
|
+
}
|
|
2933
|
+
/**
|
|
2934
|
+
* Rebalance a V3 position to a new tick range
|
|
2935
|
+
*
|
|
2936
|
+
* Atomically moves liquidity from an old position to a new tick range.
|
|
2937
|
+
* Optionally can add additional funds during rebalancing.
|
|
2938
|
+
*
|
|
2939
|
+
* @param params Rebalance parameters
|
|
2940
|
+
* @param params.poolId - Pool ID (LP identity public key)
|
|
2941
|
+
* @param params.oldTickLower - Lower tick of the current position
|
|
2942
|
+
* @param params.oldTickUpper - Upper tick of the current position
|
|
2943
|
+
* @param params.newTickLower - Lower tick for the new position
|
|
2944
|
+
* @param params.newTickUpper - Upper tick for the new position
|
|
2945
|
+
* @param params.liquidityToMove - Amount of liquidity to move (use "0" to move all)
|
|
2946
|
+
* @param params.additionalAmountA - Optional additional asset A to add
|
|
2947
|
+
* @param params.additionalAmountB - Optional additional asset B to add
|
|
2948
|
+
* @param params.retainInBalance - If true, retain any excess amounts in pool free balance instead of sending via Spark
|
|
2949
|
+
*/
|
|
2950
|
+
async rebalancePosition(params) {
|
|
2951
|
+
await this.ensureInitialized();
|
|
2952
|
+
await this.ensureAmmOperationAllowed("allow_add_liquidity");
|
|
2953
|
+
// Get pool details
|
|
2954
|
+
const pool = await this.getPool(params.poolId);
|
|
2955
|
+
// Transfer additional assets if provided
|
|
2956
|
+
let assetATransferId;
|
|
2957
|
+
let assetBTransferId;
|
|
2958
|
+
const lpSparkAddress = sparkAddress.encodeSparkAddressNew({
|
|
2959
|
+
identityPublicKey: params.poolId,
|
|
2960
|
+
network: this.sparkNetwork,
|
|
2961
|
+
});
|
|
2962
|
+
if (params.additionalAmountA && BigInt(params.additionalAmountA) > 0n) {
|
|
2963
|
+
assetATransferId = await this.transferAsset({
|
|
2964
|
+
receiverSparkAddress: lpSparkAddress,
|
|
2965
|
+
assetAddress: pool.assetAAddress,
|
|
2966
|
+
amount: params.additionalAmountA,
|
|
2967
|
+
}, "Insufficient balance for rebalance (Asset A): ");
|
|
2968
|
+
}
|
|
2969
|
+
if (params.additionalAmountB && BigInt(params.additionalAmountB) > 0n) {
|
|
2970
|
+
assetBTransferId = await this.transferAsset({
|
|
2971
|
+
receiverSparkAddress: lpSparkAddress,
|
|
2972
|
+
assetAddress: pool.assetBAddress,
|
|
2973
|
+
amount: params.additionalAmountB,
|
|
2974
|
+
}, "Insufficient balance for rebalance (Asset B): ");
|
|
2975
|
+
}
|
|
2976
|
+
// Collect transfer IDs for potential clawback
|
|
2977
|
+
const transferIds = [];
|
|
2978
|
+
if (assetATransferId) {
|
|
2979
|
+
transferIds.push(assetATransferId);
|
|
2980
|
+
}
|
|
2981
|
+
if (assetBTransferId) {
|
|
2982
|
+
transferIds.push(assetBTransferId);
|
|
2983
|
+
}
|
|
2984
|
+
// Execute (with auto-clawback if we have transfers)
|
|
2985
|
+
const executeRebalance = async () => {
|
|
2986
|
+
// Generate intent
|
|
2987
|
+
const nonce = index$2.generateNonce();
|
|
2988
|
+
const intentMessage = intents.generateRebalancePositionIntentMessage({
|
|
2989
|
+
userPublicKey: this.publicKey,
|
|
2990
|
+
lpIdentityPublicKey: params.poolId,
|
|
2991
|
+
oldTickLower: params.oldTickLower,
|
|
2992
|
+
oldTickUpper: params.oldTickUpper,
|
|
2993
|
+
newTickLower: params.newTickLower,
|
|
2994
|
+
newTickUpper: params.newTickUpper,
|
|
2995
|
+
liquidityToMove: params.liquidityToMove,
|
|
2996
|
+
assetASparkTransferId: assetATransferId,
|
|
2997
|
+
assetBSparkTransferId: assetBTransferId,
|
|
2998
|
+
additionalAmountA: params.additionalAmountA,
|
|
2999
|
+
additionalAmountB: params.additionalAmountB,
|
|
3000
|
+
nonce,
|
|
3001
|
+
});
|
|
3002
|
+
// Sign intent
|
|
3003
|
+
const messageHash = sha256__default.default(intentMessage);
|
|
3004
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
3005
|
+
const request = {
|
|
3006
|
+
poolId: params.poolId,
|
|
3007
|
+
oldTickLower: params.oldTickLower,
|
|
3008
|
+
oldTickUpper: params.oldTickUpper,
|
|
3009
|
+
newTickLower: params.newTickLower,
|
|
3010
|
+
newTickUpper: params.newTickUpper,
|
|
3011
|
+
liquidityToMove: params.liquidityToMove,
|
|
3012
|
+
assetASparkTransferId: assetATransferId,
|
|
3013
|
+
assetBSparkTransferId: assetBTransferId,
|
|
3014
|
+
additionalAmountA: params.additionalAmountA,
|
|
3015
|
+
additionalAmountB: params.additionalAmountB,
|
|
3016
|
+
retainInBalance: params.retainInBalance,
|
|
3017
|
+
nonce,
|
|
3018
|
+
signature: hex.getHexFromUint8Array(signature),
|
|
3019
|
+
};
|
|
3020
|
+
const response = await this.typedApi.rebalancePosition(request);
|
|
3021
|
+
if (!response.accepted) {
|
|
3022
|
+
const errorMessage = response.error || "Rebalance position rejected by the AMM";
|
|
3023
|
+
throw new errors.FlashnetError(errorMessage, {
|
|
3024
|
+
response: {
|
|
3025
|
+
errorCode: "UNKNOWN",
|
|
3026
|
+
errorCategory: "System",
|
|
3027
|
+
message: errorMessage,
|
|
3028
|
+
requestId: response.requestId || "",
|
|
3029
|
+
timestamp: new Date().toISOString(),
|
|
3030
|
+
service: "amm-gateway",
|
|
3031
|
+
severity: "Error",
|
|
3032
|
+
},
|
|
3033
|
+
httpStatus: 400,
|
|
3034
|
+
transferIds,
|
|
3035
|
+
lpIdentityPublicKey: params.poolId,
|
|
3036
|
+
});
|
|
3037
|
+
}
|
|
3038
|
+
return response;
|
|
3039
|
+
};
|
|
3040
|
+
// Use auto-clawback if we made transfers
|
|
3041
|
+
if (transferIds.length > 0) {
|
|
3042
|
+
return this.executeWithAutoClawback(executeRebalance, transferIds, params.poolId);
|
|
3043
|
+
}
|
|
3044
|
+
return executeRebalance();
|
|
3045
|
+
}
|
|
3046
|
+
/**
|
|
3047
|
+
* List V3 concentrated liquidity positions
|
|
3048
|
+
*
|
|
3049
|
+
* @param query Optional query parameters
|
|
3050
|
+
* @param query.poolId - Filter by pool ID
|
|
3051
|
+
* @param query.page - Page number (default: 1)
|
|
3052
|
+
* @param query.pageSize - Page size (default: 20, max: 100)
|
|
3053
|
+
*/
|
|
3054
|
+
async listConcentratedPositions(query) {
|
|
3055
|
+
await this.ensureInitialized();
|
|
3056
|
+
return this.typedApi.listConcentratedPositions(query);
|
|
3057
|
+
}
|
|
3058
|
+
/**
|
|
3059
|
+
* Get pool liquidity distribution for visualization
|
|
3060
|
+
*
|
|
3061
|
+
* Returns aggregated liquidity ranges for visualizing the liquidity distribution.
|
|
3062
|
+
*
|
|
3063
|
+
* @param poolId - Pool ID (LP identity public key)
|
|
3064
|
+
*/
|
|
3065
|
+
async getPoolLiquidity(poolId) {
|
|
3066
|
+
await this.ensureInitialized();
|
|
3067
|
+
return this.typedApi.getPoolLiquidity(poolId);
|
|
3068
|
+
}
|
|
3069
|
+
/**
|
|
3070
|
+
* Get pool ticks for simulation
|
|
3071
|
+
*
|
|
3072
|
+
* Returns all initialized ticks with their liquidity deltas for swap simulation.
|
|
3073
|
+
*
|
|
3074
|
+
* @param poolId - Pool ID (LP identity public key)
|
|
3075
|
+
*/
|
|
3076
|
+
async getPoolTicks(poolId) {
|
|
3077
|
+
await this.ensureInitialized();
|
|
3078
|
+
return this.typedApi.getPoolTicks(poolId);
|
|
3079
|
+
}
|
|
3080
|
+
// V3 Free Balance Methods
|
|
3081
|
+
/**
|
|
3082
|
+
* Get user's free balance for a specific V3 pool
|
|
3083
|
+
*
|
|
3084
|
+
* Returns the user's current free balance in the pool, which can be used for
|
|
3085
|
+
* liquidity operations without needing to transfer from the wallet.
|
|
3086
|
+
*
|
|
3087
|
+
* @param poolId - Pool ID (LP identity public key)
|
|
3088
|
+
*/
|
|
3089
|
+
async getConcentratedBalance(poolId) {
|
|
3090
|
+
await this.ensureInitialized();
|
|
3091
|
+
return this.typedApi.getConcentratedBalance(poolId);
|
|
3092
|
+
}
|
|
3093
|
+
/**
|
|
3094
|
+
* Get user's free balances across all V3 pools
|
|
3095
|
+
*
|
|
3096
|
+
* Returns all free balances for the authenticated user across all V3 pools.
|
|
3097
|
+
*/
|
|
3098
|
+
async getConcentratedBalances() {
|
|
3099
|
+
await this.ensureInitialized();
|
|
3100
|
+
return this.typedApi.getConcentratedBalances();
|
|
3101
|
+
}
|
|
3102
|
+
/**
|
|
3103
|
+
* Withdraw free balance from a V3 pool to user's Spark wallet
|
|
3104
|
+
*
|
|
3105
|
+
* Withdraws accumulated free balance from a pool. Use "0" to skip an asset,
|
|
3106
|
+
* or "max" to withdraw all available balance of that asset.
|
|
3107
|
+
*
|
|
3108
|
+
* @param params Withdrawal parameters
|
|
3109
|
+
* @param params.poolId - Pool ID (LP identity public key)
|
|
3110
|
+
* @param params.amountA - Amount of asset A to withdraw ("0" to skip, "max" to withdraw all)
|
|
3111
|
+
* @param params.amountB - Amount of asset B to withdraw ("0" to skip, "max" to withdraw all)
|
|
3112
|
+
*/
|
|
3113
|
+
async withdrawConcentratedBalance(params) {
|
|
3114
|
+
await this.ensureInitialized();
|
|
3115
|
+
// Generate intent
|
|
3116
|
+
const nonce = index$2.generateNonce();
|
|
3117
|
+
const intentMessage = intents.generateWithdrawBalanceIntentMessage({
|
|
3118
|
+
userPublicKey: this.publicKey,
|
|
3119
|
+
lpIdentityPublicKey: params.poolId,
|
|
3120
|
+
amountA: params.amountA,
|
|
3121
|
+
amountB: params.amountB,
|
|
3122
|
+
nonce,
|
|
3123
|
+
});
|
|
3124
|
+
// Sign intent
|
|
3125
|
+
const messageHash = sha256__default.default(intentMessage);
|
|
3126
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
3127
|
+
const request = {
|
|
3128
|
+
poolId: params.poolId,
|
|
3129
|
+
amountA: params.amountA,
|
|
3130
|
+
amountB: params.amountB,
|
|
3131
|
+
nonce,
|
|
3132
|
+
signature: hex.getHexFromUint8Array(signature),
|
|
3133
|
+
};
|
|
3134
|
+
const response = await this.typedApi.withdrawConcentratedBalance(request);
|
|
3135
|
+
if (!response.accepted) {
|
|
3136
|
+
const errorMessage = response.error || "Withdraw balance rejected by the AMM";
|
|
3137
|
+
throw new Error(errorMessage);
|
|
3138
|
+
}
|
|
3139
|
+
return response;
|
|
3140
|
+
}
|
|
2564
3141
|
}
|
|
2565
3142
|
|
|
2566
3143
|
exports.FlashnetClient = FlashnetClient;
|