@buildonspark/spark-sdk 0.2.4 → 0.2.6
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/CHANGELOG.md +22 -0
- package/dist/{chunk-3SEOTO43.js → chunk-3SPMJMUX.js} +3 -2
- package/dist/chunk-AVI5E5VT.js +66 -0
- package/dist/{chunk-WAQKYSDI.js → chunk-CQY5ML2A.js} +3 -2
- package/dist/{chunk-W4ZRBSWM.js → chunk-GUZ3WCB4.js} +466 -167
- package/dist/{client-KhNkrXz4.d.cts → client-CusuvuCe.d.cts} +199 -104
- package/dist/{client-BF4cn8F4.d.ts → client-Dn4Ld8pD.d.ts} +199 -104
- package/dist/debug.cjs +662 -336
- package/dist/debug.d.cts +9 -7
- package/dist/debug.d.ts +9 -7
- package/dist/debug.js +3 -3
- package/dist/graphql/objects/index.d.cts +6 -51
- package/dist/graphql/objects/index.d.ts +6 -51
- package/dist/graphql/objects/index.js +1 -1
- package/dist/index.cjs +713 -327
- package/dist/index.d.cts +19 -188
- package/dist/index.d.ts +19 -188
- package/dist/index.js +15 -8
- package/dist/index.node.cjs +638 -352
- package/dist/index.node.d.cts +7 -7
- package/dist/index.node.d.ts +7 -7
- package/dist/index.node.js +59 -100
- package/dist/native/index.cjs +655 -325
- package/dist/native/index.d.cts +253 -164
- package/dist/native/index.d.ts +253 -164
- package/dist/native/index.js +505 -172
- package/dist/proto/lrc20.d.cts +1 -1
- package/dist/proto/lrc20.d.ts +1 -1
- package/dist/proto/spark.d.cts +1 -1
- package/dist/proto/spark.d.ts +1 -1
- package/dist/proto/spark_token.d.cts +1 -1
- package/dist/proto/spark_token.d.ts +1 -1
- package/dist/{spark-B_7nZx6T.d.cts → spark-Cj4brrP5.d.cts} +1 -1
- package/dist/{spark-B_7nZx6T.d.ts → spark-Cj4brrP5.d.ts} +1 -1
- package/dist/{spark-wallet-C1Tr_VKI.d.ts → spark-wallet-B6YthxDI.d.ts} +61 -26
- package/dist/{spark-wallet-DG3x2obf.d.cts → spark-wallet-BbOf2P2l.d.cts} +61 -26
- package/dist/spark-wallet.node-BBk1sGS2.d.cts +12 -0
- package/dist/spark-wallet.node-Bffethig.d.ts +12 -0
- package/dist/tests/test-utils.cjs +86 -54
- package/dist/tests/test-utils.d.cts +24 -24
- package/dist/tests/test-utils.d.ts +24 -24
- package/dist/tests/test-utils.js +4 -4
- package/dist/token-transactions-0_5XMWjs.d.ts +184 -0
- package/dist/token-transactions-CD-Adb5y.d.cts +184 -0
- package/dist/types/index.cjs +3 -2
- package/dist/types/index.d.cts +3 -4
- package/dist/types/index.d.ts +3 -4
- package/dist/types/index.js +2 -2
- package/dist/{xchain-address-HBr6isnc.d.cts → xchain-address-BnKZ0-dY.d.cts} +6 -5
- package/dist/{xchain-address-BHu6CpZC.d.ts → xchain-address-Di3lu4Wy.d.ts} +6 -5
- package/package.json +7 -2
- package/src/graphql/client.ts +49 -8
- package/src/graphql/objects/SparkWalletUser.ts +1 -1
- package/src/graphql/queries/Transfers.ts +15 -0
- package/src/index.node.ts +5 -1
- package/src/index.ts +4 -1
- package/src/services/config.ts +13 -2
- package/src/services/token-transactions.ts +22 -8
- package/src/services/wallet-config.ts +22 -13
- package/src/spark-wallet/spark-wallet.browser.ts +72 -0
- package/src/spark-wallet/spark-wallet.node.ts +60 -118
- package/src/spark-wallet/spark-wallet.ts +400 -156
- package/src/tests/integration/ssp/coop-exit-validation.test.ts +233 -0
- package/src/tests/integration/ssp/coop-exit.test.ts +112 -93
- package/src/tests/integration/ssp/static-deposit-validation.test.ts +145 -0
- package/src/tests/integration/ssp/static_deposit.test.ts +453 -64
- package/src/tests/integration/ssp/transfers.test.ts +102 -0
- package/src/tests/integration/static_deposit.test.ts +92 -0
- package/src/tests/integration/transfer.test.ts +1 -1
- package/src/tests/utils/regtest-test-faucet.ts +8 -0
- package/src/tests/utils/spark-testing-wallet.ts +42 -0
- package/src/tests/utils/test-faucet.ts +6 -2
- package/src/types/sdk-types.ts +15 -0
- package/src/utils/bitcoin.ts +13 -0
- package/src/utils/token-identifier.ts +47 -4
- package/src/utils/token-transactions.ts +13 -9
- package/dist/chunk-TVUMSHWA.js +0 -7
- package/dist/sdk-types-CB9HrW5O.d.cts +0 -44
- package/dist/sdk-types-CkRNraXT.d.ts +0 -44
- package/dist/spark-wallet.node-CGxoeCpH.d.ts +0 -13
- package/dist/spark-wallet.node-CN9LoB_O.d.cts +0 -13
- package/src/graphql/queries/Transfer.ts +0 -10
|
@@ -1,93 +1,482 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
SparkWalletTesting,
|
|
3
|
+
initWallet,
|
|
4
|
+
} from "../../utils/spark-testing-wallet.js";
|
|
5
|
+
import { bytesToHex } from "@noble/hashes/utils";
|
|
3
6
|
import { BitcoinFaucet } from "../../utils/test-faucet.js";
|
|
7
|
+
import { ValidationError } from "../../../errors/types.js";
|
|
4
8
|
|
|
5
|
-
const
|
|
9
|
+
const SMALL_DEPOSIT_AMOUNT = 10n;
|
|
10
|
+
export const DEPOSIT_AMOUNT = 10000n;
|
|
6
11
|
const SECOND_DEPOSIT_AMOUNT = 20000n;
|
|
12
|
+
const THIRD_DEPOSIT_AMOUNT = 30000n;
|
|
7
13
|
|
|
8
14
|
describe("SSP static deposit address integration", () => {
|
|
9
|
-
|
|
10
|
-
|
|
15
|
+
describe("Happy path testing", () => {
|
|
16
|
+
it("should claim deposits to a static deposit address", async () => {
|
|
17
|
+
const faucet = BitcoinFaucet.getInstance();
|
|
18
|
+
const { wallet: userWallet } = await SparkWalletTesting.initialize(
|
|
19
|
+
{
|
|
20
|
+
options: {
|
|
21
|
+
network: "LOCAL",
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
false,
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const depositAddress = await userWallet.getStaticDepositAddress();
|
|
28
|
+
expect(depositAddress).toBeDefined();
|
|
29
|
+
const signedTx = await faucet.sendToAddress(
|
|
30
|
+
depositAddress,
|
|
31
|
+
DEPOSIT_AMOUNT,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// Wait for the transaction to be mined
|
|
35
|
+
await faucet.mineBlocks(6);
|
|
36
|
+
expect(signedTx).toBeDefined();
|
|
37
|
+
const transactionId = signedTx.id;
|
|
38
|
+
let vout;
|
|
39
|
+
for (let i = 0; i < signedTx.outputsLength; i++) {
|
|
40
|
+
const output = signedTx.getOutput(i);
|
|
41
|
+
if (output.amount === DEPOSIT_AMOUNT) {
|
|
42
|
+
vout = i;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const quote = await userWallet.getClaimStaticDepositQuote(
|
|
48
|
+
transactionId,
|
|
49
|
+
vout!,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
53
|
+
|
|
54
|
+
const quoteAmount = quote!.creditAmountSats;
|
|
55
|
+
const sspSignature = quote!.signature;
|
|
56
|
+
|
|
57
|
+
await userWallet.claimStaticDeposit({
|
|
58
|
+
transactionId,
|
|
59
|
+
creditAmountSats: quoteAmount,
|
|
60
|
+
sspSignature,
|
|
61
|
+
outputIndex: vout!,
|
|
62
|
+
});
|
|
63
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
64
|
+
const { balance } = await userWallet.getBalance();
|
|
65
|
+
expect(balance).toBe(BigInt(quoteAmount));
|
|
66
|
+
|
|
67
|
+
// Test depositing money to the same address and second time and claiming.
|
|
68
|
+
const signedTx2 = await faucet.sendToAddress(
|
|
69
|
+
depositAddress,
|
|
70
|
+
SECOND_DEPOSIT_AMOUNT,
|
|
71
|
+
);
|
|
72
|
+
const transactionId2 = signedTx2.id;
|
|
73
|
+
// Wait for the transaction to be mined
|
|
74
|
+
await faucet.mineBlocks(6);
|
|
75
|
+
// Test claiming and getting the quote without passing in the output index.
|
|
76
|
+
const quote2 =
|
|
77
|
+
await userWallet.getClaimStaticDepositQuote(transactionId2);
|
|
78
|
+
const quoteAmount2 = quote2!.creditAmountSats;
|
|
79
|
+
const sspSignature2 = quote2!.signature;
|
|
80
|
+
await userWallet.claimStaticDeposit({
|
|
81
|
+
transactionId: transactionId2,
|
|
82
|
+
creditAmountSats: quoteAmount2,
|
|
83
|
+
sspSignature: sspSignature2,
|
|
84
|
+
});
|
|
85
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
86
|
+
const { balance: balance2 } = await userWallet.getBalance();
|
|
87
|
+
expect(balance2).toBe(BigInt(quoteAmount + quoteAmount2));
|
|
88
|
+
|
|
89
|
+
// Test depositing money to the same address and test claim with max fee flow.
|
|
90
|
+
const signedTx3 = await faucet.sendToAddress(
|
|
91
|
+
depositAddress,
|
|
92
|
+
THIRD_DEPOSIT_AMOUNT,
|
|
93
|
+
);
|
|
94
|
+
const transactionId3 = signedTx3.id;
|
|
95
|
+
// Wait for the transaction to be mined
|
|
96
|
+
await faucet.mineBlocks(6);
|
|
97
|
+
// Get quote so we can calculate the expected balance. Not needed for actual flow.
|
|
98
|
+
const quote3 =
|
|
99
|
+
await userWallet.getClaimStaticDepositQuote(transactionId3);
|
|
100
|
+
const quoteAmount3 = quote3!.creditAmountSats;
|
|
101
|
+
await userWallet.claimStaticDepositWithMaxFee({
|
|
102
|
+
transactionId: transactionId3,
|
|
103
|
+
maxFee: 1000,
|
|
104
|
+
});
|
|
105
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
106
|
+
const { balance: balance3 } = await userWallet.getBalance();
|
|
107
|
+
expect(balance3).toBe(BigInt(quoteAmount + quoteAmount2 + quoteAmount3));
|
|
108
|
+
// Get transfers should include static deposit transfers.
|
|
109
|
+
const transfers = await userWallet.getTransfers();
|
|
110
|
+
expect(transfers.transfers.length).toBe(3);
|
|
111
|
+
}, 60000);
|
|
11
112
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
113
|
+
it("should create a refund transaction", async () => {
|
|
114
|
+
const faucet = BitcoinFaucet.getInstance();
|
|
115
|
+
|
|
116
|
+
const { wallet: userWallet } = await SparkWalletTesting.initialize(
|
|
117
|
+
{
|
|
118
|
+
options: {
|
|
119
|
+
network: "LOCAL",
|
|
120
|
+
},
|
|
16
121
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
);
|
|
122
|
+
false,
|
|
123
|
+
);
|
|
20
124
|
|
|
21
|
-
|
|
22
|
-
|
|
125
|
+
const depositAddress = await userWallet.getStaticDepositAddress();
|
|
126
|
+
expect(depositAddress).toBeDefined();
|
|
23
127
|
|
|
24
|
-
|
|
128
|
+
const signedTx = await faucet.sendToAddress(
|
|
129
|
+
depositAddress,
|
|
130
|
+
DEPOSIT_AMOUNT,
|
|
131
|
+
);
|
|
25
132
|
|
|
26
|
-
|
|
27
|
-
|
|
133
|
+
// Wait for the transaction to be mined
|
|
134
|
+
await faucet.mineBlocks(6);
|
|
28
135
|
|
|
29
|
-
|
|
136
|
+
expect(signedTx).toBeDefined();
|
|
30
137
|
|
|
31
|
-
|
|
138
|
+
const transactionId = signedTx.id;
|
|
32
139
|
|
|
33
|
-
|
|
140
|
+
let vout: number | undefined;
|
|
34
141
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
142
|
+
for (let i = 0; i < signedTx.outputsLength; i++) {
|
|
143
|
+
const output = signedTx.getOutput(i);
|
|
144
|
+
if (output.amount === DEPOSIT_AMOUNT) {
|
|
145
|
+
vout = i;
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
40
148
|
}
|
|
41
|
-
}
|
|
42
149
|
|
|
43
|
-
|
|
44
|
-
transactionId,
|
|
45
|
-
vout!,
|
|
46
|
-
);
|
|
150
|
+
const refundAddress = await faucet.getNewAddress();
|
|
47
151
|
|
|
48
|
-
|
|
49
|
-
|
|
152
|
+
const refundTx = await userWallet.refundStaticDeposit({
|
|
153
|
+
depositTransactionId: transactionId,
|
|
154
|
+
destinationAddress: refundAddress,
|
|
155
|
+
satsPerVbyteFee: 2,
|
|
156
|
+
});
|
|
50
157
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
158
|
+
expect(refundTx).toBeDefined();
|
|
159
|
+
|
|
160
|
+
// Calling it again should create a new transaction.
|
|
161
|
+
const refundTx2 = await userWallet.refundStaticDeposit({
|
|
162
|
+
depositTransactionId: transactionId,
|
|
163
|
+
destinationAddress: refundAddress,
|
|
164
|
+
outputIndex: vout!,
|
|
165
|
+
satsPerVbyteFee: 2,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
expect(refundTx2).toBeDefined();
|
|
169
|
+
|
|
170
|
+
expect(refundTx).not.toBe(refundTx2);
|
|
171
|
+
}, 60000);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe("Quote unhappy path testing", () => {
|
|
175
|
+
it("should error claim quote from a different wallet", async () => {
|
|
176
|
+
const { wallet: aliceWallet } = await SparkWalletTesting.initialize(
|
|
177
|
+
{
|
|
178
|
+
options: {
|
|
179
|
+
network: "LOCAL",
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
false,
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const { wallet: bobWallet } = await SparkWalletTesting.initialize(
|
|
186
|
+
{
|
|
187
|
+
options: {
|
|
188
|
+
network: "LOCAL",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
false,
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const faucet = BitcoinFaucet.getInstance();
|
|
57
195
|
|
|
58
|
-
|
|
196
|
+
const depositAddress = await aliceWallet.getStaticDepositAddress();
|
|
197
|
+
expect(depositAddress).toBeDefined();
|
|
59
198
|
|
|
60
|
-
|
|
61
|
-
|
|
199
|
+
const signedTx = await faucet.sendToAddress(
|
|
200
|
+
depositAddress,
|
|
201
|
+
DEPOSIT_AMOUNT,
|
|
202
|
+
);
|
|
62
203
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
depositAddress,
|
|
66
|
-
SECOND_DEPOSIT_AMOUNT,
|
|
67
|
-
);
|
|
68
|
-
const transactionId2 = signedTx2.id;
|
|
69
|
-
// Wait for the transaction to be mined
|
|
70
|
-
await faucet.mineBlocks(6);
|
|
204
|
+
// Wait for the transaction to be mined
|
|
205
|
+
await faucet.mineBlocks(6);
|
|
71
206
|
|
|
72
|
-
|
|
73
|
-
const quote2 = await userWallet.getClaimStaticDepositQuote(transactionId2);
|
|
207
|
+
expect(signedTx).toBeDefined();
|
|
74
208
|
|
|
75
|
-
|
|
76
|
-
const sspSignature2 = quote2!.signature;
|
|
209
|
+
const transactionId = signedTx.id;
|
|
77
210
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
211
|
+
await expect(
|
|
212
|
+
bobWallet.getClaimStaticDepositQuote(transactionId),
|
|
213
|
+
).rejects.toThrow();
|
|
214
|
+
}, 60000);
|
|
215
|
+
|
|
216
|
+
it("should error if txid does not exist", async () => {
|
|
217
|
+
const { wallet: aliceWallet } = await SparkWalletTesting.initialize(
|
|
218
|
+
{
|
|
219
|
+
options: {
|
|
220
|
+
network: "LOCAL",
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
false,
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const faucet = BitcoinFaucet.getInstance();
|
|
227
|
+
|
|
228
|
+
const depositAddress = await aliceWallet.getStaticDepositAddress();
|
|
229
|
+
expect(depositAddress).toBeDefined();
|
|
230
|
+
|
|
231
|
+
const signedTx = await faucet.sendToAddress(
|
|
232
|
+
depositAddress,
|
|
233
|
+
DEPOSIT_AMOUNT,
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
// Wait for the transaction to be mined
|
|
237
|
+
await faucet.mineBlocks(6);
|
|
238
|
+
|
|
239
|
+
expect(signedTx).toBeDefined();
|
|
240
|
+
|
|
241
|
+
const transactionId = signedTx.id;
|
|
242
|
+
|
|
243
|
+
await expect(
|
|
244
|
+
aliceWallet.getClaimStaticDepositQuote(
|
|
245
|
+
`${transactionId.slice(0, -6)}abcdef`,
|
|
246
|
+
),
|
|
247
|
+
).rejects.toThrow();
|
|
82
248
|
});
|
|
83
249
|
|
|
84
|
-
|
|
250
|
+
it("should error if tx amount does not cover fees", async () => {
|
|
251
|
+
const { wallet: aliceWallet } = await SparkWalletTesting.initialize(
|
|
252
|
+
{
|
|
253
|
+
options: {
|
|
254
|
+
network: "LOCAL",
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
false,
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
const faucet = BitcoinFaucet.getInstance();
|
|
261
|
+
|
|
262
|
+
const depositAddress = await aliceWallet.getStaticDepositAddress();
|
|
263
|
+
expect(depositAddress).toBeDefined();
|
|
264
|
+
|
|
265
|
+
const signedTx = await faucet.sendToAddress(
|
|
266
|
+
depositAddress,
|
|
267
|
+
SMALL_DEPOSIT_AMOUNT,
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
// Wait for the transaction to be mined
|
|
271
|
+
await faucet.mineBlocks(6);
|
|
272
|
+
|
|
273
|
+
expect(signedTx).toBeDefined();
|
|
274
|
+
|
|
275
|
+
const transactionId = signedTx.id;
|
|
276
|
+
|
|
277
|
+
await expect(
|
|
278
|
+
aliceWallet.getClaimStaticDepositQuote(transactionId),
|
|
279
|
+
).rejects.toThrow();
|
|
280
|
+
}, 60000);
|
|
281
|
+
|
|
282
|
+
it("should error claim quote if tx already claimed", async () => {
|
|
283
|
+
const { wallet: aliceWallet } = await SparkWalletTesting.initialize(
|
|
284
|
+
{
|
|
285
|
+
options: {
|
|
286
|
+
network: "LOCAL",
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
false,
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const faucet = BitcoinFaucet.getInstance();
|
|
293
|
+
|
|
294
|
+
const depositAddress = await aliceWallet.getStaticDepositAddress();
|
|
295
|
+
expect(depositAddress).toBeDefined();
|
|
296
|
+
|
|
297
|
+
const signedTx = await faucet.sendToAddress(
|
|
298
|
+
depositAddress,
|
|
299
|
+
DEPOSIT_AMOUNT,
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
// Wait for the transaction to be mined
|
|
303
|
+
await faucet.mineBlocks(6);
|
|
304
|
+
|
|
305
|
+
expect(signedTx).toBeDefined();
|
|
306
|
+
|
|
307
|
+
const transactionId = signedTx.id;
|
|
308
|
+
|
|
309
|
+
const quote = await aliceWallet.getClaimStaticDepositQuote(transactionId);
|
|
310
|
+
|
|
311
|
+
await aliceWallet.claimStaticDeposit({
|
|
312
|
+
transactionId: transactionId,
|
|
313
|
+
creditAmountSats: quote.creditAmountSats,
|
|
314
|
+
sspSignature: quote.signature,
|
|
315
|
+
});
|
|
316
|
+
await new Promise((resolve) => setTimeout(resolve, 40000));
|
|
317
|
+
|
|
318
|
+
const { balance } = await aliceWallet.getBalance();
|
|
319
|
+
|
|
320
|
+
expect(balance).toBe(BigInt(quote.creditAmountSats));
|
|
321
|
+
|
|
322
|
+
await expect(
|
|
323
|
+
aliceWallet.getClaimStaticDepositQuote(transactionId),
|
|
324
|
+
).rejects.toThrow();
|
|
325
|
+
}, 60000);
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
describe("Claim unhappy path testing", () => {
|
|
329
|
+
it("should reject claim with fake SSP signature", async () => {
|
|
330
|
+
console.log("Initializing wallet for fake SSP signature test...");
|
|
331
|
+
const {
|
|
332
|
+
wallet: userWallet,
|
|
333
|
+
signedTx,
|
|
334
|
+
vout,
|
|
335
|
+
faucet,
|
|
336
|
+
} = await initWallet(DEPOSIT_AMOUNT, "LOCAL");
|
|
337
|
+
|
|
338
|
+
// Wait for the transaction to be mined
|
|
339
|
+
await faucet.mineBlocks(6);
|
|
340
|
+
|
|
341
|
+
const transactionId = signedTx.id;
|
|
342
|
+
|
|
343
|
+
console.log("Fetching claim quote for static deposit...");
|
|
344
|
+
const quote = await userWallet.getClaimStaticDepositQuote(
|
|
345
|
+
transactionId,
|
|
346
|
+
vout!,
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
await new Promise((resolve) => setTimeout(resolve, 10000));
|
|
350
|
+
|
|
351
|
+
const quoteAmount = quote!.creditAmountSats;
|
|
352
|
+
|
|
353
|
+
// Generate a fake signature (64 bytes of random data to simulate a signature)
|
|
354
|
+
const fakeSignature = new Uint8Array(64);
|
|
355
|
+
crypto.getRandomValues(fakeSignature);
|
|
356
|
+
console.log("Expecting error when claiming with fake signature...");
|
|
357
|
+
await expect(
|
|
358
|
+
userWallet.claimStaticDeposit({
|
|
359
|
+
transactionId,
|
|
360
|
+
creditAmountSats: quoteAmount,
|
|
361
|
+
sspSignature: bytesToHex(fakeSignature),
|
|
362
|
+
outputIndex: vout!,
|
|
363
|
+
}),
|
|
364
|
+
).rejects.toThrow(
|
|
365
|
+
'Request ClaimStaticDeposit failed. [{"message":"Something went wrong."',
|
|
366
|
+
);
|
|
367
|
+
}, 600000);
|
|
368
|
+
|
|
369
|
+
it("should reject claiming the same deposit twice", async () => {
|
|
370
|
+
console.log("Initializing wallet for double-claim test...");
|
|
371
|
+
const {
|
|
372
|
+
wallet: userWallet,
|
|
373
|
+
signedTx,
|
|
374
|
+
vout,
|
|
375
|
+
faucet,
|
|
376
|
+
} = await initWallet(DEPOSIT_AMOUNT, "LOCAL");
|
|
377
|
+
|
|
378
|
+
// Wait for the transaction to be mined
|
|
379
|
+
await faucet.mineBlocks(6);
|
|
380
|
+
|
|
381
|
+
const transactionId = signedTx.id;
|
|
382
|
+
|
|
383
|
+
console.log("Fetching claim quote for static deposit...");
|
|
384
|
+
const quote = await userWallet.getClaimStaticDepositQuote(
|
|
385
|
+
transactionId,
|
|
386
|
+
vout!,
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
await new Promise((resolve) => setTimeout(resolve, 10000));
|
|
390
|
+
|
|
391
|
+
const quoteAmount = quote!.creditAmountSats;
|
|
392
|
+
const sspSignature = quote!.signature;
|
|
393
|
+
|
|
394
|
+
console.log("Attempting to claim static deposit for the first time...");
|
|
395
|
+
const outputs = await userWallet.claimStaticDeposit({
|
|
396
|
+
transactionId,
|
|
397
|
+
creditAmountSats: quoteAmount,
|
|
398
|
+
sspSignature,
|
|
399
|
+
outputIndex: vout!,
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
await new Promise((resolve) => setTimeout(resolve, 30000));
|
|
403
|
+
|
|
404
|
+
expect(outputs).toBeDefined();
|
|
405
|
+
|
|
406
|
+
console.log(
|
|
407
|
+
"Expecting error when attempting to claim the same deposit twice...",
|
|
408
|
+
);
|
|
409
|
+
await expect(
|
|
410
|
+
userWallet.claimStaticDeposit({
|
|
411
|
+
transactionId,
|
|
412
|
+
creditAmountSats: quoteAmount,
|
|
413
|
+
sspSignature,
|
|
414
|
+
outputIndex: vout!,
|
|
415
|
+
}),
|
|
416
|
+
).rejects.toThrow("UTXO is spent or not found.");
|
|
417
|
+
}, 600000);
|
|
418
|
+
|
|
419
|
+
it("Claim, then try to refund.", async () => {
|
|
420
|
+
console.log("Initializing wallet for claim and refund test...");
|
|
421
|
+
const {
|
|
422
|
+
wallet: userWallet,
|
|
423
|
+
depositAddress,
|
|
424
|
+
signedTx,
|
|
425
|
+
vout,
|
|
426
|
+
faucet,
|
|
427
|
+
} = await initWallet(DEPOSIT_AMOUNT, "LOCAL");
|
|
428
|
+
|
|
429
|
+
// Wait for the transaction to be mined
|
|
430
|
+
await faucet.mineBlocks(6);
|
|
431
|
+
|
|
432
|
+
expect(signedTx).toBeDefined();
|
|
433
|
+
|
|
434
|
+
const transactionId = signedTx.id;
|
|
435
|
+
|
|
436
|
+
const quote = await userWallet.getClaimStaticDepositQuote(
|
|
437
|
+
transactionId,
|
|
438
|
+
vout!,
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
const quoteAmount = quote!.creditAmountSats;
|
|
442
|
+
const sspSignature = quote!.signature;
|
|
443
|
+
|
|
444
|
+
console.log("Attempting to claim static deposit...");
|
|
445
|
+
await userWallet.claimStaticDeposit({
|
|
446
|
+
transactionId,
|
|
447
|
+
creditAmountSats: quoteAmount,
|
|
448
|
+
sspSignature,
|
|
449
|
+
outputIndex: vout!,
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
await new Promise((resolve) => setTimeout(resolve, 30000));
|
|
453
|
+
|
|
454
|
+
console.log("Fetching wallet balance after claim...");
|
|
455
|
+
const { balance } = await userWallet.getBalance();
|
|
456
|
+
expect(balance).toBe(BigInt(quoteAmount));
|
|
457
|
+
|
|
458
|
+
console.log(`Alice balance: ${balance}`);
|
|
459
|
+
|
|
460
|
+
console.log("Initiating transfer to Spark address...");
|
|
461
|
+
const sparkAddress = await userWallet.getSparkAddress();
|
|
462
|
+
const transfer = await userWallet.transfer({
|
|
463
|
+
amountSats: Number(balance),
|
|
464
|
+
receiverSparkAddress: sparkAddress,
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
expect(transfer).toBeDefined();
|
|
85
468
|
|
|
86
|
-
|
|
87
|
-
expect(balance2).toBe(BigInt(quoteAmount + quoteAmount2));
|
|
469
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
88
470
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
471
|
+
// Try to refund the deposit after claiming and transfer
|
|
472
|
+
console.log("Attempting refund of claimed deposit...");
|
|
473
|
+
await expect(
|
|
474
|
+
userWallet.refundStaticDeposit({
|
|
475
|
+
depositTransactionId: transactionId,
|
|
476
|
+
destinationAddress: depositAddress,
|
|
477
|
+
fee: 301,
|
|
478
|
+
}),
|
|
479
|
+
).rejects.toThrow();
|
|
480
|
+
}, 600000);
|
|
481
|
+
});
|
|
93
482
|
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, expect, it } from "@jest/globals";
|
|
2
|
+
import { TransferType, transferTypeToJSON } from "../../../proto/spark.js";
|
|
3
|
+
import { SparkWalletTesting } from "../../utils/spark-testing-wallet.js";
|
|
4
|
+
import { BitcoinFaucet } from "../../utils/test-faucet.js";
|
|
5
|
+
|
|
6
|
+
const DEPOSIT_AMOUNT = 10000n;
|
|
7
|
+
const SECOND_DEPOSIT_AMOUNT = 20000n;
|
|
8
|
+
|
|
9
|
+
describe("SSP Transfers Test", () => {
|
|
10
|
+
it("getTransfers and getTransfer should return the corresponding ssp request if it exists", async () => {
|
|
11
|
+
const faucet = BitcoinFaucet.getInstance();
|
|
12
|
+
|
|
13
|
+
const { wallet: userWallet } = await SparkWalletTesting.initialize(
|
|
14
|
+
{
|
|
15
|
+
options: {
|
|
16
|
+
network: "LOCAL",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
false,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const { wallet: userWallet2 } = await SparkWalletTesting.initialize(
|
|
23
|
+
{
|
|
24
|
+
options: {
|
|
25
|
+
network: "LOCAL",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
false,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const depositAddress = await userWallet.getStaticDepositAddress();
|
|
32
|
+
expect(depositAddress).toBeDefined();
|
|
33
|
+
|
|
34
|
+
const signedTx = await faucet.sendToAddress(depositAddress, DEPOSIT_AMOUNT);
|
|
35
|
+
|
|
36
|
+
// Wait for the transaction to be mined
|
|
37
|
+
await faucet.mineBlocks(6);
|
|
38
|
+
|
|
39
|
+
expect(signedTx).toBeDefined();
|
|
40
|
+
|
|
41
|
+
const transactionId = signedTx.id;
|
|
42
|
+
|
|
43
|
+
let vout;
|
|
44
|
+
|
|
45
|
+
for (let i = 0; i < signedTx.outputsLength; i++) {
|
|
46
|
+
const output = signedTx.getOutput(i);
|
|
47
|
+
if (output.amount === DEPOSIT_AMOUNT) {
|
|
48
|
+
vout = i;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const quote = await userWallet.getClaimStaticDepositQuote(
|
|
54
|
+
transactionId,
|
|
55
|
+
vout!,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const quoteAmount = quote!.creditAmountSats;
|
|
59
|
+
const sspSignature = quote!.signature;
|
|
60
|
+
|
|
61
|
+
await userWallet.claimStaticDeposit({
|
|
62
|
+
transactionId,
|
|
63
|
+
creditAmountSats: quoteAmount,
|
|
64
|
+
sspSignature,
|
|
65
|
+
outputIndex: vout!,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
69
|
+
|
|
70
|
+
const { balance } = await userWallet.getBalance();
|
|
71
|
+
expect(balance).toBe(BigInt(quoteAmount));
|
|
72
|
+
|
|
73
|
+
await userWallet.transfer({
|
|
74
|
+
amountSats: quoteAmount,
|
|
75
|
+
receiverSparkAddress: await userWallet2.getSparkAddress(),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const transfers = await userWallet.getTransfers();
|
|
79
|
+
expect(transfers.transfers.length).toBe(2);
|
|
80
|
+
|
|
81
|
+
const firstTransfer = transfers.transfers[0];
|
|
82
|
+
expect(firstTransfer).toBeDefined();
|
|
83
|
+
expect(firstTransfer?.userRequest).not.toBeDefined();
|
|
84
|
+
expect(firstTransfer?.type).toEqual(
|
|
85
|
+
transferTypeToJSON(TransferType.TRANSFER),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const sparkTransfer = await userWallet.getTransfer(firstTransfer!.id);
|
|
89
|
+
expect(sparkTransfer?.userRequest).not.toBeDefined();
|
|
90
|
+
|
|
91
|
+
const secondTransfer = transfers.transfers[1];
|
|
92
|
+
expect(secondTransfer).toBeDefined();
|
|
93
|
+
expect(secondTransfer?.userRequest).toBeDefined();
|
|
94
|
+
expect(secondTransfer?.type).toEqual(
|
|
95
|
+
transferTypeToJSON(TransferType.UTXO_SWAP),
|
|
96
|
+
);
|
|
97
|
+
expect(secondTransfer?.userRequest?.typename).toBe("ClaimStaticDeposit");
|
|
98
|
+
|
|
99
|
+
const utxoSwapTransfer = await userWallet.getTransfer(secondTransfer!.id);
|
|
100
|
+
expect(utxoSwapTransfer?.userRequest).toBeDefined();
|
|
101
|
+
}, 60000);
|
|
102
|
+
});
|