@buildonspark/spark-sdk 0.0.15 → 0.0.16
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/services/wallet-config.d.ts +1 -0
- package/dist/services/wallet-config.js +1 -0
- package/dist/services/wallet-config.js.map +1 -1
- package/dist/spark-sdk.d.ts +1 -1
- package/dist/spark-sdk.js +3 -3
- package/dist/spark-sdk.js.map +1 -1
- package/package.json +4 -3
- package/src/examples/example.js +247 -0
- package/src/examples/example.ts +207 -0
- package/src/graphql/client.ts +282 -0
- package/src/graphql/mutations/CompleteCoopExit.ts +19 -0
- package/src/graphql/mutations/CompleteLeavesSwap.ts +17 -0
- package/src/graphql/mutations/RequestCoopExit.ts +20 -0
- package/src/graphql/mutations/RequestLightningReceive.ts +26 -0
- package/src/graphql/mutations/RequestLightningSend.ts +17 -0
- package/src/graphql/mutations/RequestSwapLeaves.ts +24 -0
- package/src/graphql/objects/BitcoinNetwork.ts +22 -0
- package/src/graphql/objects/CompleteCoopExitInput.ts +41 -0
- package/src/graphql/objects/CompleteCoopExitOutput.ts +45 -0
- package/src/graphql/objects/CompleteLeavesSwapInput.ts +45 -0
- package/src/graphql/objects/CompleteLeavesSwapOutput.ts +45 -0
- package/src/graphql/objects/CompleteSeedReleaseInput.ts +41 -0
- package/src/graphql/objects/CompleteSeedReleaseOutput.ts +43 -0
- package/src/graphql/objects/Connection.ts +90 -0
- package/src/graphql/objects/CoopExitFeeEstimateInput.ts +41 -0
- package/src/graphql/objects/CoopExitFeeEstimateOutput.ts +52 -0
- package/src/graphql/objects/CoopExitRequest.ts +118 -0
- package/src/graphql/objects/CurrencyAmount.ts +74 -0
- package/src/graphql/objects/CurrencyUnit.ts +32 -0
- package/src/graphql/objects/Entity.ts +202 -0
- package/src/graphql/objects/GetChallengeInput.ts +37 -0
- package/src/graphql/objects/GetChallengeOutput.ts +43 -0
- package/src/graphql/objects/Invoice.ts +83 -0
- package/src/graphql/objects/Leaf.ts +59 -0
- package/src/graphql/objects/LeavesSwapFeeEstimateInput.ts +37 -0
- package/src/graphql/objects/LeavesSwapFeeEstimateOutput.ts +52 -0
- package/src/graphql/objects/LeavesSwapRequest.ts +192 -0
- package/src/graphql/objects/LightningReceiveFeeEstimateInput.ts +41 -0
- package/src/graphql/objects/LightningReceiveFeeEstimateOutput.ts +52 -0
- package/src/graphql/objects/LightningReceiveRequest.ts +147 -0
- package/src/graphql/objects/LightningReceiveRequestStatus.ts +34 -0
- package/src/graphql/objects/LightningSendFeeEstimateInput.ts +37 -0
- package/src/graphql/objects/LightningSendFeeEstimateOutput.ts +52 -0
- package/src/graphql/objects/LightningSendRequest.ts +134 -0
- package/src/graphql/objects/LightningSendRequestStatus.ts +28 -0
- package/src/graphql/objects/NotifyReceiverTransferInput.ts +41 -0
- package/src/graphql/objects/PageInfo.ts +58 -0
- package/src/graphql/objects/Provider.ts +41 -0
- package/src/graphql/objects/RequestCoopExitInput.ts +41 -0
- package/src/graphql/objects/RequestCoopExitOutput.ts +45 -0
- package/src/graphql/objects/RequestLeavesSwapInput.ts +55 -0
- package/src/graphql/objects/RequestLeavesSwapOutput.ts +45 -0
- package/src/graphql/objects/RequestLightningReceiveInput.ts +58 -0
- package/src/graphql/objects/RequestLightningReceiveOutput.ts +45 -0
- package/src/graphql/objects/RequestLightningSendInput.ts +41 -0
- package/src/graphql/objects/RequestLightningSendOutput.ts +45 -0
- package/src/graphql/objects/SparkCoopExitRequestStatus.ts +20 -0
- package/src/graphql/objects/SparkLeavesSwapRequestStatus.ts +20 -0
- package/src/graphql/objects/SparkTransferToLeavesConnection.ts +79 -0
- package/src/graphql/objects/SparkWalletUser.ts +86 -0
- package/src/graphql/objects/StartSeedReleaseInput.ts +37 -0
- package/src/graphql/objects/SwapLeaf.ts +53 -0
- package/src/graphql/objects/Transfer.ts +98 -0
- package/src/graphql/objects/UserLeafInput.ts +28 -0
- package/src/graphql/objects/VerifyChallengeInput.ts +51 -0
- package/src/graphql/objects/VerifyChallengeOutput.ts +43 -0
- package/src/graphql/objects/WalletUserIdentityPublicKeyInput.ts +37 -0
- package/src/graphql/objects/WalletUserIdentityPublicKeyOutput.ts +43 -0
- package/src/graphql/objects/index.ts +67 -0
- package/src/graphql/queries/CoopExitFeeEstimate.ts +18 -0
- package/src/graphql/queries/CurrentUser.ts +10 -0
- package/src/graphql/queries/LightningReceiveFeeEstimate.ts +18 -0
- package/src/graphql/queries/LightningSendFeeEstimate.ts +16 -0
- package/src/proto/common.ts +431 -0
- package/src/proto/google/protobuf/descriptor.ts +6625 -0
- package/src/proto/google/protobuf/duration.ts +197 -0
- package/src/proto/google/protobuf/empty.ts +83 -0
- package/src/proto/google/protobuf/timestamp.ts +226 -0
- package/src/proto/mock.ts +151 -0
- package/src/proto/spark.ts +12727 -0
- package/src/proto/spark_authn.ts +673 -0
- package/src/proto/validate/validate.ts +6047 -0
- package/src/services/config.ts +71 -0
- package/src/services/connection.ts +264 -0
- package/src/services/coop-exit.ts +190 -0
- package/src/services/deposit.ts +327 -0
- package/src/services/lightning.ts +341 -0
- package/src/services/lrc20.ts +42 -0
- package/src/services/token-transactions.ts +499 -0
- package/src/services/transfer.ts +1188 -0
- package/src/services/tree-creation.ts +618 -0
- package/src/services/wallet-config.ts +141 -0
- package/src/signer/signer.ts +531 -0
- package/src/spark-sdk.ts +1644 -0
- package/src/tests/adaptor-signature.test.ts +64 -0
- package/src/tests/bitcoin.test.ts +122 -0
- package/src/tests/coop-exit.test.ts +233 -0
- package/src/tests/deposit.test.ts +98 -0
- package/src/tests/keys.test.ts +82 -0
- package/src/tests/lightning.test.ts +307 -0
- package/src/tests/secret-sharing.test.ts +63 -0
- package/src/tests/swap.test.ts +252 -0
- package/src/tests/test-util.ts +92 -0
- package/src/tests/tokens.test.ts +47 -0
- package/src/tests/transfer.test.ts +371 -0
- package/src/tests/tree-creation.test.ts +56 -0
- package/src/tests/utils/spark-testing-wallet.ts +37 -0
- package/src/tests/utils/test-faucet.ts +257 -0
- package/src/types/grpc.ts +8 -0
- package/src/types/index.ts +3 -0
- package/src/utils/adaptor-signature.ts +189 -0
- package/src/utils/bitcoin.ts +138 -0
- package/src/utils/crypto.ts +14 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/keys.ts +92 -0
- package/src/utils/mempool.ts +42 -0
- package/src/utils/network.ts +70 -0
- package/src/utils/proof.ts +17 -0
- package/src/utils/response-validation.ts +26 -0
- package/src/utils/secret-sharing.ts +263 -0
- package/src/utils/signing.ts +96 -0
- package/src/utils/token-hashing.ts +163 -0
- package/src/utils/token-keyshares.ts +31 -0
- package/src/utils/token-transactions.ts +71 -0
- package/src/utils/transaction.ts +45 -0
- package/src/utils/wasm-wrapper.ts +57 -0
- package/src/utils/wasm.ts +154 -0
- package/src/wasm/spark_bindings.d.ts +208 -0
- package/src/wasm/spark_bindings.js +1161 -0
- package/src/wasm/spark_bindings_bg.wasm +0 -0
- package/src/wasm/spark_bindings_bg.wasm.d.ts +136 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { numberToBytesBE } from "@noble/curves/abstract/utils";
|
|
2
|
+
import { hashTokenTransaction } from "../utils/token-hashing.js";
|
|
3
|
+
|
|
4
|
+
describe("hash token transaction", () => {
|
|
5
|
+
it("should produce the exact same hash", () => {
|
|
6
|
+
const tokenAmount: bigint = 1000n;
|
|
7
|
+
|
|
8
|
+
const tokenPublicKey = new Uint8Array([
|
|
9
|
+
242, 155, 208, 90, 72, 211, 120, 244, 69, 99, 28, 101, 149, 222, 123, 50,
|
|
10
|
+
252, 63, 99, 54, 137, 226, 7, 224, 163, 122, 93, 248, 42, 159, 173, 45,
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
const identityPubKey = new Uint8Array([
|
|
14
|
+
25, 155, 208, 90, 72, 211, 120, 244, 69, 99, 28, 101, 149, 222, 123, 50,
|
|
15
|
+
252, 63, 99, 54, 137, 226, 7, 224, 163, 122, 93, 248, 42, 159, 173, 46,
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
const tokenTransaction = {
|
|
19
|
+
tokenInput: {
|
|
20
|
+
$case: "mintInput" as const,
|
|
21
|
+
mintInput: {
|
|
22
|
+
issuerPublicKey: tokenPublicKey,
|
|
23
|
+
issuerProvidedTimestamp: 100,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
outputLeaves: [
|
|
27
|
+
{
|
|
28
|
+
id: "db1a4e48-0fc5-4f6c-8a80-d9d6c561a436",
|
|
29
|
+
ownerPublicKey: identityPubKey,
|
|
30
|
+
withdrawBondSats: 10000,
|
|
31
|
+
withdrawLocktime: 100,
|
|
32
|
+
tokenPublicKey: tokenPublicKey,
|
|
33
|
+
tokenAmount: numberToBytesBE(tokenAmount, 16),
|
|
34
|
+
revocationPublicKey: new Uint8Array(0),
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
sparkOperatorIdentityPublicKeys: [],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const hash = hashTokenTransaction(tokenTransaction, false);
|
|
41
|
+
|
|
42
|
+
expect(Array.from(hash)).toEqual([
|
|
43
|
+
169, 30, 146, 172, 90, 113, 89, 157, 142, 5, 138, 251, 237, 122, 65, 135,
|
|
44
|
+
47, 178, 192, 116, 107, 24, 176, 162, 78, 238, 80, 166, 38, 129, 151, 167,
|
|
45
|
+
]);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { describe, expect, it } from "@jest/globals";
|
|
2
|
+
import {
|
|
3
|
+
bytesToHex,
|
|
4
|
+
equalBytes,
|
|
5
|
+
hexToBytes,
|
|
6
|
+
} from "@noble/curves/abstract/utils";
|
|
7
|
+
import { generateMnemonic } from "@scure/bip39";
|
|
8
|
+
import { wordlist } from "@scure/bip39/wordlists/english";
|
|
9
|
+
import { sha256 } from "@scure/btc-signer/utils";
|
|
10
|
+
import { WalletConfigService } from "../services/config.js";
|
|
11
|
+
import { ConnectionManager } from "../services/connection.js";
|
|
12
|
+
import { LeafKeyTweak, TransferService } from "../services/transfer.js";
|
|
13
|
+
import { ConfigOptions } from "../services/wallet-config.js";
|
|
14
|
+
import { createNewTree } from "./test-util.js";
|
|
15
|
+
import { SparkWalletTesting } from "./utils/spark-testing-wallet.js";
|
|
16
|
+
import { BitcoinFaucet } from "./utils/test-faucet.js";
|
|
17
|
+
describe("Transfer", () => {
|
|
18
|
+
// Skip all tests if running in GitHub Actions
|
|
19
|
+
const testFn = process.env.GITHUB_ACTIONS ? it.skip : it;
|
|
20
|
+
|
|
21
|
+
testFn(
|
|
22
|
+
"test transfer",
|
|
23
|
+
async () => {
|
|
24
|
+
const faucet = new BitcoinFaucet(
|
|
25
|
+
"http://127.0.0.1:18443",
|
|
26
|
+
"admin1",
|
|
27
|
+
"123",
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const options: ConfigOptions = {
|
|
31
|
+
network: "LOCAL",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const { wallet: senderWallet } = await SparkWalletTesting.create({
|
|
35
|
+
options,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const senderConfigService = new WalletConfigService(
|
|
39
|
+
options,
|
|
40
|
+
senderWallet.getSigner(),
|
|
41
|
+
);
|
|
42
|
+
const senderConnectionManager = new ConnectionManager(
|
|
43
|
+
senderConfigService,
|
|
44
|
+
);
|
|
45
|
+
const senderTransferService = new TransferService(
|
|
46
|
+
senderConfigService,
|
|
47
|
+
senderConnectionManager,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const leafPubKey = await senderWallet.getSigner().generatePublicKey();
|
|
51
|
+
const rootNode = await createNewTree(
|
|
52
|
+
senderWallet,
|
|
53
|
+
leafPubKey,
|
|
54
|
+
faucet,
|
|
55
|
+
1000n,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const newLeafPubKey = await senderWallet.getSigner().generatePublicKey();
|
|
59
|
+
|
|
60
|
+
const { wallet: receiverWallet } = await SparkWalletTesting.create({
|
|
61
|
+
options,
|
|
62
|
+
});
|
|
63
|
+
const receiverPubkey = await receiverWallet.getIdentityPublicKey();
|
|
64
|
+
|
|
65
|
+
const receiverConfigService = new WalletConfigService(
|
|
66
|
+
options,
|
|
67
|
+
receiverWallet.getSigner(),
|
|
68
|
+
);
|
|
69
|
+
const receiverConnectionManager = new ConnectionManager(
|
|
70
|
+
receiverConfigService,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const receiverTransferService = new TransferService(
|
|
74
|
+
receiverConfigService,
|
|
75
|
+
receiverConnectionManager,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const transferNode = {
|
|
79
|
+
leaf: rootNode,
|
|
80
|
+
signingPubKey: leafPubKey,
|
|
81
|
+
newSigningPubKey: newLeafPubKey,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const senderTransfer = await senderTransferService.sendTransfer(
|
|
85
|
+
[transferNode],
|
|
86
|
+
hexToBytes(receiverPubkey),
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const pendingTransfer = await receiverWallet.queryPendingTransfers();
|
|
90
|
+
|
|
91
|
+
expect(pendingTransfer.transfers.length).toBe(1);
|
|
92
|
+
|
|
93
|
+
const receiverTransfer = pendingTransfer.transfers[0];
|
|
94
|
+
|
|
95
|
+
expect(receiverTransfer!.id).toBe(senderTransfer.id);
|
|
96
|
+
|
|
97
|
+
const leafPrivKeyMap = await receiverWallet.verifyPendingTransfer(
|
|
98
|
+
receiverTransfer!,
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
expect(leafPrivKeyMap.size).toBe(1);
|
|
102
|
+
|
|
103
|
+
const leafPrivKeyMapBytes = leafPrivKeyMap.get(rootNode.id);
|
|
104
|
+
expect(leafPrivKeyMapBytes).toBeDefined();
|
|
105
|
+
expect(bytesToHex(leafPrivKeyMapBytes!)).toBe(bytesToHex(newLeafPubKey));
|
|
106
|
+
|
|
107
|
+
const finalLeafPubKey = await receiverWallet
|
|
108
|
+
.getSigner()
|
|
109
|
+
.generatePublicKey(sha256(rootNode.id));
|
|
110
|
+
|
|
111
|
+
const claimingNode = {
|
|
112
|
+
leaf: rootNode,
|
|
113
|
+
signingPubKey: newLeafPubKey,
|
|
114
|
+
newSigningPubKey: finalLeafPubKey,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
await receiverTransferService.claimTransfer(receiverTransfer!, [
|
|
118
|
+
claimingNode,
|
|
119
|
+
]);
|
|
120
|
+
|
|
121
|
+
const { wallet: newReceiverWallet } = await SparkWalletTesting.create({
|
|
122
|
+
options: {
|
|
123
|
+
network: "LOCAL",
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
const newReceiverPubkey = await newReceiverWallet.getIdentityPublicKey();
|
|
127
|
+
|
|
128
|
+
await receiverWallet.transfer({
|
|
129
|
+
amountSats: 1000,
|
|
130
|
+
receiverSparkAddress: newReceiverPubkey,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const newPendingTransfer =
|
|
134
|
+
await newReceiverWallet.queryPendingTransfers();
|
|
135
|
+
|
|
136
|
+
expect(newPendingTransfer.transfers.length).toBe(1);
|
|
137
|
+
await newReceiverWallet.getBalance();
|
|
138
|
+
},
|
|
139
|
+
30000,
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
testFn("test transfer with separate", async () => {
|
|
143
|
+
const faucet = new BitcoinFaucet("http://127.0.0.1:18443", "admin1", "123");
|
|
144
|
+
|
|
145
|
+
const options: ConfigOptions = {
|
|
146
|
+
network: "LOCAL",
|
|
147
|
+
};
|
|
148
|
+
const { wallet: senderWallet } = await SparkWalletTesting.create({
|
|
149
|
+
options,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const senderConfigService = new WalletConfigService(
|
|
153
|
+
options,
|
|
154
|
+
senderWallet.getSigner(),
|
|
155
|
+
);
|
|
156
|
+
const senderConnectionManager = new ConnectionManager(senderConfigService);
|
|
157
|
+
const senderTransferService = new TransferService(
|
|
158
|
+
senderConfigService,
|
|
159
|
+
senderConnectionManager,
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const { wallet: receiverWallet } = await SparkWalletTesting.create({
|
|
163
|
+
options,
|
|
164
|
+
});
|
|
165
|
+
const receiverPubkey = await receiverWallet.getIdentityPublicKey();
|
|
166
|
+
|
|
167
|
+
const receiverConfigService = new WalletConfigService(
|
|
168
|
+
options,
|
|
169
|
+
receiverWallet.getSigner(),
|
|
170
|
+
);
|
|
171
|
+
const receiverConnectionManager = new ConnectionManager(
|
|
172
|
+
receiverConfigService,
|
|
173
|
+
);
|
|
174
|
+
const receiverTransferService = new TransferService(
|
|
175
|
+
receiverConfigService,
|
|
176
|
+
receiverConnectionManager,
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const leafPubKey = await senderWallet.getSigner().generatePublicKey();
|
|
180
|
+
|
|
181
|
+
const rootNode = await createNewTree(
|
|
182
|
+
senderWallet,
|
|
183
|
+
leafPubKey,
|
|
184
|
+
faucet,
|
|
185
|
+
100_000n,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const newLeafPubKey = await senderWallet.getSigner().generatePublicKey();
|
|
189
|
+
|
|
190
|
+
const transferNode: LeafKeyTweak = {
|
|
191
|
+
leaf: rootNode,
|
|
192
|
+
signingPubKey: leafPubKey,
|
|
193
|
+
newSigningPubKey: newLeafPubKey,
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const leavesToTransfer = [transferNode];
|
|
197
|
+
|
|
198
|
+
const senderTransfer = await senderTransferService.sendTransfer(
|
|
199
|
+
leavesToTransfer,
|
|
200
|
+
hexToBytes(receiverPubkey),
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
// Receiver queries pending transfer
|
|
204
|
+
const pendingTransfer = await receiverWallet.queryPendingTransfers();
|
|
205
|
+
|
|
206
|
+
expect(pendingTransfer.transfers.length).toBe(1);
|
|
207
|
+
|
|
208
|
+
const receiverTransfer = pendingTransfer.transfers[0];
|
|
209
|
+
|
|
210
|
+
expect(receiverTransfer!.id).toBe(senderTransfer.id);
|
|
211
|
+
|
|
212
|
+
const leafPrivKeyMap = await receiverWallet.verifyPendingTransfer(
|
|
213
|
+
receiverTransfer!,
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
expect(leafPrivKeyMap.size).toBe(1);
|
|
217
|
+
|
|
218
|
+
const leafPrivKeyMapBytes = leafPrivKeyMap.get(rootNode.id);
|
|
219
|
+
expect(leafPrivKeyMapBytes).toBeDefined();
|
|
220
|
+
expect(equalBytes(leafPrivKeyMapBytes!, newLeafPubKey)).toBe(true);
|
|
221
|
+
|
|
222
|
+
const finalLeafPubKey = await receiverWallet
|
|
223
|
+
.getSigner()
|
|
224
|
+
.generatePublicKey(sha256(rootNode.id));
|
|
225
|
+
|
|
226
|
+
const claimingNode: LeafKeyTweak = {
|
|
227
|
+
leaf: receiverTransfer!.leaves[0]!.leaf!,
|
|
228
|
+
signingPubKey: newLeafPubKey,
|
|
229
|
+
newSigningPubKey: finalLeafPubKey,
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const transferService = new TransferService(
|
|
233
|
+
receiverConfigService,
|
|
234
|
+
new ConnectionManager(receiverConfigService),
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
await transferService.claimTransferTweakKeys(receiverTransfer!, [
|
|
238
|
+
claimingNode,
|
|
239
|
+
]);
|
|
240
|
+
|
|
241
|
+
const newPendingTransfer = await receiverWallet.queryPendingTransfers();
|
|
242
|
+
|
|
243
|
+
expect(newPendingTransfer.transfers.length).toBe(1);
|
|
244
|
+
|
|
245
|
+
const newReceiverTransfer = newPendingTransfer.transfers[0];
|
|
246
|
+
expect(newReceiverTransfer!.id).toBe(receiverTransfer!.id);
|
|
247
|
+
|
|
248
|
+
const newLeafPubKeyMap = await receiverWallet.verifyPendingTransfer(
|
|
249
|
+
newReceiverTransfer!,
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
expect(newLeafPubKeyMap.size).toBe(1);
|
|
253
|
+
|
|
254
|
+
const newLeafPubKeyMapBytes = newLeafPubKeyMap.get(rootNode.id);
|
|
255
|
+
expect(newLeafPubKeyMapBytes).toBeDefined();
|
|
256
|
+
expect(bytesToHex(newLeafPubKeyMapBytes!)).toBe(bytesToHex(newLeafPubKey));
|
|
257
|
+
|
|
258
|
+
await transferService.claimTransferSignRefunds(newReceiverTransfer!, [
|
|
259
|
+
claimingNode,
|
|
260
|
+
]);
|
|
261
|
+
|
|
262
|
+
const newNewPendingTransfer = await receiverWallet.queryPendingTransfers();
|
|
263
|
+
expect(newNewPendingTransfer.transfers.length).toBe(1);
|
|
264
|
+
|
|
265
|
+
await receiverTransferService.claimTransfer(
|
|
266
|
+
newNewPendingTransfer.transfers[0]!,
|
|
267
|
+
[claimingNode],
|
|
268
|
+
);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
testFn("cancel transfer", async () => {
|
|
272
|
+
const faucet = new BitcoinFaucet("http://127.0.0.1:18443", "admin1", "123");
|
|
273
|
+
|
|
274
|
+
const options: ConfigOptions = {
|
|
275
|
+
network: "LOCAL",
|
|
276
|
+
};
|
|
277
|
+
const { wallet: senderWallet } = await SparkWalletTesting.create({
|
|
278
|
+
options,
|
|
279
|
+
});
|
|
280
|
+
const mnemonic = generateMnemonic(wordlist);
|
|
281
|
+
|
|
282
|
+
const { wallet: receiverWallet } = await SparkWalletTesting.create({
|
|
283
|
+
options,
|
|
284
|
+
});
|
|
285
|
+
const receiverPubkey = await receiverWallet.getIdentityPublicKey();
|
|
286
|
+
|
|
287
|
+
const receiverConfigService = new WalletConfigService(
|
|
288
|
+
options,
|
|
289
|
+
receiverWallet.getSigner(),
|
|
290
|
+
);
|
|
291
|
+
const receiverConnectionManager = new ConnectionManager(
|
|
292
|
+
receiverConfigService,
|
|
293
|
+
);
|
|
294
|
+
const receiverTransferService = new TransferService(
|
|
295
|
+
receiverConfigService,
|
|
296
|
+
receiverConnectionManager,
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
const leafPubKey = await senderWallet.getSigner().generatePublicKey();
|
|
300
|
+
const rootNode = await createNewTree(
|
|
301
|
+
senderWallet,
|
|
302
|
+
leafPubKey,
|
|
303
|
+
faucet,
|
|
304
|
+
100_000n,
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
const newLeafPubKey = await senderWallet.getSigner().generatePublicKey();
|
|
308
|
+
|
|
309
|
+
const transferNode: LeafKeyTweak = {
|
|
310
|
+
leaf: rootNode,
|
|
311
|
+
signingPubKey: leafPubKey,
|
|
312
|
+
newSigningPubKey: newLeafPubKey,
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const senderConfigService = new WalletConfigService(
|
|
316
|
+
options,
|
|
317
|
+
senderWallet.getSigner(),
|
|
318
|
+
);
|
|
319
|
+
const senderConnectionManager = new ConnectionManager(senderConfigService);
|
|
320
|
+
const senderTransferService = new TransferService(
|
|
321
|
+
senderConfigService,
|
|
322
|
+
senderConnectionManager,
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
const senderTransfer = await senderTransferService.sendTransferSignRefund(
|
|
326
|
+
[transferNode],
|
|
327
|
+
hexToBytes(receiverPubkey),
|
|
328
|
+
new Date(Date.now() + 10 * 60 * 1000),
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
await senderTransferService.cancelSendTransfer(
|
|
332
|
+
senderTransfer.transfer,
|
|
333
|
+
senderConfigService.getCoordinatorAddress(),
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
const newSenderTransfer = await senderTransferService.sendTransfer(
|
|
337
|
+
[transferNode],
|
|
338
|
+
hexToBytes(receiverPubkey),
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
const pendingTransfer = await receiverWallet.queryPendingTransfers();
|
|
342
|
+
expect(pendingTransfer.transfers.length).toBe(1);
|
|
343
|
+
|
|
344
|
+
const receiverTransfer = pendingTransfer.transfers[0];
|
|
345
|
+
expect(receiverTransfer!.id).toBe(newSenderTransfer.id);
|
|
346
|
+
|
|
347
|
+
const leafPubKeyMap = await receiverWallet.verifyPendingTransfer(
|
|
348
|
+
receiverTransfer!,
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
expect(leafPubKeyMap.size).toBe(1);
|
|
352
|
+
|
|
353
|
+
const leafPubKeyMapBytes = leafPubKeyMap.get(rootNode.id);
|
|
354
|
+
expect(leafPubKeyMapBytes).toBeDefined();
|
|
355
|
+
expect(equalBytes(leafPubKeyMapBytes!, newLeafPubKey)).toBe(true);
|
|
356
|
+
|
|
357
|
+
const finalLeafPubKey = await receiverWallet
|
|
358
|
+
.getSigner()
|
|
359
|
+
.generatePublicKey(sha256(rootNode.id));
|
|
360
|
+
|
|
361
|
+
const claimingNode: LeafKeyTweak = {
|
|
362
|
+
leaf: receiverTransfer!.leaves[0]!.leaf!,
|
|
363
|
+
signingPubKey: newLeafPubKey,
|
|
364
|
+
newSigningPubKey: finalLeafPubKey,
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
await receiverTransferService.claimTransfer(receiverTransfer!, [
|
|
368
|
+
claimingNode,
|
|
369
|
+
]);
|
|
370
|
+
});
|
|
371
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { describe, expect, it } from "@jest/globals";
|
|
3
|
+
import { bytesToHex } from "@noble/curves/abstract/utils";
|
|
4
|
+
import { getTxFromRawTxBytes, getTxId } from "../utils/bitcoin.js";
|
|
5
|
+
import { Network } from "../utils/network.js";
|
|
6
|
+
import { createDummyTx } from "../utils/wasm.js";
|
|
7
|
+
import { SparkWalletTesting } from "./utils/spark-testing-wallet.js";
|
|
8
|
+
|
|
9
|
+
describe("Tree Creation", () => {
|
|
10
|
+
// Skip all tests if running in GitHub Actions
|
|
11
|
+
const testFn = process.env.GITHUB_ACTIONS ? it.skip : xit;
|
|
12
|
+
|
|
13
|
+
testFn(
|
|
14
|
+
"test tree creation address generation",
|
|
15
|
+
async () => {
|
|
16
|
+
const wallet = new SparkWalletTesting(Network.LOCAL);
|
|
17
|
+
await wallet.initWallet();
|
|
18
|
+
|
|
19
|
+
const pubKey = await wallet.getSigner().generatePublicKey();
|
|
20
|
+
|
|
21
|
+
const depositResp = await wallet.generateDepositAddress();
|
|
22
|
+
|
|
23
|
+
expect(depositResp.depositAddress).toBeDefined();
|
|
24
|
+
|
|
25
|
+
const dummyTx = createDummyTx({
|
|
26
|
+
address: depositResp.depositAddress!.address,
|
|
27
|
+
amountSats: 65536n,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const depositTxHex = bytesToHex(dummyTx.tx);
|
|
31
|
+
const depositTx = getTxFromRawTxBytes(dummyTx.tx);
|
|
32
|
+
|
|
33
|
+
const vout = 0;
|
|
34
|
+
const txid = getTxId(depositTx);
|
|
35
|
+
if (!txid) {
|
|
36
|
+
throw new Error("txid not found");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const treeResp = await wallet.generateDepositAddressForTree(
|
|
40
|
+
vout,
|
|
41
|
+
pubKey,
|
|
42
|
+
depositTx,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const treeNodes = await wallet.createTree(
|
|
46
|
+
vout,
|
|
47
|
+
treeResp,
|
|
48
|
+
true,
|
|
49
|
+
depositTx,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
console.log("tree nodes:", treeNodes);
|
|
53
|
+
},
|
|
54
|
+
30000,
|
|
55
|
+
);
|
|
56
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { QueryPendingTransfersResponse, Transfer } from "../../proto/spark.js";
|
|
2
|
+
import { SparkSigner } from "../../signer/signer.js";
|
|
3
|
+
import { SparkWallet, SparkWalletProps } from "../../spark-sdk.js";
|
|
4
|
+
|
|
5
|
+
interface ISparkWalletTesting extends SparkWallet {
|
|
6
|
+
getSigner(): SparkSigner;
|
|
7
|
+
queryPendingTransfers(): Promise<QueryPendingTransfersResponse>;
|
|
8
|
+
verifyPendingTransfer(transfer: Transfer): Promise<Map<string, Uint8Array>>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class SparkWalletTesting
|
|
12
|
+
extends SparkWallet
|
|
13
|
+
implements ISparkWalletTesting
|
|
14
|
+
{
|
|
15
|
+
static async create(props: SparkWalletProps) {
|
|
16
|
+
const wallet = new SparkWalletTesting(props.options, props.signer);
|
|
17
|
+
const initResponse = await wallet.initWallet(props.mnemonicOrSeed);
|
|
18
|
+
return {
|
|
19
|
+
wallet,
|
|
20
|
+
mnemonic: initResponse?.mnemonic,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public getSigner(): SparkSigner {
|
|
25
|
+
return this.config.signer;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public async queryPendingTransfers(): Promise<QueryPendingTransfersResponse> {
|
|
29
|
+
return await this.transferService.queryPendingTransfers();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public async verifyPendingTransfer(
|
|
33
|
+
transfer: Transfer,
|
|
34
|
+
): Promise<Map<string, Uint8Array>> {
|
|
35
|
+
return await this.transferService.verifyPendingTransfer(transfer);
|
|
36
|
+
}
|
|
37
|
+
}
|