@flashnet/sdk 0.4.4 → 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 +181 -1
- package/dist/cjs/src/client/FlashnetClient.d.ts.map +1 -1
- package/dist/cjs/src/client/FlashnetClient.js +478 -14
- 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 +181 -1
- package/dist/esm/src/client/FlashnetClient.d.ts.map +1 -1
- package/dist/esm/src/client/FlashnetClient.js +479 -15
- 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
|
@@ -6,7 +6,7 @@ import { getSparkNetworkFromLegacy, getClientEnvironmentFromLegacy, Network } fr
|
|
|
6
6
|
import { generateNonce, compareDecimalStrings } from '../utils/index.js';
|
|
7
7
|
import { AuthManager } from '../utils/auth.js';
|
|
8
8
|
import { getHexFromUint8Array } from '../utils/hex.js';
|
|
9
|
-
import { generateConstantProductPoolInitializationIntentMessage, generatePoolInitializationIntentMessage, generatePoolConfirmInitialDepositIntentMessage, generatePoolSwapIntentMessage, generateRouteSwapIntentMessage, generateAddLiquidityIntentMessage, generateRemoveLiquidityIntentMessage, generateRegisterHostIntentMessage, generateWithdrawHostFeesIntentMessage, generateWithdrawIntegratorFeesIntentMessage, generateCreateEscrowIntentMessage, generateFundEscrowIntentMessage, generateClaimEscrowIntentMessage, generateClawbackIntentMessage } from '../utils/intents.js';
|
|
9
|
+
import { generateConstantProductPoolInitializationIntentMessage, generatePoolInitializationIntentMessage, generatePoolConfirmInitialDepositIntentMessage, generatePoolSwapIntentMessage, generateRouteSwapIntentMessage, generateAddLiquidityIntentMessage, generateRemoveLiquidityIntentMessage, generateRegisterHostIntentMessage, generateWithdrawHostFeesIntentMessage, generateWithdrawIntegratorFeesIntentMessage, generateCreateEscrowIntentMessage, generateFundEscrowIntentMessage, generateClaimEscrowIntentMessage, generateClawbackIntentMessage, generateCreateConcentratedPoolIntentMessage, generateDecreaseLiquidityIntentMessage, generateCollectFeesIntentMessage, generateWithdrawBalanceIntentMessage, generateIncreaseLiquidityIntentMessage, generateRebalancePositionIntentMessage } from '../utils/intents.js';
|
|
10
10
|
import { getSparkNetworkFromAddress, encodeSparkAddressNew } from '../utils/spark-address.js';
|
|
11
11
|
import { encodeSparkHumanReadableTokenIdentifier, decodeSparkHumanReadableTokenIdentifier } from '../utils/tokenAddress.js';
|
|
12
12
|
import { FlashnetError } from '../types/errors.js';
|
|
@@ -299,7 +299,7 @@ class FlashnetClient {
|
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
|
-
//
|
|
302
|
+
// Pool Operations
|
|
303
303
|
/**
|
|
304
304
|
* List pools with optional filters
|
|
305
305
|
*/
|
|
@@ -562,7 +562,7 @@ class FlashnetClient {
|
|
|
562
562
|
};
|
|
563
563
|
return this.typedApi.confirmInitialDeposit(request);
|
|
564
564
|
}
|
|
565
|
-
//
|
|
565
|
+
// Swap Operations
|
|
566
566
|
/**
|
|
567
567
|
* Simulate a swap without executing it
|
|
568
568
|
*/
|
|
@@ -811,7 +811,7 @@ class FlashnetClient {
|
|
|
811
811
|
return response;
|
|
812
812
|
}, [initialTransferId], firstPoolId);
|
|
813
813
|
}
|
|
814
|
-
//
|
|
814
|
+
// Liquidity Operations
|
|
815
815
|
/**
|
|
816
816
|
* Simulate adding liquidity
|
|
817
817
|
*/
|
|
@@ -962,7 +962,7 @@ class FlashnetClient {
|
|
|
962
962
|
}
|
|
963
963
|
return response;
|
|
964
964
|
}
|
|
965
|
-
//
|
|
965
|
+
// Host Operations
|
|
966
966
|
/**
|
|
967
967
|
* Register as a host
|
|
968
968
|
*/
|
|
@@ -1108,7 +1108,7 @@ class FlashnetClient {
|
|
|
1108
1108
|
await this.ensureInitialized();
|
|
1109
1109
|
return this.typedApi.getIntegratorFees();
|
|
1110
1110
|
}
|
|
1111
|
-
//
|
|
1111
|
+
// Escrow Operations
|
|
1112
1112
|
/**
|
|
1113
1113
|
* Creates a new escrow contract.
|
|
1114
1114
|
* This is the first step in a two-step process: create, then fund.
|
|
@@ -1247,7 +1247,7 @@ class FlashnetClient {
|
|
|
1247
1247
|
await this.ensureInitialized();
|
|
1248
1248
|
return this.typedApi.getEscrow(escrowId);
|
|
1249
1249
|
}
|
|
1250
|
-
//
|
|
1250
|
+
// Swap History
|
|
1251
1251
|
/**
|
|
1252
1252
|
* Get swaps for a specific pool
|
|
1253
1253
|
*/
|
|
@@ -1270,7 +1270,7 @@ class FlashnetClient {
|
|
|
1270
1270
|
const user = userPublicKey || this.publicKey;
|
|
1271
1271
|
return this.typedApi.getUserSwaps(user, query);
|
|
1272
1272
|
}
|
|
1273
|
-
//
|
|
1273
|
+
// Clawback
|
|
1274
1274
|
/**
|
|
1275
1275
|
* Request clawback of a stuck inbound transfer to an LP wallet
|
|
1276
1276
|
*/
|
|
@@ -1455,7 +1455,7 @@ class FlashnetClient {
|
|
|
1455
1455
|
throw flashnetError;
|
|
1456
1456
|
}
|
|
1457
1457
|
}
|
|
1458
|
-
//
|
|
1458
|
+
// Clawback Monitor
|
|
1459
1459
|
/**
|
|
1460
1460
|
* Start a background job that periodically polls for clawbackable transfers
|
|
1461
1461
|
* and automatically claws them back.
|
|
@@ -1589,7 +1589,7 @@ class FlashnetClient {
|
|
|
1589
1589
|
},
|
|
1590
1590
|
};
|
|
1591
1591
|
}
|
|
1592
|
-
//
|
|
1592
|
+
// Token Address Operations
|
|
1593
1593
|
/**
|
|
1594
1594
|
* Encode a token identifier into a human-readable token address using the client's Spark network
|
|
1595
1595
|
* @param tokenIdentifier - Token identifier as hex string or Uint8Array
|
|
@@ -1624,8 +1624,8 @@ class FlashnetClient {
|
|
|
1624
1624
|
decodeLegacyTokenAddress(address) {
|
|
1625
1625
|
return decodeSparkHumanReadableTokenIdentifier(address, this.sparkNetwork);
|
|
1626
1626
|
}
|
|
1627
|
-
//
|
|
1628
|
-
//
|
|
1627
|
+
// Status
|
|
1628
|
+
// Config Inspection
|
|
1629
1629
|
/**
|
|
1630
1630
|
* Get raw feature status list (cached briefly)
|
|
1631
1631
|
*/
|
|
@@ -1686,7 +1686,7 @@ class FlashnetClient {
|
|
|
1686
1686
|
await this.ensureInitialized();
|
|
1687
1687
|
return this.typedApi.ping();
|
|
1688
1688
|
}
|
|
1689
|
-
//
|
|
1689
|
+
// Helper Methods
|
|
1690
1690
|
/**
|
|
1691
1691
|
* Performs asset transfer using generalized asset address for both BTC and tokens.
|
|
1692
1692
|
*/
|
|
@@ -1786,7 +1786,7 @@ class FlashnetClient {
|
|
|
1786
1786
|
throw new Error(errorMessage);
|
|
1787
1787
|
}
|
|
1788
1788
|
}
|
|
1789
|
-
//
|
|
1789
|
+
// Lightning Payment with Token
|
|
1790
1790
|
/**
|
|
1791
1791
|
* Get a quote for paying a Lightning invoice with a token.
|
|
1792
1792
|
* This calculates the optimal pool and token amount needed.
|
|
@@ -2488,7 +2488,7 @@ class FlashnetClient {
|
|
|
2488
2488
|
async cleanup() {
|
|
2489
2489
|
await this._wallet.cleanupConnections();
|
|
2490
2490
|
}
|
|
2491
|
-
//
|
|
2491
|
+
// Config and Policy Enforcement Helpers
|
|
2492
2492
|
async ensureAmmOperationAllowed(requiredFeature) {
|
|
2493
2493
|
await this.ensurePingOk();
|
|
2494
2494
|
const featureMap = await this.getFeatureStatusMap();
|
|
@@ -2668,6 +2668,470 @@ ${relaxed.toString()} (50% relaxed), provided minAmountOut ${minAmountOut.toStri
|
|
|
2668
2668
|
throw new Error(`Asset B is not allowed for pool creation: ${assetBHex}`);
|
|
2669
2669
|
}
|
|
2670
2670
|
}
|
|
2671
|
+
// V3 Concentrated Liquidity Operations
|
|
2672
|
+
/**
|
|
2673
|
+
* Create a V3 concentrated liquidity pool
|
|
2674
|
+
*
|
|
2675
|
+
* Concentrated liquidity pools allow LPs to provide liquidity within specific
|
|
2676
|
+
* price ranges (tick ranges) for higher capital efficiency.
|
|
2677
|
+
*
|
|
2678
|
+
* @param params Pool creation parameters
|
|
2679
|
+
* @param params.assetAAddress - Address of asset A (base asset)
|
|
2680
|
+
* @param params.assetBAddress - Address of asset B (quote asset)
|
|
2681
|
+
* @param params.tickSpacing - Tick spacing (common values: 10, 60, 200)
|
|
2682
|
+
* @param params.initialPrice - Initial price of asset A in terms of asset B
|
|
2683
|
+
* @param params.lpFeeRateBps - LP fee rate in basis points
|
|
2684
|
+
* @param params.hostFeeRateBps - Host fee rate in basis points
|
|
2685
|
+
* @param params.hostNamespace - Optional host namespace
|
|
2686
|
+
* @param params.poolOwnerPublicKey - Optional pool owner (defaults to wallet pubkey)
|
|
2687
|
+
*/
|
|
2688
|
+
async createConcentratedPool(params) {
|
|
2689
|
+
await this.ensureInitialized();
|
|
2690
|
+
await this.ensureAmmOperationAllowed("allow_pool_creation");
|
|
2691
|
+
await this.assertAllowedAssetBForPoolCreation(this.toHexTokenIdentifier(params.assetBAddress));
|
|
2692
|
+
const poolOwnerPublicKey = params.poolOwnerPublicKey ?? this.publicKey;
|
|
2693
|
+
// Generate intent
|
|
2694
|
+
const nonce = generateNonce();
|
|
2695
|
+
const intentMessage = generateCreateConcentratedPoolIntentMessage({
|
|
2696
|
+
poolOwnerPublicKey,
|
|
2697
|
+
assetAAddress: this.toHexTokenIdentifier(params.assetAAddress),
|
|
2698
|
+
assetBAddress: this.toHexTokenIdentifier(params.assetBAddress),
|
|
2699
|
+
tickSpacing: params.tickSpacing,
|
|
2700
|
+
initialPrice: params.initialPrice,
|
|
2701
|
+
lpFeeRateBps: params.lpFeeRateBps.toString(),
|
|
2702
|
+
hostFeeRateBps: params.hostFeeRateBps.toString(),
|
|
2703
|
+
nonce,
|
|
2704
|
+
});
|
|
2705
|
+
// Sign intent
|
|
2706
|
+
const messageHash = sha256(intentMessage);
|
|
2707
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
2708
|
+
const request = {
|
|
2709
|
+
poolOwnerPublicKey,
|
|
2710
|
+
assetAAddress: this.toHexTokenIdentifier(params.assetAAddress),
|
|
2711
|
+
assetBAddress: this.toHexTokenIdentifier(params.assetBAddress),
|
|
2712
|
+
tickSpacing: params.tickSpacing,
|
|
2713
|
+
initialPrice: params.initialPrice,
|
|
2714
|
+
lpFeeRateBps: params.lpFeeRateBps.toString(),
|
|
2715
|
+
hostFeeRateBps: params.hostFeeRateBps.toString(),
|
|
2716
|
+
hostNamespace: params.hostNamespace,
|
|
2717
|
+
nonce,
|
|
2718
|
+
signature: getHexFromUint8Array(signature),
|
|
2719
|
+
};
|
|
2720
|
+
return this.typedApi.createConcentratedPool(request);
|
|
2721
|
+
}
|
|
2722
|
+
/**
|
|
2723
|
+
* Add liquidity to a V3 concentrated position
|
|
2724
|
+
*
|
|
2725
|
+
* Increases liquidity within a specific tick range. If the position doesn't exist,
|
|
2726
|
+
* a new position is created.
|
|
2727
|
+
*
|
|
2728
|
+
* @param params Position parameters
|
|
2729
|
+
* @param params.poolId - Pool ID (LP identity public key)
|
|
2730
|
+
* @param params.tickLower - Lower tick of the position
|
|
2731
|
+
* @param params.tickUpper - Upper tick of the position
|
|
2732
|
+
* @param params.amountADesired - Desired amount of asset A to add
|
|
2733
|
+
* @param params.amountBDesired - Desired amount of asset B to add
|
|
2734
|
+
* @param params.amountAMin - Minimum amount of asset A (slippage protection)
|
|
2735
|
+
* @param params.amountBMin - Minimum amount of asset B (slippage protection)
|
|
2736
|
+
* @param params.useFreeBalanceA - If true, use free balance from pool for asset A instead of Spark transfer
|
|
2737
|
+
* @param params.useFreeBalanceB - If true, use free balance from pool for asset B instead of Spark transfer
|
|
2738
|
+
* @param params.retainExcessInBalance - If true, retain any excess amounts in pool free balance instead of refunding via Spark
|
|
2739
|
+
*/
|
|
2740
|
+
async increaseLiquidity(params) {
|
|
2741
|
+
await this.ensureInitialized();
|
|
2742
|
+
await this.ensureAmmOperationAllowed("allow_add_liquidity");
|
|
2743
|
+
// Get pool details to know asset addresses
|
|
2744
|
+
const pool = await this.getPool(params.poolId);
|
|
2745
|
+
// Transfer assets to pool (unless using free balance)
|
|
2746
|
+
const lpSparkAddress = encodeSparkAddressNew({
|
|
2747
|
+
identityPublicKey: params.poolId,
|
|
2748
|
+
network: this.sparkNetwork,
|
|
2749
|
+
});
|
|
2750
|
+
let assetATransferId = "";
|
|
2751
|
+
let assetBTransferId = "";
|
|
2752
|
+
const transferIds = [];
|
|
2753
|
+
// Transfer asset A if not using free balance
|
|
2754
|
+
if (!params.useFreeBalanceA && BigInt(params.amountADesired) > 0n) {
|
|
2755
|
+
assetATransferId = await this.transferAsset({
|
|
2756
|
+
receiverSparkAddress: lpSparkAddress,
|
|
2757
|
+
assetAddress: pool.assetAAddress,
|
|
2758
|
+
amount: params.amountADesired,
|
|
2759
|
+
}, "Insufficient balance for adding V3 liquidity (Asset A): ");
|
|
2760
|
+
transferIds.push(assetATransferId);
|
|
2761
|
+
}
|
|
2762
|
+
// Transfer asset B if not using free balance
|
|
2763
|
+
if (!params.useFreeBalanceB && BigInt(params.amountBDesired) > 0n) {
|
|
2764
|
+
assetBTransferId = await this.transferAsset({
|
|
2765
|
+
receiverSparkAddress: lpSparkAddress,
|
|
2766
|
+
assetAddress: pool.assetBAddress,
|
|
2767
|
+
amount: params.amountBDesired,
|
|
2768
|
+
}, "Insufficient balance for adding V3 liquidity (Asset B): ");
|
|
2769
|
+
transferIds.push(assetBTransferId);
|
|
2770
|
+
}
|
|
2771
|
+
const executeIncrease = async () => {
|
|
2772
|
+
// Generate intent
|
|
2773
|
+
const nonce = generateNonce();
|
|
2774
|
+
const intentMessage = generateIncreaseLiquidityIntentMessage({
|
|
2775
|
+
userPublicKey: this.publicKey,
|
|
2776
|
+
lpIdentityPublicKey: params.poolId,
|
|
2777
|
+
tickLower: params.tickLower,
|
|
2778
|
+
tickUpper: params.tickUpper,
|
|
2779
|
+
assetASparkTransferId: assetATransferId,
|
|
2780
|
+
assetBSparkTransferId: assetBTransferId,
|
|
2781
|
+
amountADesired: params.amountADesired,
|
|
2782
|
+
amountBDesired: params.amountBDesired,
|
|
2783
|
+
amountAMin: params.amountAMin,
|
|
2784
|
+
amountBMin: params.amountBMin,
|
|
2785
|
+
nonce,
|
|
2786
|
+
});
|
|
2787
|
+
// Sign intent
|
|
2788
|
+
const messageHash = sha256(intentMessage);
|
|
2789
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
2790
|
+
const request = {
|
|
2791
|
+
poolId: params.poolId,
|
|
2792
|
+
tickLower: params.tickLower,
|
|
2793
|
+
tickUpper: params.tickUpper,
|
|
2794
|
+
assetASparkTransferId: assetATransferId,
|
|
2795
|
+
assetBSparkTransferId: assetBTransferId,
|
|
2796
|
+
amountADesired: params.amountADesired,
|
|
2797
|
+
amountBDesired: params.amountBDesired,
|
|
2798
|
+
amountAMin: params.amountAMin,
|
|
2799
|
+
amountBMin: params.amountBMin,
|
|
2800
|
+
useFreeBalanceA: params.useFreeBalanceA,
|
|
2801
|
+
useFreeBalanceB: params.useFreeBalanceB,
|
|
2802
|
+
retainExcessInBalance: params.retainExcessInBalance,
|
|
2803
|
+
nonce,
|
|
2804
|
+
signature: getHexFromUint8Array(signature),
|
|
2805
|
+
};
|
|
2806
|
+
const response = await this.typedApi.increaseLiquidity(request);
|
|
2807
|
+
if (!response.accepted) {
|
|
2808
|
+
const errorMessage = response.error || "Increase liquidity rejected by the AMM";
|
|
2809
|
+
const hasRefund = !!(response.amountARefund || response.amountBRefund);
|
|
2810
|
+
const refundInfo = hasRefund
|
|
2811
|
+
? ` Refunds: Asset A: ${response.amountARefund || "0"}, Asset B: ${response.amountBRefund || "0"}`
|
|
2812
|
+
: "";
|
|
2813
|
+
throw new FlashnetError(`${errorMessage}.${refundInfo}`, {
|
|
2814
|
+
response: {
|
|
2815
|
+
errorCode: hasRefund ? "FSAG-4203" : "UNKNOWN",
|
|
2816
|
+
errorCategory: hasRefund ? "Business" : "System",
|
|
2817
|
+
message: `${errorMessage}.${refundInfo}`,
|
|
2818
|
+
requestId: response.requestId || "",
|
|
2819
|
+
timestamp: new Date().toISOString(),
|
|
2820
|
+
service: "amm-gateway",
|
|
2821
|
+
severity: "Error",
|
|
2822
|
+
},
|
|
2823
|
+
httpStatus: 400,
|
|
2824
|
+
transferIds: hasRefund ? [] : transferIds,
|
|
2825
|
+
lpIdentityPublicKey: params.poolId,
|
|
2826
|
+
});
|
|
2827
|
+
}
|
|
2828
|
+
return response;
|
|
2829
|
+
};
|
|
2830
|
+
// Execute with auto-clawback if we made transfers
|
|
2831
|
+
if (transferIds.length > 0) {
|
|
2832
|
+
return this.executeWithAutoClawback(executeIncrease, transferIds, params.poolId);
|
|
2833
|
+
}
|
|
2834
|
+
return executeIncrease();
|
|
2835
|
+
}
|
|
2836
|
+
/**
|
|
2837
|
+
* Remove liquidity from a V3 concentrated position
|
|
2838
|
+
*
|
|
2839
|
+
* Decreases liquidity from a specific tick range position.
|
|
2840
|
+
*
|
|
2841
|
+
* @param params Position parameters
|
|
2842
|
+
* @param params.poolId - Pool ID (LP identity public key)
|
|
2843
|
+
* @param params.tickLower - Lower tick of the position
|
|
2844
|
+
* @param params.tickUpper - Upper tick of the position
|
|
2845
|
+
* @param params.liquidityToRemove - Amount of liquidity to remove (use "0" to remove all)
|
|
2846
|
+
* @param params.amountAMin - Minimum amount of asset A to receive (slippage protection)
|
|
2847
|
+
* @param params.amountBMin - Minimum amount of asset B to receive (slippage protection)
|
|
2848
|
+
* @param params.retainInBalance - If true, retain withdrawn assets in pool free balance instead of sending via Spark
|
|
2849
|
+
*/
|
|
2850
|
+
async decreaseLiquidity(params) {
|
|
2851
|
+
await this.ensureInitialized();
|
|
2852
|
+
await this.ensureAmmOperationAllowed("allow_withdraw_liquidity");
|
|
2853
|
+
// Generate intent
|
|
2854
|
+
const nonce = generateNonce();
|
|
2855
|
+
const intentMessage = generateDecreaseLiquidityIntentMessage({
|
|
2856
|
+
userPublicKey: this.publicKey,
|
|
2857
|
+
lpIdentityPublicKey: params.poolId,
|
|
2858
|
+
tickLower: params.tickLower,
|
|
2859
|
+
tickUpper: params.tickUpper,
|
|
2860
|
+
liquidityToRemove: params.liquidityToRemove,
|
|
2861
|
+
amountAMin: params.amountAMin,
|
|
2862
|
+
amountBMin: params.amountBMin,
|
|
2863
|
+
nonce,
|
|
2864
|
+
});
|
|
2865
|
+
// Sign intent
|
|
2866
|
+
const messageHash = sha256(intentMessage);
|
|
2867
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
2868
|
+
const request = {
|
|
2869
|
+
poolId: params.poolId,
|
|
2870
|
+
tickLower: params.tickLower,
|
|
2871
|
+
tickUpper: params.tickUpper,
|
|
2872
|
+
liquidityToRemove: params.liquidityToRemove,
|
|
2873
|
+
amountAMin: params.amountAMin,
|
|
2874
|
+
amountBMin: params.amountBMin,
|
|
2875
|
+
retainInBalance: params.retainInBalance,
|
|
2876
|
+
nonce,
|
|
2877
|
+
signature: getHexFromUint8Array(signature),
|
|
2878
|
+
};
|
|
2879
|
+
const response = await this.typedApi.decreaseLiquidity(request);
|
|
2880
|
+
if (!response.accepted) {
|
|
2881
|
+
const errorMessage = response.error || "Decrease liquidity rejected by the AMM";
|
|
2882
|
+
throw new Error(errorMessage);
|
|
2883
|
+
}
|
|
2884
|
+
return response;
|
|
2885
|
+
}
|
|
2886
|
+
/**
|
|
2887
|
+
* Collect accumulated fees from a V3 position
|
|
2888
|
+
*
|
|
2889
|
+
* Collects fees earned from trading activity without removing liquidity.
|
|
2890
|
+
*
|
|
2891
|
+
* @param params Position parameters
|
|
2892
|
+
* @param params.poolId - Pool ID (LP identity public key)
|
|
2893
|
+
* @param params.tickLower - Lower tick of the position
|
|
2894
|
+
* @param params.tickUpper - Upper tick of the position
|
|
2895
|
+
* @param params.retainInBalance - If true, retain collected fees in pool free balance instead of sending via Spark
|
|
2896
|
+
*/
|
|
2897
|
+
async collectFees(params) {
|
|
2898
|
+
await this.ensureInitialized();
|
|
2899
|
+
await this.ensureAmmOperationAllowed("allow_withdraw_fees");
|
|
2900
|
+
// Generate intent
|
|
2901
|
+
const nonce = generateNonce();
|
|
2902
|
+
const intentMessage = generateCollectFeesIntentMessage({
|
|
2903
|
+
userPublicKey: this.publicKey,
|
|
2904
|
+
lpIdentityPublicKey: params.poolId,
|
|
2905
|
+
tickLower: params.tickLower,
|
|
2906
|
+
tickUpper: params.tickUpper,
|
|
2907
|
+
nonce,
|
|
2908
|
+
});
|
|
2909
|
+
// Sign intent
|
|
2910
|
+
const messageHash = sha256(intentMessage);
|
|
2911
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
2912
|
+
const request = {
|
|
2913
|
+
poolId: params.poolId,
|
|
2914
|
+
tickLower: params.tickLower,
|
|
2915
|
+
tickUpper: params.tickUpper,
|
|
2916
|
+
retainInBalance: params.retainInBalance,
|
|
2917
|
+
nonce,
|
|
2918
|
+
signature: getHexFromUint8Array(signature),
|
|
2919
|
+
};
|
|
2920
|
+
const response = await this.typedApi.collectFees(request);
|
|
2921
|
+
if (!response.accepted) {
|
|
2922
|
+
const errorMessage = response.error || "Collect fees rejected by the AMM";
|
|
2923
|
+
throw new Error(errorMessage);
|
|
2924
|
+
}
|
|
2925
|
+
return response;
|
|
2926
|
+
}
|
|
2927
|
+
/**
|
|
2928
|
+
* Rebalance a V3 position to a new tick range
|
|
2929
|
+
*
|
|
2930
|
+
* Atomically moves liquidity from an old position to a new tick range.
|
|
2931
|
+
* Optionally can add additional funds during rebalancing.
|
|
2932
|
+
*
|
|
2933
|
+
* @param params Rebalance parameters
|
|
2934
|
+
* @param params.poolId - Pool ID (LP identity public key)
|
|
2935
|
+
* @param params.oldTickLower - Lower tick of the current position
|
|
2936
|
+
* @param params.oldTickUpper - Upper tick of the current position
|
|
2937
|
+
* @param params.newTickLower - Lower tick for the new position
|
|
2938
|
+
* @param params.newTickUpper - Upper tick for the new position
|
|
2939
|
+
* @param params.liquidityToMove - Amount of liquidity to move (use "0" to move all)
|
|
2940
|
+
* @param params.additionalAmountA - Optional additional asset A to add
|
|
2941
|
+
* @param params.additionalAmountB - Optional additional asset B to add
|
|
2942
|
+
* @param params.retainInBalance - If true, retain any excess amounts in pool free balance instead of sending via Spark
|
|
2943
|
+
*/
|
|
2944
|
+
async rebalancePosition(params) {
|
|
2945
|
+
await this.ensureInitialized();
|
|
2946
|
+
await this.ensureAmmOperationAllowed("allow_add_liquidity");
|
|
2947
|
+
// Get pool details
|
|
2948
|
+
const pool = await this.getPool(params.poolId);
|
|
2949
|
+
// Transfer additional assets if provided
|
|
2950
|
+
let assetATransferId;
|
|
2951
|
+
let assetBTransferId;
|
|
2952
|
+
const lpSparkAddress = encodeSparkAddressNew({
|
|
2953
|
+
identityPublicKey: params.poolId,
|
|
2954
|
+
network: this.sparkNetwork,
|
|
2955
|
+
});
|
|
2956
|
+
if (params.additionalAmountA && BigInt(params.additionalAmountA) > 0n) {
|
|
2957
|
+
assetATransferId = await this.transferAsset({
|
|
2958
|
+
receiverSparkAddress: lpSparkAddress,
|
|
2959
|
+
assetAddress: pool.assetAAddress,
|
|
2960
|
+
amount: params.additionalAmountA,
|
|
2961
|
+
}, "Insufficient balance for rebalance (Asset A): ");
|
|
2962
|
+
}
|
|
2963
|
+
if (params.additionalAmountB && BigInt(params.additionalAmountB) > 0n) {
|
|
2964
|
+
assetBTransferId = await this.transferAsset({
|
|
2965
|
+
receiverSparkAddress: lpSparkAddress,
|
|
2966
|
+
assetAddress: pool.assetBAddress,
|
|
2967
|
+
amount: params.additionalAmountB,
|
|
2968
|
+
}, "Insufficient balance for rebalance (Asset B): ");
|
|
2969
|
+
}
|
|
2970
|
+
// Collect transfer IDs for potential clawback
|
|
2971
|
+
const transferIds = [];
|
|
2972
|
+
if (assetATransferId) {
|
|
2973
|
+
transferIds.push(assetATransferId);
|
|
2974
|
+
}
|
|
2975
|
+
if (assetBTransferId) {
|
|
2976
|
+
transferIds.push(assetBTransferId);
|
|
2977
|
+
}
|
|
2978
|
+
// Execute (with auto-clawback if we have transfers)
|
|
2979
|
+
const executeRebalance = async () => {
|
|
2980
|
+
// Generate intent
|
|
2981
|
+
const nonce = generateNonce();
|
|
2982
|
+
const intentMessage = generateRebalancePositionIntentMessage({
|
|
2983
|
+
userPublicKey: this.publicKey,
|
|
2984
|
+
lpIdentityPublicKey: params.poolId,
|
|
2985
|
+
oldTickLower: params.oldTickLower,
|
|
2986
|
+
oldTickUpper: params.oldTickUpper,
|
|
2987
|
+
newTickLower: params.newTickLower,
|
|
2988
|
+
newTickUpper: params.newTickUpper,
|
|
2989
|
+
liquidityToMove: params.liquidityToMove,
|
|
2990
|
+
assetASparkTransferId: assetATransferId,
|
|
2991
|
+
assetBSparkTransferId: assetBTransferId,
|
|
2992
|
+
additionalAmountA: params.additionalAmountA,
|
|
2993
|
+
additionalAmountB: params.additionalAmountB,
|
|
2994
|
+
nonce,
|
|
2995
|
+
});
|
|
2996
|
+
// Sign intent
|
|
2997
|
+
const messageHash = sha256(intentMessage);
|
|
2998
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
2999
|
+
const request = {
|
|
3000
|
+
poolId: params.poolId,
|
|
3001
|
+
oldTickLower: params.oldTickLower,
|
|
3002
|
+
oldTickUpper: params.oldTickUpper,
|
|
3003
|
+
newTickLower: params.newTickLower,
|
|
3004
|
+
newTickUpper: params.newTickUpper,
|
|
3005
|
+
liquidityToMove: params.liquidityToMove,
|
|
3006
|
+
assetASparkTransferId: assetATransferId,
|
|
3007
|
+
assetBSparkTransferId: assetBTransferId,
|
|
3008
|
+
additionalAmountA: params.additionalAmountA,
|
|
3009
|
+
additionalAmountB: params.additionalAmountB,
|
|
3010
|
+
retainInBalance: params.retainInBalance,
|
|
3011
|
+
nonce,
|
|
3012
|
+
signature: getHexFromUint8Array(signature),
|
|
3013
|
+
};
|
|
3014
|
+
const response = await this.typedApi.rebalancePosition(request);
|
|
3015
|
+
if (!response.accepted) {
|
|
3016
|
+
const errorMessage = response.error || "Rebalance position rejected by the AMM";
|
|
3017
|
+
throw new FlashnetError(errorMessage, {
|
|
3018
|
+
response: {
|
|
3019
|
+
errorCode: "UNKNOWN",
|
|
3020
|
+
errorCategory: "System",
|
|
3021
|
+
message: errorMessage,
|
|
3022
|
+
requestId: response.requestId || "",
|
|
3023
|
+
timestamp: new Date().toISOString(),
|
|
3024
|
+
service: "amm-gateway",
|
|
3025
|
+
severity: "Error",
|
|
3026
|
+
},
|
|
3027
|
+
httpStatus: 400,
|
|
3028
|
+
transferIds,
|
|
3029
|
+
lpIdentityPublicKey: params.poolId,
|
|
3030
|
+
});
|
|
3031
|
+
}
|
|
3032
|
+
return response;
|
|
3033
|
+
};
|
|
3034
|
+
// Use auto-clawback if we made transfers
|
|
3035
|
+
if (transferIds.length > 0) {
|
|
3036
|
+
return this.executeWithAutoClawback(executeRebalance, transferIds, params.poolId);
|
|
3037
|
+
}
|
|
3038
|
+
return executeRebalance();
|
|
3039
|
+
}
|
|
3040
|
+
/**
|
|
3041
|
+
* List V3 concentrated liquidity positions
|
|
3042
|
+
*
|
|
3043
|
+
* @param query Optional query parameters
|
|
3044
|
+
* @param query.poolId - Filter by pool ID
|
|
3045
|
+
* @param query.page - Page number (default: 1)
|
|
3046
|
+
* @param query.pageSize - Page size (default: 20, max: 100)
|
|
3047
|
+
*/
|
|
3048
|
+
async listConcentratedPositions(query) {
|
|
3049
|
+
await this.ensureInitialized();
|
|
3050
|
+
return this.typedApi.listConcentratedPositions(query);
|
|
3051
|
+
}
|
|
3052
|
+
/**
|
|
3053
|
+
* Get pool liquidity distribution for visualization
|
|
3054
|
+
*
|
|
3055
|
+
* Returns aggregated liquidity ranges for visualizing the liquidity distribution.
|
|
3056
|
+
*
|
|
3057
|
+
* @param poolId - Pool ID (LP identity public key)
|
|
3058
|
+
*/
|
|
3059
|
+
async getPoolLiquidity(poolId) {
|
|
3060
|
+
await this.ensureInitialized();
|
|
3061
|
+
return this.typedApi.getPoolLiquidity(poolId);
|
|
3062
|
+
}
|
|
3063
|
+
/**
|
|
3064
|
+
* Get pool ticks for simulation
|
|
3065
|
+
*
|
|
3066
|
+
* Returns all initialized ticks with their liquidity deltas for swap simulation.
|
|
3067
|
+
*
|
|
3068
|
+
* @param poolId - Pool ID (LP identity public key)
|
|
3069
|
+
*/
|
|
3070
|
+
async getPoolTicks(poolId) {
|
|
3071
|
+
await this.ensureInitialized();
|
|
3072
|
+
return this.typedApi.getPoolTicks(poolId);
|
|
3073
|
+
}
|
|
3074
|
+
// V3 Free Balance Methods
|
|
3075
|
+
/**
|
|
3076
|
+
* Get user's free balance for a specific V3 pool
|
|
3077
|
+
*
|
|
3078
|
+
* Returns the user's current free balance in the pool, which can be used for
|
|
3079
|
+
* liquidity operations without needing to transfer from the wallet.
|
|
3080
|
+
*
|
|
3081
|
+
* @param poolId - Pool ID (LP identity public key)
|
|
3082
|
+
*/
|
|
3083
|
+
async getConcentratedBalance(poolId) {
|
|
3084
|
+
await this.ensureInitialized();
|
|
3085
|
+
return this.typedApi.getConcentratedBalance(poolId);
|
|
3086
|
+
}
|
|
3087
|
+
/**
|
|
3088
|
+
* Get user's free balances across all V3 pools
|
|
3089
|
+
*
|
|
3090
|
+
* Returns all free balances for the authenticated user across all V3 pools.
|
|
3091
|
+
*/
|
|
3092
|
+
async getConcentratedBalances() {
|
|
3093
|
+
await this.ensureInitialized();
|
|
3094
|
+
return this.typedApi.getConcentratedBalances();
|
|
3095
|
+
}
|
|
3096
|
+
/**
|
|
3097
|
+
* Withdraw free balance from a V3 pool to user's Spark wallet
|
|
3098
|
+
*
|
|
3099
|
+
* Withdraws accumulated free balance from a pool. Use "0" to skip an asset,
|
|
3100
|
+
* or "max" to withdraw all available balance of that asset.
|
|
3101
|
+
*
|
|
3102
|
+
* @param params Withdrawal parameters
|
|
3103
|
+
* @param params.poolId - Pool ID (LP identity public key)
|
|
3104
|
+
* @param params.amountA - Amount of asset A to withdraw ("0" to skip, "max" to withdraw all)
|
|
3105
|
+
* @param params.amountB - Amount of asset B to withdraw ("0" to skip, "max" to withdraw all)
|
|
3106
|
+
*/
|
|
3107
|
+
async withdrawConcentratedBalance(params) {
|
|
3108
|
+
await this.ensureInitialized();
|
|
3109
|
+
// Generate intent
|
|
3110
|
+
const nonce = generateNonce();
|
|
3111
|
+
const intentMessage = generateWithdrawBalanceIntentMessage({
|
|
3112
|
+
userPublicKey: this.publicKey,
|
|
3113
|
+
lpIdentityPublicKey: params.poolId,
|
|
3114
|
+
amountA: params.amountA,
|
|
3115
|
+
amountB: params.amountB,
|
|
3116
|
+
nonce,
|
|
3117
|
+
});
|
|
3118
|
+
// Sign intent
|
|
3119
|
+
const messageHash = sha256(intentMessage);
|
|
3120
|
+
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
3121
|
+
const request = {
|
|
3122
|
+
poolId: params.poolId,
|
|
3123
|
+
amountA: params.amountA,
|
|
3124
|
+
amountB: params.amountB,
|
|
3125
|
+
nonce,
|
|
3126
|
+
signature: getHexFromUint8Array(signature),
|
|
3127
|
+
};
|
|
3128
|
+
const response = await this.typedApi.withdrawConcentratedBalance(request);
|
|
3129
|
+
if (!response.accepted) {
|
|
3130
|
+
const errorMessage = response.error || "Withdraw balance rejected by the AMM";
|
|
3131
|
+
throw new Error(errorMessage);
|
|
3132
|
+
}
|
|
3133
|
+
return response;
|
|
3134
|
+
}
|
|
2671
3135
|
}
|
|
2672
3136
|
|
|
2673
3137
|
export { FlashnetClient };
|