@buildonspark/spark-sdk 0.0.11 → 0.0.13
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/graphql/objects/LeavesSwapRequest.d.ts +8 -8
- package/dist/graphql/objects/LeavesSwapRequest.js +21 -12
- package/dist/graphql/objects/LeavesSwapRequest.js.map +1 -1
- package/dist/graphql/objects/SparkTransferToLeavesConnection.d.ts +5 -5
- package/dist/graphql/objects/SparkTransferToLeavesConnection.js +6 -5
- package/dist/graphql/objects/SparkTransferToLeavesConnection.js.map +1 -1
- package/dist/graphql/objects/Transfer.d.ts +1 -1
- package/dist/services/config.d.ts +2 -16
- package/dist/services/config.js +8 -8
- package/dist/services/config.js.map +1 -1
- package/dist/services/connection.js +25 -11
- package/dist/services/connection.js.map +1 -1
- package/dist/services/coop-exit.js +1 -2
- package/dist/services/coop-exit.js.map +1 -1
- package/dist/services/deposit.js +1 -1
- package/dist/services/deposit.js.map +1 -1
- package/dist/services/lightning.js +1 -0
- package/dist/services/lightning.js.map +1 -1
- package/dist/services/transfer.d.ts +4 -4
- package/dist/services/transfer.js +6 -6
- package/dist/services/transfer.js.map +1 -1
- package/dist/services/wallet-config.d.ts +22 -0
- package/dist/services/wallet-config.js +100 -0
- package/dist/services/wallet-config.js.map +1 -0
- package/dist/signer/signer.d.ts +8 -4
- package/dist/signer/signer.js +45 -36
- package/dist/signer/signer.js.map +1 -1
- package/dist/spark-sdk.d.ts +49 -47
- package/dist/spark-sdk.js +73 -145
- package/dist/spark-sdk.js.map +1 -1
- package/dist/tests/adaptor-signature.test.js +5 -2
- package/dist/tests/adaptor-signature.test.js.map +1 -1
- package/dist/tests/coop-exit.test.js +10 -9
- package/dist/tests/coop-exit.test.js.map +1 -1
- package/dist/tests/deposit.test.js +10 -4
- package/dist/tests/deposit.test.js.map +1 -1
- package/dist/tests/lightning.test.js +16 -12
- package/dist/tests/lightning.test.js.map +1 -1
- package/dist/tests/swap.test.js +16 -11
- package/dist/tests/swap.test.js.map +1 -1
- package/dist/tests/test-util.d.ts +1 -8
- package/dist/tests/test-util.js +5 -117
- package/dist/tests/test-util.js.map +1 -1
- package/dist/tests/transfer.test.js +41 -36
- package/dist/tests/transfer.test.js.map +1 -1
- package/dist/tests/utils/spark-testing-wallet.d.ts +5 -1
- package/dist/tests/utils/spark-testing-wallet.js +8 -0
- package/dist/tests/utils/spark-testing-wallet.js.map +1 -1
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/mempool.d.ts +1 -0
- package/dist/utils/mempool.js +29 -0
- package/dist/utils/mempool.js.map +1 -0
- package/dist/utils/network.d.ts +14 -6
- package/dist/utils/network.js +29 -6
- package/dist/utils/network.js.map +1 -1
- package/dist/utils/signing.d.ts +1 -1
- package/dist/utils/wasm-wrapper.js +23 -13
- package/dist/utils/wasm-wrapper.js.map +1 -1
- package/package.json +21 -5
package/dist/spark-sdk.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { CoopExitFeeEstimateInput, CoopExitFeeEstimateOutput, LeavesSwapRequest, LightningReceiveFeeEstimateInput, LightningReceiveFeeEstimateOutput, LightningSendFeeEstimateInput, LightningSendFeeEstimateOutput } from "./graphql/objects/index.js";
|
|
1
2
|
import { LeafWithPreviousTransactionData, QueryAllTransfersResponse, Transfer, TreeNode } from "./proto/spark.js";
|
|
2
|
-
import {
|
|
3
|
+
import { WalletConfigService } from "./services/config.js";
|
|
3
4
|
import { ConnectionManager } from "./services/connection.js";
|
|
4
5
|
import { TransferService } from "./services/transfer.js";
|
|
5
|
-
import {
|
|
6
|
+
import { ConfigOptions } from "./services/wallet-config.js";
|
|
6
7
|
import { LRC20WalletApiConfig, LRCWallet } from "@buildonspark/lrc20-sdk";
|
|
8
|
+
import { SparkSigner } from "./signer/signer.js";
|
|
7
9
|
export type CreateLightningInvoiceParams = {
|
|
8
10
|
amountSats: number;
|
|
9
11
|
memo: string;
|
|
@@ -12,19 +14,19 @@ export type CreateLightningInvoiceParams = {
|
|
|
12
14
|
export type PayLightningInvoiceParams = {
|
|
13
15
|
invoice: string;
|
|
14
16
|
};
|
|
15
|
-
export type
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
receiverPubKey: string;
|
|
19
|
-
expiryTime?: Date;
|
|
17
|
+
export type TransferParams = {
|
|
18
|
+
amountSats: number;
|
|
19
|
+
receiverSparkAddress: string;
|
|
20
20
|
};
|
|
21
21
|
export type InitWalletResponse = {
|
|
22
|
-
balance: bigint;
|
|
23
|
-
tokenBalance: Map<string, {
|
|
24
|
-
balance: bigint;
|
|
25
|
-
}>;
|
|
26
22
|
mnemonic?: string | undefined;
|
|
27
23
|
};
|
|
24
|
+
export interface SparkWalletProps {
|
|
25
|
+
mnemonicOrSeed?: Uint8Array | string;
|
|
26
|
+
signer?: SparkSigner;
|
|
27
|
+
options?: ConfigOptions;
|
|
28
|
+
lrc20WalletApiConfig?: LRC20WalletApiConfig;
|
|
29
|
+
}
|
|
28
30
|
/**
|
|
29
31
|
* The SparkWallet class is the primary interface for interacting with the Spark network.
|
|
30
32
|
* It provides methods for creating and managing wallets, handling deposits, executing transfers,
|
|
@@ -47,7 +49,11 @@ export declare class SparkWallet {
|
|
|
47
49
|
private wasmModule;
|
|
48
50
|
protected leaves: TreeNode[];
|
|
49
51
|
protected tokenLeaves: Map<string, LeafWithPreviousTransactionData[]>;
|
|
50
|
-
constructor(
|
|
52
|
+
protected constructor(options?: ConfigOptions, signer?: SparkSigner);
|
|
53
|
+
static create({ mnemonicOrSeed, signer, options, lrc20WalletApiConfig, }: SparkWalletProps): Promise<{
|
|
54
|
+
mnemonic?: string | undefined;
|
|
55
|
+
wallet: SparkWallet;
|
|
56
|
+
}>;
|
|
51
57
|
private initWasm;
|
|
52
58
|
private initializeWallet;
|
|
53
59
|
private getLeaves;
|
|
@@ -57,7 +63,6 @@ export declare class SparkWallet {
|
|
|
57
63
|
private optimizeLeaves;
|
|
58
64
|
private syncWallet;
|
|
59
65
|
private withLeaves;
|
|
60
|
-
private isInitialized;
|
|
61
66
|
/**
|
|
62
67
|
* Gets the identity public key of the wallet.
|
|
63
68
|
*
|
|
@@ -84,9 +89,9 @@ export declare class SparkWallet {
|
|
|
84
89
|
* - mnemonic: The mnemonic if one was generated (undefined for raw seed)
|
|
85
90
|
* - balance: The wallet's initial balance in satoshis
|
|
86
91
|
* - tokenBalance: Map of token balances and leaf counts
|
|
92
|
+
* @private
|
|
87
93
|
*/
|
|
88
|
-
initWallet(mnemonicOrSeed?: Uint8Array | string,
|
|
89
|
-
private initWalletFromMnemonic;
|
|
94
|
+
protected initWallet(mnemonicOrSeed?: Uint8Array | string, lrc20WalletApiConfig?: LRC20WalletApiConfig): Promise<InitWalletResponse | undefined>;
|
|
90
95
|
/**
|
|
91
96
|
* Initializes a wallet from a seed.
|
|
92
97
|
*
|
|
@@ -102,9 +107,11 @@ export declare class SparkWallet {
|
|
|
102
107
|
* @param {number} [params.targetAmount] - Target amount for the swap
|
|
103
108
|
* @param {TreeNode[]} [params.leaves] - Specific leaves to swap
|
|
104
109
|
* @returns {Promise<Object>} The completed swap response
|
|
105
|
-
* @private
|
|
106
110
|
*/
|
|
107
|
-
|
|
111
|
+
requestLeavesSwap({ targetAmount, leaves, }: {
|
|
112
|
+
targetAmount?: number;
|
|
113
|
+
leaves?: TreeNode[];
|
|
114
|
+
}): Promise<LeavesSwapRequest>;
|
|
108
115
|
/**
|
|
109
116
|
* Gets all transfers for the wallet.
|
|
110
117
|
*
|
|
@@ -112,7 +119,7 @@ export declare class SparkWallet {
|
|
|
112
119
|
* @param {number} [offset=0] - Offset for pagination
|
|
113
120
|
* @returns {Promise<QueryAllTransfersResponse>} Response containing the list of transfers
|
|
114
121
|
*/
|
|
115
|
-
|
|
122
|
+
getTransfers(limit?: number, offset?: number): Promise<QueryAllTransfersResponse>;
|
|
116
123
|
/**
|
|
117
124
|
* Gets the current balance of the wallet.
|
|
118
125
|
* You can use the forceRefetch option to synchronize your wallet and claim any
|
|
@@ -153,15 +160,19 @@ export declare class SparkWallet {
|
|
|
153
160
|
* @private
|
|
154
161
|
*/
|
|
155
162
|
private finalizeDeposit;
|
|
156
|
-
claimDeposit(txid: string): Promise<TreeNode[] | undefined>;
|
|
157
163
|
/**
|
|
158
|
-
*
|
|
164
|
+
* Gets all unused deposit addresses for the wallet.
|
|
159
165
|
*
|
|
160
|
-
* @
|
|
161
|
-
|
|
162
|
-
|
|
166
|
+
* @returns {Promise<string[]>} The unused deposit addresses
|
|
167
|
+
*/
|
|
168
|
+
getUnusedDepositAddresses(): Promise<string[]>;
|
|
169
|
+
/**
|
|
170
|
+
* Claims a deposit to the wallet.
|
|
171
|
+
*
|
|
172
|
+
* @param {string} txid - The transaction ID of the deposit
|
|
173
|
+
* @returns {Promise<TreeNode[] | undefined>} The nodes resulting from the deposit
|
|
163
174
|
*/
|
|
164
|
-
|
|
175
|
+
claimDeposit(txid: string): Promise<TreeNode[] | undefined>;
|
|
165
176
|
/**
|
|
166
177
|
* Transfers deposit to self to claim ownership.
|
|
167
178
|
*
|
|
@@ -174,45 +185,39 @@ export declare class SparkWallet {
|
|
|
174
185
|
/**
|
|
175
186
|
* Sends a transfer to another Spark user.
|
|
176
187
|
*
|
|
177
|
-
* @param {
|
|
188
|
+
* @param {TransferParams} params - Parameters for the transfer
|
|
178
189
|
* @param {string} params.receiverSparkAddress - The recipient's Spark address
|
|
179
190
|
* @param {number} params.amountSats - Amount to send in satoshis
|
|
180
191
|
* @returns {Promise<Transfer>} The completed transfer details
|
|
181
192
|
*/
|
|
182
|
-
|
|
183
|
-
receiverSparkAddress: string;
|
|
184
|
-
amountSats: number;
|
|
185
|
-
}): Promise<Transfer>;
|
|
193
|
+
transfer({ amountSats, receiverSparkAddress }: TransferParams): Promise<Transfer>;
|
|
186
194
|
/**
|
|
187
|
-
* Internal method to
|
|
195
|
+
* Internal method to refresh timelock nodes.
|
|
188
196
|
*
|
|
189
|
-
* @param {
|
|
190
|
-
* @returns {Promise<
|
|
197
|
+
* @param {string} nodeId - The optional ID of the node to refresh. If not provided, all nodes will be checked.
|
|
198
|
+
* @returns {Promise<void>}
|
|
191
199
|
* @private
|
|
192
200
|
*/
|
|
193
|
-
private
|
|
201
|
+
private refreshTimelockNodes;
|
|
194
202
|
/**
|
|
195
|
-
*
|
|
203
|
+
* Gets all pending transfers.
|
|
196
204
|
*
|
|
197
|
-
* @
|
|
198
|
-
* @returns {Promise<void>}
|
|
205
|
+
* @returns {Promise<Transfer[]>} The pending transfers
|
|
199
206
|
*/
|
|
200
|
-
|
|
207
|
+
getPendingTransfers(): Promise<Transfer[]>;
|
|
201
208
|
/**
|
|
202
209
|
* Claims a specific transfer.
|
|
203
210
|
*
|
|
204
211
|
* @param {Transfer} transfer - The transfer to claim
|
|
205
212
|
* @returns {Promise<Object>} The claim result
|
|
206
|
-
* @private
|
|
207
213
|
*/
|
|
208
|
-
|
|
214
|
+
claimTransfer(transfer: Transfer): Promise<TreeNode[]>;
|
|
209
215
|
/**
|
|
210
216
|
* Claims all pending transfers.
|
|
211
217
|
*
|
|
212
218
|
* @returns {Promise<boolean>} True if any transfers were claimed
|
|
213
|
-
* @private
|
|
214
219
|
*/
|
|
215
|
-
|
|
220
|
+
claimTransfers(): Promise<boolean>;
|
|
216
221
|
/**
|
|
217
222
|
* Cancels all sender-initiated transfers.
|
|
218
223
|
*
|
|
@@ -243,17 +248,15 @@ export declare class SparkWallet {
|
|
|
243
248
|
*
|
|
244
249
|
* @param {LightningReceiveFeeEstimateInput} params - Input parameters for fee estimation
|
|
245
250
|
* @returns {Promise<LightningReceiveFeeEstimateOutput | null>} Fee estimate for receiving Lightning payments
|
|
246
|
-
* @private
|
|
247
251
|
*/
|
|
248
|
-
|
|
252
|
+
getLightningReceiveFeeEstimate({ amountSats, network, }: LightningReceiveFeeEstimateInput): Promise<LightningReceiveFeeEstimateOutput | null>;
|
|
249
253
|
/**
|
|
250
254
|
* Gets fee estimate for sending Lightning payments.
|
|
251
255
|
*
|
|
252
256
|
* @param {LightningSendFeeEstimateInput} params - Input parameters for fee estimation
|
|
253
257
|
* @returns {Promise<LightningSendFeeEstimateOutput | null>} Fee estimate for sending Lightning payments
|
|
254
|
-
* @private
|
|
255
258
|
*/
|
|
256
|
-
|
|
259
|
+
getLightningSendFeeEstimate({ encodedInvoice, }: LightningSendFeeEstimateInput): Promise<LightningSendFeeEstimateOutput | null>;
|
|
257
260
|
/**
|
|
258
261
|
* Generates a deposit address for a tree.
|
|
259
262
|
*
|
|
@@ -303,9 +306,8 @@ export declare class SparkWallet {
|
|
|
303
306
|
*
|
|
304
307
|
* @param {CoopExitFeeEstimateInput} params - Input parameters for fee estimation
|
|
305
308
|
* @returns {Promise<CoopExitFeeEstimateOutput | null>} Fee estimate for the withdrawal
|
|
306
|
-
* @private
|
|
307
309
|
*/
|
|
308
|
-
|
|
310
|
+
getCoopExitFeeEstimate({ leafExternalIds, withdrawalAddress, }: CoopExitFeeEstimateInput): Promise<CoopExitFeeEstimateOutput | null>;
|
|
309
311
|
/**
|
|
310
312
|
* Synchronizes token leaves for the wallet.
|
|
311
313
|
*
|
package/dist/spark-sdk.js
CHANGED
|
@@ -13,7 +13,6 @@ import { DepositService } from "./services/deposit.js";
|
|
|
13
13
|
import { LightningService } from "./services/lightning.js";
|
|
14
14
|
import { TokenTransactionService } from "./services/token-transactions.js";
|
|
15
15
|
import { TransferService } from "./services/transfer.js";
|
|
16
|
-
import * as bip39 from "@scure/bip39";
|
|
17
16
|
import { validateMnemonic } from "@scure/bip39";
|
|
18
17
|
import { wordlist } from "@scure/bip39/wordlists/english";
|
|
19
18
|
import { Mutex } from "async-mutex";
|
|
@@ -30,20 +29,6 @@ import { broadcastL1Withdrawal } from "./services/lrc20.js";
|
|
|
30
29
|
import { getMasterHDKeyFromSeed } from "./utils/index.js";
|
|
31
30
|
// Add this constant at the file level
|
|
32
31
|
const MAX_TOKEN_LEAVES = 100;
|
|
33
|
-
class LeafOperationError extends Error {
|
|
34
|
-
cause;
|
|
35
|
-
constructor(message, cause) {
|
|
36
|
-
super(message);
|
|
37
|
-
this.cause = cause;
|
|
38
|
-
this.name = "LeafOperationError";
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
class LeafOperationTimeoutError extends LeafOperationError {
|
|
42
|
-
constructor(message) {
|
|
43
|
-
super(message);
|
|
44
|
-
this.name = "LeafOperationTimeoutError";
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
32
|
/**
|
|
48
33
|
* The SparkWallet class is the primary interface for interacting with the Spark network.
|
|
49
34
|
* It provides methods for creating and managing wallets, handling deposits, executing transfers,
|
|
@@ -66,8 +51,8 @@ export class SparkWallet {
|
|
|
66
51
|
wasmModule = null;
|
|
67
52
|
leaves = [];
|
|
68
53
|
tokenLeaves = new Map();
|
|
69
|
-
constructor(
|
|
70
|
-
this.config = new WalletConfigService(
|
|
54
|
+
constructor(options, signer) {
|
|
55
|
+
this.config = new WalletConfigService(options, signer);
|
|
71
56
|
this.connectionManager = new ConnectionManager(this.config);
|
|
72
57
|
this.depositService = new DepositService(this.config, this.connectionManager);
|
|
73
58
|
this.transferService = new TransferService(this.config, this.connectionManager);
|
|
@@ -76,6 +61,14 @@ export class SparkWallet {
|
|
|
76
61
|
this.lightningService = new LightningService(this.config, this.connectionManager);
|
|
77
62
|
this.coopExitService = new CoopExitService(this.config, this.connectionManager);
|
|
78
63
|
}
|
|
64
|
+
static async create({ mnemonicOrSeed, signer, options, lrc20WalletApiConfig, }) {
|
|
65
|
+
const wallet = new SparkWallet(options, signer);
|
|
66
|
+
const initResponse = await wallet.initWallet(mnemonicOrSeed, lrc20WalletApiConfig);
|
|
67
|
+
return {
|
|
68
|
+
wallet,
|
|
69
|
+
...initResponse,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
79
72
|
async initWasm() {
|
|
80
73
|
try {
|
|
81
74
|
this.wasmModule = await initWasm();
|
|
@@ -85,13 +78,9 @@ export class SparkWallet {
|
|
|
85
78
|
}
|
|
86
79
|
}
|
|
87
80
|
async initializeWallet(identityPublicKey) {
|
|
88
|
-
await this.connectionManager.createClients();
|
|
89
81
|
this.sspClient = new SspClient(identityPublicKey);
|
|
90
|
-
await
|
|
91
|
-
|
|
92
|
-
// Hacky but do this to store the deposit signing key in the signer
|
|
93
|
-
this.config.signer.getDepositSigningKey(),
|
|
94
|
-
]);
|
|
82
|
+
await this.connectionManager.createClients();
|
|
83
|
+
await this.initWasm();
|
|
95
84
|
await this.syncWallet();
|
|
96
85
|
}
|
|
97
86
|
async getLeaves() {
|
|
@@ -195,8 +184,8 @@ export class SparkWallet {
|
|
|
195
184
|
async syncWallet() {
|
|
196
185
|
await Promise.all([this.claimTransfers(), this.syncTokenLeaves()]);
|
|
197
186
|
this.leaves = await this.getLeaves();
|
|
198
|
-
await this.refreshTimelockNodes();
|
|
199
187
|
await this.config.signer.restoreSigningKeysFromLeafs(this.leaves);
|
|
188
|
+
await this.refreshTimelockNodes();
|
|
200
189
|
this.optimizeLeaves().catch((e) => {
|
|
201
190
|
console.error("Failed to optimize leaves", e);
|
|
202
191
|
});
|
|
@@ -210,9 +199,6 @@ export class SparkWallet {
|
|
|
210
199
|
release();
|
|
211
200
|
}
|
|
212
201
|
}
|
|
213
|
-
isInitialized() {
|
|
214
|
-
return this.sspClient !== null && this.wasmModule !== null;
|
|
215
|
-
}
|
|
216
202
|
/**
|
|
217
203
|
* Gets the identity public key of the wallet.
|
|
218
204
|
*
|
|
@@ -243,33 +229,28 @@ export class SparkWallet {
|
|
|
243
229
|
* - mnemonic: The mnemonic if one was generated (undefined for raw seed)
|
|
244
230
|
* - balance: The wallet's initial balance in satoshis
|
|
245
231
|
* - tokenBalance: Map of token balances and leaf counts
|
|
232
|
+
* @private
|
|
246
233
|
*/
|
|
247
|
-
async initWallet(mnemonicOrSeed,
|
|
234
|
+
async initWallet(mnemonicOrSeed, lrc20WalletApiConfig) {
|
|
248
235
|
const returnMnemonic = !mnemonicOrSeed;
|
|
236
|
+
let mnemonic;
|
|
249
237
|
if (!mnemonicOrSeed) {
|
|
250
238
|
mnemonicOrSeed = await this.config.signer.generateMnemonic();
|
|
251
239
|
}
|
|
240
|
+
let seed;
|
|
252
241
|
if (typeof mnemonicOrSeed !== "string") {
|
|
253
|
-
|
|
254
|
-
}
|
|
255
|
-
let mnemonic;
|
|
256
|
-
if (validateMnemonic(mnemonicOrSeed, wordlist)) {
|
|
257
|
-
mnemonic = mnemonicOrSeed;
|
|
258
|
-
await this.initWalletFromMnemonic(mnemonicOrSeed);
|
|
242
|
+
seed = mnemonicOrSeed;
|
|
259
243
|
}
|
|
260
244
|
else {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const balance = this.leaves.reduce((acc, leaf) => acc + BigInt(leaf.value), 0n);
|
|
264
|
-
const tokenBalance = await this.getAllTokenBalances();
|
|
265
|
-
if (enableLRC20Wallet) {
|
|
266
|
-
let seed;
|
|
267
|
-
if (typeof mnemonicOrSeed === "string") {
|
|
268
|
-
seed = await bip39.mnemonicToSeed(mnemonicOrSeed);
|
|
245
|
+
if (validateMnemonic(mnemonicOrSeed, wordlist)) {
|
|
246
|
+
seed = await this.config.signer.mnemonicToSeed(mnemonicOrSeed);
|
|
269
247
|
}
|
|
270
248
|
else {
|
|
271
|
-
seed = mnemonicOrSeed;
|
|
249
|
+
seed = hexToBytes(mnemonicOrSeed);
|
|
272
250
|
}
|
|
251
|
+
}
|
|
252
|
+
await this.initWalletFromSeed(seed);
|
|
253
|
+
if (lrc20WalletApiConfig) {
|
|
273
254
|
const network = this.config.getNetwork();
|
|
274
255
|
const masterPrivateKey = getMasterHDKeyFromSeed(seed, network == Network.REGTEST ? 0 : 1).privateKey;
|
|
275
256
|
this.lrc20Wallet = new LRCWallet(bytesToHex(masterPrivateKey), LRC_WALLET_NETWORK[network], LRC_WALLET_NETWORK_TYPE[network], lrc20WalletApiConfig);
|
|
@@ -277,19 +258,9 @@ export class SparkWallet {
|
|
|
277
258
|
if (returnMnemonic) {
|
|
278
259
|
return {
|
|
279
260
|
mnemonic,
|
|
280
|
-
balance,
|
|
281
|
-
tokenBalance,
|
|
282
261
|
};
|
|
283
262
|
}
|
|
284
|
-
return
|
|
285
|
-
balance,
|
|
286
|
-
tokenBalance,
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
async initWalletFromMnemonic(mnemonic) {
|
|
290
|
-
const identityPublicKey = await this.config.signer.createSparkWalletFromMnemonic(mnemonic, this.config.getNetwork());
|
|
291
|
-
await this.initializeWallet(identityPublicKey);
|
|
292
|
-
return identityPublicKey;
|
|
263
|
+
return;
|
|
293
264
|
}
|
|
294
265
|
/**
|
|
295
266
|
* Initializes a wallet from a seed.
|
|
@@ -310,7 +281,6 @@ export class SparkWallet {
|
|
|
310
281
|
* @param {number} [params.targetAmount] - Target amount for the swap
|
|
311
282
|
* @param {TreeNode[]} [params.leaves] - Specific leaves to swap
|
|
312
283
|
* @returns {Promise<Object>} The completed swap response
|
|
313
|
-
* @private
|
|
314
284
|
*/
|
|
315
285
|
async requestLeavesSwap({ targetAmount, leaves, }) {
|
|
316
286
|
if (targetAmount && targetAmount <= 0) {
|
|
@@ -338,7 +308,7 @@ export class SparkWallet {
|
|
|
338
308
|
signingPubKey: await this.config.signer.generatePublicKey(sha256(leaf.id)),
|
|
339
309
|
newSigningPubKey: await this.config.signer.generatePublicKey(),
|
|
340
310
|
})));
|
|
341
|
-
const { transfer, signatureMap } = await this.transferService.sendTransferSignRefund(leafKeyTweaks, await this.config.signer.getSspIdentityPublicKey(this.config.getNetwork()), new Date(Date.now() +
|
|
311
|
+
const { transfer, signatureMap } = await this.transferService.sendTransferSignRefund(leafKeyTweaks, await this.config.signer.getSspIdentityPublicKey(this.config.getNetwork()), new Date(Date.now() + 2 * 60 * 1000));
|
|
342
312
|
try {
|
|
343
313
|
if (!transfer.leaves[0]?.leaf) {
|
|
344
314
|
throw new Error("Failed to get leaf");
|
|
@@ -445,7 +415,7 @@ export class SparkWallet {
|
|
|
445
415
|
* @param {number} [offset=0] - Offset for pagination
|
|
446
416
|
* @returns {Promise<QueryAllTransfersResponse>} Response containing the list of transfers
|
|
447
417
|
*/
|
|
448
|
-
async
|
|
418
|
+
async getTransfers(limit = 20, offset = 0) {
|
|
449
419
|
return await this.transferService.queryAllTransfers(limit, offset);
|
|
450
420
|
}
|
|
451
421
|
/**
|
|
@@ -518,6 +488,23 @@ export class SparkWallet {
|
|
|
518
488
|
});
|
|
519
489
|
return await this.transferDepositToSelf(response.nodes, signingPubKey);
|
|
520
490
|
}
|
|
491
|
+
/**
|
|
492
|
+
* Gets all unused deposit addresses for the wallet.
|
|
493
|
+
*
|
|
494
|
+
* @returns {Promise<string[]>} The unused deposit addresses
|
|
495
|
+
*/
|
|
496
|
+
async getUnusedDepositAddresses() {
|
|
497
|
+
const sparkClient = await this.connectionManager.createSparkClient(this.config.getCoordinatorAddress());
|
|
498
|
+
return (await sparkClient.query_unused_deposit_addresses({
|
|
499
|
+
identityPublicKey: await this.config.signer.getIdentityPublicKey(),
|
|
500
|
+
})).depositAddresses.map((addr) => addr.depositAddress);
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Claims a deposit to the wallet.
|
|
504
|
+
*
|
|
505
|
+
* @param {string} txid - The transaction ID of the deposit
|
|
506
|
+
* @returns {Promise<TreeNode[] | undefined>} The nodes resulting from the deposit
|
|
507
|
+
*/
|
|
521
508
|
async claimDeposit(txid) {
|
|
522
509
|
const baseUrl = this.config.getNetwork() === Network.REGTEST
|
|
523
510
|
? "https://regtest-mempool.dev.dev.sparkinfra.net/api"
|
|
@@ -567,47 +554,6 @@ export class SparkWallet {
|
|
|
567
554
|
});
|
|
568
555
|
return nodes;
|
|
569
556
|
}
|
|
570
|
-
/**
|
|
571
|
-
* Queries the mempool for transactions associated with an address.
|
|
572
|
-
*
|
|
573
|
-
* @param {string} address - The address to query
|
|
574
|
-
* @returns {Promise<{depositTx: Transaction, vout: number} | null>} Transaction details or null if none found
|
|
575
|
-
* @private
|
|
576
|
-
*/
|
|
577
|
-
async queryMempoolTxs(address) {
|
|
578
|
-
const network = getNetworkFromAddress(address) || this.config.getNetwork();
|
|
579
|
-
const baseUrl = network === BitcoinNetwork.REGTEST
|
|
580
|
-
? "https://regtest-mempool.dev.dev.sparkinfra.net/api"
|
|
581
|
-
: "https://mempool.space/docs/api";
|
|
582
|
-
const auth = btoa("spark-sdk:mCMk1JqlBNtetUNy");
|
|
583
|
-
const headers = {
|
|
584
|
-
"Content-Type": "application/json",
|
|
585
|
-
};
|
|
586
|
-
if (network === BitcoinNetwork.REGTEST) {
|
|
587
|
-
headers["Authorization"] = `Basic ${auth}`;
|
|
588
|
-
}
|
|
589
|
-
const response = await fetch(`${baseUrl}/address/${address}/txs`, {
|
|
590
|
-
headers,
|
|
591
|
-
});
|
|
592
|
-
const addressTxs = await response.json();
|
|
593
|
-
if (addressTxs && addressTxs.length > 0) {
|
|
594
|
-
const latestTx = addressTxs[0];
|
|
595
|
-
const outputIndex = latestTx.vout.findIndex((output) => output.scriptpubkey_address === address);
|
|
596
|
-
if (outputIndex === -1) {
|
|
597
|
-
return null;
|
|
598
|
-
}
|
|
599
|
-
const txResponse = await fetch(`${baseUrl}/tx/${latestTx.txid}/hex`, {
|
|
600
|
-
headers,
|
|
601
|
-
});
|
|
602
|
-
const txHex = await txResponse.text();
|
|
603
|
-
const depositTx = getTxFromRawTxHex(txHex);
|
|
604
|
-
return {
|
|
605
|
-
depositTx,
|
|
606
|
-
vout: outputIndex,
|
|
607
|
-
};
|
|
608
|
-
}
|
|
609
|
-
return null;
|
|
610
|
-
}
|
|
611
557
|
/**
|
|
612
558
|
* Transfers deposit to self to claim ownership.
|
|
613
559
|
*
|
|
@@ -622,7 +568,7 @@ export class SparkWallet {
|
|
|
622
568
|
signingPubKey,
|
|
623
569
|
newSigningPubKey: await this.config.signer.generatePublicKey(),
|
|
624
570
|
})));
|
|
625
|
-
await this.transferService.sendTransfer(leafKeyTweaks, await this.config.signer.getIdentityPublicKey()
|
|
571
|
+
await this.transferService.sendTransfer(leafKeyTweaks, await this.config.signer.getIdentityPublicKey());
|
|
626
572
|
const pendingTransfers = await this.transferService.queryPendingTransfers();
|
|
627
573
|
if (pendingTransfers.transfers.length > 0) {
|
|
628
574
|
// @ts-ignore - We check the length, so the first element is guaranteed to exist
|
|
@@ -634,55 +580,32 @@ export class SparkWallet {
|
|
|
634
580
|
/**
|
|
635
581
|
* Sends a transfer to another Spark user.
|
|
636
582
|
*
|
|
637
|
-
* @param {
|
|
583
|
+
* @param {TransferParams} params - Parameters for the transfer
|
|
638
584
|
* @param {string} params.receiverSparkAddress - The recipient's Spark address
|
|
639
585
|
* @param {number} params.amountSats - Amount to send in satoshis
|
|
640
586
|
* @returns {Promise<Transfer>} The completed transfer details
|
|
641
587
|
*/
|
|
642
|
-
async
|
|
588
|
+
async transfer({ amountSats, receiverSparkAddress }) {
|
|
643
589
|
return await this.withLeaves(async () => {
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
590
|
+
const leavesToSend = await this.selectLeaves(amountSats);
|
|
591
|
+
await this.refreshTimelockNodes();
|
|
592
|
+
const leafKeyTweaks = await Promise.all(leavesToSend.map(async (leaf) => ({
|
|
593
|
+
leaf,
|
|
594
|
+
signingPubKey: await this.config.signer.generatePublicKey(sha256(leaf.id)),
|
|
595
|
+
newSigningPubKey: await this.config.signer.generatePublicKey(),
|
|
596
|
+
})));
|
|
597
|
+
const transfer = await this.transferService.sendTransfer(leafKeyTweaks, hexToBytes(receiverSparkAddress));
|
|
598
|
+
const leavesToRemove = new Set(leavesToSend.map((leaf) => leaf.id));
|
|
599
|
+
this.leaves = this.leaves.filter((leaf) => !leavesToRemove.has(leaf.id));
|
|
600
|
+
return transfer;
|
|
648
601
|
});
|
|
649
602
|
}
|
|
650
|
-
/**
|
|
651
|
-
* Internal method to send a transfer.
|
|
652
|
-
*
|
|
653
|
-
* @param {SendTransferParams} params - Parameters for the transfer
|
|
654
|
-
* @returns {Promise<Transfer>} The completed transfer details
|
|
655
|
-
* @private
|
|
656
|
-
*/
|
|
657
|
-
async _sendTransfer({ amount, receiverPubKey, leaves, expiryTime = new Date(Date.now() + 10 * 60 * 1000), }) {
|
|
658
|
-
let leavesToSend = [];
|
|
659
|
-
if (leaves) {
|
|
660
|
-
leavesToSend = leaves.map((leaf) => ({
|
|
661
|
-
...leaf,
|
|
662
|
-
}));
|
|
663
|
-
}
|
|
664
|
-
else if (amount) {
|
|
665
|
-
leavesToSend = await this.selectLeaves(amount);
|
|
666
|
-
}
|
|
667
|
-
else {
|
|
668
|
-
throw new Error("Must provide amount or leaves");
|
|
669
|
-
}
|
|
670
|
-
await this.refreshTimelockNodes();
|
|
671
|
-
const leafKeyTweaks = await Promise.all(leavesToSend.map(async (leaf) => ({
|
|
672
|
-
leaf,
|
|
673
|
-
signingPubKey: await this.config.signer.generatePublicKey(sha256(leaf.id)),
|
|
674
|
-
newSigningPubKey: await this.config.signer.generatePublicKey(),
|
|
675
|
-
})));
|
|
676
|
-
const transfer = await this.transferService.sendTransfer(leafKeyTweaks, hexToBytes(receiverPubKey), expiryTime);
|
|
677
|
-
const leavesToRemove = new Set(leavesToSend.map((leaf) => leaf.id));
|
|
678
|
-
this.leaves = this.leaves.filter((leaf) => !leavesToRemove.has(leaf.id));
|
|
679
|
-
return transfer;
|
|
680
|
-
}
|
|
681
603
|
/**
|
|
682
604
|
* Internal method to refresh timelock nodes.
|
|
683
605
|
*
|
|
684
606
|
* @param {string} nodeId - The optional ID of the node to refresh. If not provided, all nodes will be checked.
|
|
685
607
|
* @returns {Promise<void>}
|
|
608
|
+
* @private
|
|
686
609
|
*/
|
|
687
610
|
async refreshTimelockNodes(nodeId) {
|
|
688
611
|
const nodesToRefresh = [];
|
|
@@ -747,12 +670,19 @@ export class SparkWallet {
|
|
|
747
670
|
this.leaves.push(newNode);
|
|
748
671
|
}
|
|
749
672
|
}
|
|
673
|
+
/**
|
|
674
|
+
* Gets all pending transfers.
|
|
675
|
+
*
|
|
676
|
+
* @returns {Promise<Transfer[]>} The pending transfers
|
|
677
|
+
*/
|
|
678
|
+
async getPendingTransfers() {
|
|
679
|
+
return (await this.transferService.queryPendingTransfers()).transfers;
|
|
680
|
+
}
|
|
750
681
|
/**
|
|
751
682
|
* Claims a specific transfer.
|
|
752
683
|
*
|
|
753
684
|
* @param {Transfer} transfer - The transfer to claim
|
|
754
685
|
* @returns {Promise<Object>} The claim result
|
|
755
|
-
* @private
|
|
756
686
|
*/
|
|
757
687
|
async claimTransfer(transfer) {
|
|
758
688
|
return await this.claimTransferMutex.runExclusive(async () => {
|
|
@@ -780,7 +710,6 @@ export class SparkWallet {
|
|
|
780
710
|
* Claims all pending transfers.
|
|
781
711
|
*
|
|
782
712
|
* @returns {Promise<boolean>} True if any transfers were claimed
|
|
783
|
-
* @private
|
|
784
713
|
*/
|
|
785
714
|
async claimTransfers() {
|
|
786
715
|
const transfers = await this.transferService.queryPendingTransfers();
|
|
@@ -805,10 +734,12 @@ export class SparkWallet {
|
|
|
805
734
|
* @private
|
|
806
735
|
*/
|
|
807
736
|
async cancelAllSenderInitiatedTransfers() {
|
|
808
|
-
const
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
737
|
+
for (const operator of Object.values(this.config.getSigningOperators())) {
|
|
738
|
+
const transfers = await this.transferService.queryPendingTransfersBySender(operator.address);
|
|
739
|
+
for (const transfer of transfers.transfers) {
|
|
740
|
+
if (transfer.status === TransferStatus.TRANSFER_STATUS_SENDER_INITIATED) {
|
|
741
|
+
await this.transferService.cancelSendTransfer(transfer, operator.address);
|
|
742
|
+
}
|
|
812
743
|
}
|
|
813
744
|
}
|
|
814
745
|
}
|
|
@@ -908,7 +839,6 @@ export class SparkWallet {
|
|
|
908
839
|
*
|
|
909
840
|
* @param {LightningReceiveFeeEstimateInput} params - Input parameters for fee estimation
|
|
910
841
|
* @returns {Promise<LightningReceiveFeeEstimateOutput | null>} Fee estimate for receiving Lightning payments
|
|
911
|
-
* @private
|
|
912
842
|
*/
|
|
913
843
|
async getLightningReceiveFeeEstimate({ amountSats, network, }) {
|
|
914
844
|
if (!this.sspClient) {
|
|
@@ -921,7 +851,6 @@ export class SparkWallet {
|
|
|
921
851
|
*
|
|
922
852
|
* @param {LightningSendFeeEstimateInput} params - Input parameters for fee estimation
|
|
923
853
|
* @returns {Promise<LightningSendFeeEstimateOutput | null>} Fee estimate for sending Lightning payments
|
|
924
|
-
* @private
|
|
925
854
|
*/
|
|
926
855
|
async getLightningSendFeeEstimate({ encodedInvoice, }) {
|
|
927
856
|
if (!this.sspClient) {
|
|
@@ -1032,7 +961,6 @@ export class SparkWallet {
|
|
|
1032
961
|
*
|
|
1033
962
|
* @param {CoopExitFeeEstimateInput} params - Input parameters for fee estimation
|
|
1034
963
|
* @returns {Promise<CoopExitFeeEstimateOutput | null>} Fee estimate for the withdrawal
|
|
1035
|
-
* @private
|
|
1036
964
|
*/
|
|
1037
965
|
async getCoopExitFeeEstimate({ leafExternalIds, withdrawalAddress, }) {
|
|
1038
966
|
if (!this.sspClient) {
|