@flashnet/sdk 0.4.1 → 0.4.3
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/src/client/FlashnetClient.d.ts +16 -3
- package/dist/cjs/src/client/FlashnetClient.d.ts.map +1 -1
- package/dist/cjs/src/client/FlashnetClient.js +147 -43
- package/dist/cjs/src/client/FlashnetClient.js.map +1 -1
- package/dist/cjs/src/utils/auth.d.ts.map +1 -1
- package/dist/cjs/src/utils/auth.js +6 -1
- package/dist/cjs/src/utils/auth.js.map +1 -1
- package/dist/cjs/src/utils/crypto.d.ts +7 -0
- package/dist/cjs/src/utils/crypto.d.ts.map +1 -0
- package/dist/cjs/src/utils/hex.d.ts.map +1 -1
- package/dist/cjs/src/utils/hex.js +7 -3
- package/dist/cjs/src/utils/hex.js.map +1 -1
- package/dist/cjs/src/utils/index.js +1 -1
- package/dist/esm/src/client/FlashnetClient.d.ts +16 -3
- package/dist/esm/src/client/FlashnetClient.d.ts.map +1 -1
- package/dist/esm/src/client/FlashnetClient.js +143 -43
- package/dist/esm/src/client/FlashnetClient.js.map +1 -1
- package/dist/esm/src/utils/auth.d.ts.map +1 -1
- package/dist/esm/src/utils/auth.js +2 -1
- package/dist/esm/src/utils/auth.js.map +1 -1
- package/dist/esm/src/utils/crypto.d.ts +7 -0
- package/dist/esm/src/utils/crypto.d.ts.map +1 -0
- package/dist/esm/src/utils/hex.d.ts.map +1 -1
- package/dist/esm/src/utils/hex.js +7 -3
- package/dist/esm/src/utils/hex.js.map +1 -1
- package/dist/esm/src/utils/index.js +1 -1
- package/package.json +9 -5
|
@@ -4,6 +4,7 @@ import { getClientEnvironmentName, resolveClientNetworkConfig, getClientNetworkC
|
|
|
4
4
|
import { getSparkNetworkFromLegacy, getClientEnvironmentFromLegacy, Network } from '../types/index.js';
|
|
5
5
|
import { generateNonce, compareDecimalStrings } from '../utils/index.js';
|
|
6
6
|
import { AuthManager } from '../utils/auth.js';
|
|
7
|
+
import sha256 from 'fast-sha256';
|
|
7
8
|
import { getHexFromUint8Array } from '../utils/hex.js';
|
|
8
9
|
import { generateConstantProductPoolInitializationIntentMessage, generatePoolInitializationIntentMessage, generatePoolConfirmInitialDepositIntentMessage, generatePoolSwapIntentMessage, generateRouteSwapIntentMessage, generateAddLiquidityIntentMessage, generateRemoveLiquidityIntentMessage, generateRegisterHostIntentMessage, generateWithdrawHostFeesIntentMessage, generateWithdrawIntegratorFeesIntentMessage, generateCreateEscrowIntentMessage, generateFundEscrowIntentMessage, generateClaimEscrowIntentMessage, generateClawbackIntentMessage } from '../utils/intents.js';
|
|
9
10
|
import { getSparkNetworkFromAddress, encodeSparkAddressNew } from '../utils/spark-address.js';
|
|
@@ -364,7 +365,7 @@ class FlashnetClient {
|
|
|
364
365
|
nonce,
|
|
365
366
|
});
|
|
366
367
|
// Sign intent
|
|
367
|
-
const messageHash =
|
|
368
|
+
const messageHash = sha256(intentMessage);
|
|
368
369
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
369
370
|
// Create pool
|
|
370
371
|
const request = {
|
|
@@ -495,7 +496,7 @@ class FlashnetClient {
|
|
|
495
496
|
totalHostFeeRateBps: params.totalHostFeeRateBps.toString(),
|
|
496
497
|
nonce,
|
|
497
498
|
});
|
|
498
|
-
const messageHash =
|
|
499
|
+
const messageHash = sha256(intentMessage);
|
|
499
500
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
500
501
|
// Create pool
|
|
501
502
|
const request = {
|
|
@@ -551,7 +552,7 @@ class FlashnetClient {
|
|
|
551
552
|
assetASparkTransferId,
|
|
552
553
|
nonce,
|
|
553
554
|
});
|
|
554
|
-
const messageHash =
|
|
555
|
+
const messageHash = sha256(intentMessage);
|
|
555
556
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
556
557
|
const request = {
|
|
557
558
|
poolId,
|
|
@@ -635,7 +636,7 @@ class FlashnetClient {
|
|
|
635
636
|
nonce,
|
|
636
637
|
});
|
|
637
638
|
// Sign intent
|
|
638
|
-
const messageHash =
|
|
639
|
+
const messageHash = sha256(intentMessage);
|
|
639
640
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
640
641
|
const request = {
|
|
641
642
|
userPublicKey: this.publicKey,
|
|
@@ -771,7 +772,7 @@ class FlashnetClient {
|
|
|
771
772
|
defaultIntegratorFeeRateBps: params.integratorFeeRateBps?.toString(),
|
|
772
773
|
});
|
|
773
774
|
// Sign intent
|
|
774
|
-
const messageHash =
|
|
775
|
+
const messageHash = sha256(intentMessage);
|
|
775
776
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
776
777
|
const request = {
|
|
777
778
|
userPublicKey: this.publicKey,
|
|
@@ -870,7 +871,7 @@ class FlashnetClient {
|
|
|
870
871
|
nonce,
|
|
871
872
|
});
|
|
872
873
|
// Sign intent
|
|
873
|
-
const messageHash =
|
|
874
|
+
const messageHash = sha256(intentMessage);
|
|
874
875
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
875
876
|
const request = {
|
|
876
877
|
userPublicKey: this.publicKey,
|
|
@@ -945,7 +946,7 @@ class FlashnetClient {
|
|
|
945
946
|
nonce,
|
|
946
947
|
});
|
|
947
948
|
// Sign intent
|
|
948
|
-
const messageHash =
|
|
949
|
+
const messageHash = sha256(intentMessage);
|
|
949
950
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
950
951
|
const request = {
|
|
951
952
|
userPublicKey: this.publicKey,
|
|
@@ -979,7 +980,7 @@ class FlashnetClient {
|
|
|
979
980
|
nonce,
|
|
980
981
|
});
|
|
981
982
|
// Sign intent
|
|
982
|
-
const messageHash =
|
|
983
|
+
const messageHash = sha256(intentMessage);
|
|
983
984
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
984
985
|
const request = {
|
|
985
986
|
namespace: params.namespace,
|
|
@@ -1027,7 +1028,7 @@ class FlashnetClient {
|
|
|
1027
1028
|
nonce,
|
|
1028
1029
|
});
|
|
1029
1030
|
// Sign intent
|
|
1030
|
-
const messageHash =
|
|
1031
|
+
const messageHash = sha256(intentMessage);
|
|
1031
1032
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
1032
1033
|
const request = {
|
|
1033
1034
|
lpIdentityPublicKey: params.lpIdentityPublicKey,
|
|
@@ -1084,7 +1085,7 @@ class FlashnetClient {
|
|
|
1084
1085
|
nonce,
|
|
1085
1086
|
});
|
|
1086
1087
|
// Sign intent
|
|
1087
|
-
const messageHash =
|
|
1088
|
+
const messageHash = sha256(intentMessage);
|
|
1088
1089
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
1089
1090
|
const request = {
|
|
1090
1091
|
integratorPublicKey: this.publicKey,
|
|
@@ -1135,7 +1136,7 @@ class FlashnetClient {
|
|
|
1135
1136
|
abandonConditions: params.abandonConditions || undefined,
|
|
1136
1137
|
nonce,
|
|
1137
1138
|
});
|
|
1138
|
-
const messageHash =
|
|
1139
|
+
const messageHash = sha256(intentMessage);
|
|
1139
1140
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
1140
1141
|
const request = {
|
|
1141
1142
|
creatorPublicKey: this.publicKey,
|
|
@@ -1203,7 +1204,7 @@ class FlashnetClient {
|
|
|
1203
1204
|
nonce,
|
|
1204
1205
|
});
|
|
1205
1206
|
// Sign
|
|
1206
|
-
const messageHash =
|
|
1207
|
+
const messageHash = sha256(intentMessage);
|
|
1207
1208
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
1208
1209
|
// Call API
|
|
1209
1210
|
const request = {
|
|
@@ -1228,7 +1229,7 @@ class FlashnetClient {
|
|
|
1228
1229
|
recipientPublicKey: this.publicKey,
|
|
1229
1230
|
nonce,
|
|
1230
1231
|
});
|
|
1231
|
-
const messageHash =
|
|
1232
|
+
const messageHash = sha256(intentMessage);
|
|
1232
1233
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
1233
1234
|
const request = {
|
|
1234
1235
|
escrowId: params.escrowId,
|
|
@@ -1284,7 +1285,7 @@ class FlashnetClient {
|
|
|
1284
1285
|
lpIdentityPublicKey: params.lpIdentityPublicKey,
|
|
1285
1286
|
nonce,
|
|
1286
1287
|
});
|
|
1287
|
-
const messageHash =
|
|
1288
|
+
const messageHash = sha256(intentMessage);
|
|
1288
1289
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
1289
1290
|
const request = {
|
|
1290
1291
|
senderPublicKey: this.publicKey,
|
|
@@ -1765,7 +1766,7 @@ class FlashnetClient {
|
|
|
1765
1766
|
assetBMinAmountIn: assetBMinAmountIn.toString(),
|
|
1766
1767
|
nonce,
|
|
1767
1768
|
});
|
|
1768
|
-
const messageHash =
|
|
1769
|
+
const messageHash = sha256(intentMessage);
|
|
1769
1770
|
const signature = await this._wallet.config.signer.signMessageWithIdentityKey(messageHash, true);
|
|
1770
1771
|
const request = {
|
|
1771
1772
|
userPublicKey: this.publicKey,
|
|
@@ -1863,15 +1864,16 @@ class FlashnetClient {
|
|
|
1863
1864
|
*/
|
|
1864
1865
|
async payLightningWithToken(options) {
|
|
1865
1866
|
await this.ensureInitialized();
|
|
1866
|
-
const { invoice, tokenAddress, maxSlippageBps =
|
|
1867
|
-
maxLightningFeeSats, preferSpark = true, integratorFeeRateBps, integratorPublicKey, transferTimeoutMs =
|
|
1867
|
+
const { invoice, tokenAddress, maxSlippageBps = 500, // 5% default
|
|
1868
|
+
maxLightningFeeSats, preferSpark = true, integratorFeeRateBps, integratorPublicKey, transferTimeoutMs = 30000, // 30s default
|
|
1869
|
+
rollbackOnFailure = false, useExistingBtcBalance = false, } = options;
|
|
1868
1870
|
try {
|
|
1869
1871
|
// Step 1: Get a quote for the payment
|
|
1870
1872
|
const quote = await this.getPayLightningWithTokenQuote(invoice, tokenAddress, {
|
|
1871
1873
|
maxSlippageBps,
|
|
1872
1874
|
integratorFeeRateBps,
|
|
1873
1875
|
});
|
|
1874
|
-
// Step 2: Check balance
|
|
1876
|
+
// Step 2: Check token balance (always required)
|
|
1875
1877
|
await this.checkBalance({
|
|
1876
1878
|
balancesToCheck: [
|
|
1877
1879
|
{
|
|
@@ -1881,6 +1883,16 @@ class FlashnetClient {
|
|
|
1881
1883
|
],
|
|
1882
1884
|
errorPrefix: "Insufficient token balance for Lightning payment: ",
|
|
1883
1885
|
});
|
|
1886
|
+
// Determine if we can pay immediately using existing BTC balance
|
|
1887
|
+
let canPayImmediately = false;
|
|
1888
|
+
if (useExistingBtcBalance) {
|
|
1889
|
+
const invoiceAmountSats = await this.decodeInvoiceAmount(invoice);
|
|
1890
|
+
const effectiveMaxLightningFee = maxLightningFeeSats ?? quote.estimatedLightningFee;
|
|
1891
|
+
const btcNeededForPayment = invoiceAmountSats + effectiveMaxLightningFee;
|
|
1892
|
+
// Check if we have enough BTC (don't throw if not, just fall back to waiting)
|
|
1893
|
+
const balance = await this.getBalance();
|
|
1894
|
+
canPayImmediately = balance.balance >= BigInt(btcNeededForPayment);
|
|
1895
|
+
}
|
|
1884
1896
|
// Step 3: Get pool details
|
|
1885
1897
|
const pool = await this.getPool(quote.poolId);
|
|
1886
1898
|
// Step 4: Determine swap direction and execute
|
|
@@ -1914,39 +1926,88 @@ class FlashnetClient {
|
|
|
1914
1926
|
error: swapResponse.error || "Swap was not accepted",
|
|
1915
1927
|
};
|
|
1916
1928
|
}
|
|
1917
|
-
// Step 5: Wait for the transfer to complete
|
|
1918
|
-
|
|
1919
|
-
|
|
1929
|
+
// Step 5: Wait for the transfer to complete (unless paying immediately with existing BTC)
|
|
1930
|
+
if (!canPayImmediately) {
|
|
1931
|
+
const transferComplete = await this.waitForTransferCompletion(swapResponse.outboundTransferId, transferTimeoutMs);
|
|
1932
|
+
if (!transferComplete) {
|
|
1933
|
+
return {
|
|
1934
|
+
success: false,
|
|
1935
|
+
poolId: quote.poolId,
|
|
1936
|
+
tokenAmountSpent: quote.tokenAmountRequired,
|
|
1937
|
+
btcAmountReceived: swapResponse.amountOut || "0",
|
|
1938
|
+
swapTransferId: swapResponse.outboundTransferId,
|
|
1939
|
+
ammFeePaid: quote.estimatedAmmFee,
|
|
1940
|
+
error: "Transfer did not complete within timeout",
|
|
1941
|
+
};
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
// Step 6: Calculate Lightning fee limit - use the quoted estimate, not a recalculation
|
|
1945
|
+
const effectiveMaxLightningFee = maxLightningFeeSats ?? quote.estimatedLightningFee;
|
|
1946
|
+
// Step 7: Pay the Lightning invoice
|
|
1947
|
+
const btcReceived = swapResponse.amountOut || quote.btcAmountRequired;
|
|
1948
|
+
try {
|
|
1949
|
+
const lightningPayment = await this._wallet.payLightningInvoice({
|
|
1950
|
+
invoice,
|
|
1951
|
+
maxFeeSats: effectiveMaxLightningFee,
|
|
1952
|
+
preferSpark,
|
|
1953
|
+
});
|
|
1954
|
+
return {
|
|
1955
|
+
success: true,
|
|
1956
|
+
poolId: quote.poolId,
|
|
1957
|
+
tokenAmountSpent: quote.tokenAmountRequired,
|
|
1958
|
+
btcAmountReceived: btcReceived,
|
|
1959
|
+
swapTransferId: swapResponse.outboundTransferId,
|
|
1960
|
+
lightningPaymentId: lightningPayment.id,
|
|
1961
|
+
ammFeePaid: quote.estimatedAmmFee,
|
|
1962
|
+
lightningFeePaid: effectiveMaxLightningFee,
|
|
1963
|
+
};
|
|
1964
|
+
}
|
|
1965
|
+
catch (lightningError) {
|
|
1966
|
+
// Lightning payment failed after swap succeeded
|
|
1967
|
+
const lightningErrorMessage = lightningError instanceof Error
|
|
1968
|
+
? lightningError.message
|
|
1969
|
+
: String(lightningError);
|
|
1970
|
+
// Attempt rollback if requested
|
|
1971
|
+
if (rollbackOnFailure) {
|
|
1972
|
+
try {
|
|
1973
|
+
const rollbackResult = await this.rollbackSwap(quote.poolId, btcReceived, tokenAddress, maxSlippageBps);
|
|
1974
|
+
if (rollbackResult.success) {
|
|
1975
|
+
return {
|
|
1976
|
+
success: false,
|
|
1977
|
+
poolId: quote.poolId,
|
|
1978
|
+
tokenAmountSpent: "0", // Rolled back
|
|
1979
|
+
btcAmountReceived: "0",
|
|
1980
|
+
swapTransferId: swapResponse.outboundTransferId,
|
|
1981
|
+
ammFeePaid: quote.estimatedAmmFee,
|
|
1982
|
+
error: `Lightning payment failed: ${lightningErrorMessage}. Funds rolled back to ${rollbackResult.tokenAmount} tokens.`,
|
|
1983
|
+
};
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
catch (rollbackError) {
|
|
1987
|
+
const rollbackErrorMessage = rollbackError instanceof Error
|
|
1988
|
+
? rollbackError.message
|
|
1989
|
+
: String(rollbackError);
|
|
1990
|
+
return {
|
|
1991
|
+
success: false,
|
|
1992
|
+
poolId: quote.poolId,
|
|
1993
|
+
tokenAmountSpent: quote.tokenAmountRequired,
|
|
1994
|
+
btcAmountReceived: btcReceived,
|
|
1995
|
+
swapTransferId: swapResponse.outboundTransferId,
|
|
1996
|
+
ammFeePaid: quote.estimatedAmmFee,
|
|
1997
|
+
error: `Lightning payment failed: ${lightningErrorMessage}. Rollback also failed: ${rollbackErrorMessage}. BTC remains in wallet.`,
|
|
1998
|
+
};
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
1920
2001
|
return {
|
|
1921
2002
|
success: false,
|
|
1922
2003
|
poolId: quote.poolId,
|
|
1923
2004
|
tokenAmountSpent: quote.tokenAmountRequired,
|
|
1924
|
-
btcAmountReceived:
|
|
2005
|
+
btcAmountReceived: btcReceived,
|
|
1925
2006
|
swapTransferId: swapResponse.outboundTransferId,
|
|
1926
2007
|
ammFeePaid: quote.estimatedAmmFee,
|
|
1927
|
-
error:
|
|
2008
|
+
error: `Lightning payment failed: ${lightningErrorMessage}. BTC (${btcReceived} sats) remains in wallet.`,
|
|
1928
2009
|
};
|
|
1929
2010
|
}
|
|
1930
|
-
// Step 6: Calculate Lightning fee limit
|
|
1931
|
-
const invoiceAmountSats = await this.decodeInvoiceAmount(invoice);
|
|
1932
|
-
const effectiveMaxLightningFee = maxLightningFeeSats ??
|
|
1933
|
-
Math.max(5, Math.ceil(invoiceAmountSats * 0.0017)); // 17 bps or 5 sats minimum
|
|
1934
|
-
// Step 7: Pay the Lightning invoice
|
|
1935
|
-
const lightningPayment = await this._wallet.payLightningInvoice({
|
|
1936
|
-
invoice,
|
|
1937
|
-
maxFeeSats: effectiveMaxLightningFee,
|
|
1938
|
-
preferSpark,
|
|
1939
|
-
});
|
|
1940
|
-
return {
|
|
1941
|
-
success: true,
|
|
1942
|
-
poolId: quote.poolId,
|
|
1943
|
-
tokenAmountSpent: quote.tokenAmountRequired,
|
|
1944
|
-
btcAmountReceived: swapResponse.amountOut || quote.btcAmountRequired,
|
|
1945
|
-
swapTransferId: swapResponse.outboundTransferId,
|
|
1946
|
-
lightningPaymentId: lightningPayment.id,
|
|
1947
|
-
ammFeePaid: quote.estimatedAmmFee,
|
|
1948
|
-
lightningFeePaid: effectiveMaxLightningFee,
|
|
1949
|
-
};
|
|
1950
2011
|
}
|
|
1951
2012
|
catch (error) {
|
|
1952
2013
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -1961,6 +2022,45 @@ class FlashnetClient {
|
|
|
1961
2022
|
};
|
|
1962
2023
|
}
|
|
1963
2024
|
}
|
|
2025
|
+
/**
|
|
2026
|
+
* Attempt to rollback a swap by swapping BTC back to the original token
|
|
2027
|
+
* @private
|
|
2028
|
+
*/
|
|
2029
|
+
async rollbackSwap(poolId, btcAmount, tokenAddress, maxSlippageBps) {
|
|
2030
|
+
const pool = await this.getPool(poolId);
|
|
2031
|
+
const tokenHex = this.toHexTokenIdentifier(tokenAddress);
|
|
2032
|
+
// Determine swap direction (BTC -> Token)
|
|
2033
|
+
const tokenIsAssetA = pool.assetAAddress === tokenHex;
|
|
2034
|
+
const assetInAddress = tokenIsAssetA
|
|
2035
|
+
? pool.assetBAddress
|
|
2036
|
+
: pool.assetAAddress; // BTC
|
|
2037
|
+
const assetOutAddress = tokenIsAssetA
|
|
2038
|
+
? pool.assetAAddress
|
|
2039
|
+
: pool.assetBAddress; // Token
|
|
2040
|
+
// Calculate expected token output and min amount with slippage
|
|
2041
|
+
// For rollback, we accept more slippage since we're recovering from failure
|
|
2042
|
+
const minAmountOut = "0"; // Accept any amount to ensure rollback succeeds
|
|
2043
|
+
// Execute reverse swap
|
|
2044
|
+
const swapResponse = await this.executeSwap({
|
|
2045
|
+
poolId,
|
|
2046
|
+
assetInAddress,
|
|
2047
|
+
assetOutAddress,
|
|
2048
|
+
amountIn: btcAmount,
|
|
2049
|
+
maxSlippageBps: maxSlippageBps * 2, // Double slippage for rollback
|
|
2050
|
+
minAmountOut,
|
|
2051
|
+
});
|
|
2052
|
+
if (!swapResponse.accepted) {
|
|
2053
|
+
throw new Error(swapResponse.error || "Rollback swap not accepted");
|
|
2054
|
+
}
|
|
2055
|
+
// Wait for the rollback transfer
|
|
2056
|
+
if (swapResponse.outboundTransferId) {
|
|
2057
|
+
await this.waitForTransferCompletion(swapResponse.outboundTransferId, 30000);
|
|
2058
|
+
}
|
|
2059
|
+
return {
|
|
2060
|
+
success: true,
|
|
2061
|
+
tokenAmount: swapResponse.amountOut,
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
1964
2064
|
/**
|
|
1965
2065
|
* Find the best pool for swapping a token to BTC
|
|
1966
2066
|
* @private
|