@buildonspark/spark-sdk 0.3.8 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/android/build.gradle +1 -1
- package/android/src/main/java/uniffi/uniffi/spark_frost/spark_frost.kt +1361 -1367
- package/android/src/main/jniLibs/arm64-v8a/libuniffi_spark_frost.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libuniffi_spark_frost.so +0 -0
- package/android/src/main/jniLibs/x86/libuniffi_spark_frost.so +0 -0
- package/android/src/main/jniLibs/x86_64/libuniffi_spark_frost.so +0 -0
- package/dist/bare/index.cjs +1342 -1346
- package/dist/bare/index.d.cts +114 -68
- package/dist/bare/index.d.ts +114 -68
- package/dist/bare/index.js +1266 -1279
- package/dist/{chunk-FXIESWE6.js → chunk-27ILUWDJ.js} +1 -1
- package/dist/{chunk-5ASXVNTM.js → chunk-4YFT7DAE.js} +1 -1
- package/dist/{chunk-FP2CRVQH.js → chunk-G3LHXHF3.js} +1045 -1308
- package/dist/{chunk-XI6FCNYG.js → chunk-JLF6WJ7K.js} +1 -1
- package/dist/{chunk-3LPEQGVJ.js → chunk-LOXWCMZL.js} +1 -1
- package/dist/{chunk-5HU5W56H.js → chunk-WICAF6BS.js} +2 -2
- package/dist/{chunk-VFN34EOX.js → chunk-YEBEN7XD.js} +258 -0
- package/dist/{client-pNpGP15j.d.cts → client-BIqiUNy4.d.cts} +1 -1
- package/dist/{client-By-N7oJS.d.ts → client-BaQf-5gD.d.ts} +1 -1
- package/dist/debug.cjs +1330 -1336
- package/dist/debug.d.cts +20 -16
- package/dist/debug.d.ts +20 -16
- package/dist/debug.js +5 -5
- package/dist/graphql/objects/index.d.cts +3 -3
- package/dist/graphql/objects/index.d.ts +3 -3
- package/dist/index.cjs +1363 -1365
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +32 -24
- package/dist/index.node.cjs +1363 -1365
- package/dist/index.node.d.cts +7 -7
- package/dist/index.node.d.ts +7 -7
- package/dist/index.node.js +31 -23
- package/dist/{logging-DMFVY384.d.ts → logging-BNGm6dBp.d.ts} +42 -37
- package/dist/{logging-DxLp34Xm.d.cts → logging-D3IfXfHG.d.cts} +42 -37
- package/dist/native/index.react-native.cjs +1505 -1366
- package/dist/native/index.react-native.d.cts +112 -58
- package/dist/native/index.react-native.d.ts +112 -58
- package/dist/native/index.react-native.js +1415 -1289
- package/dist/proto/spark.cjs +258 -0
- package/dist/proto/spark.d.cts +1 -1
- package/dist/proto/spark.d.ts +1 -1
- package/dist/proto/spark.js +5 -1
- package/dist/proto/spark_token.d.cts +1 -1
- package/dist/proto/spark_token.d.ts +1 -1
- package/dist/proto/spark_token.js +2 -2
- package/dist/{spark-By6yHsrk.d.cts → spark-DOpheE8_.d.cts} +39 -2
- package/dist/{spark-By6yHsrk.d.ts → spark-DOpheE8_.d.ts} +39 -2
- package/dist/{spark-wallet.browser-C1dQknVj.d.ts → spark-wallet.browser-B2rGwjuM.d.ts} +2 -2
- package/dist/{spark-wallet.browser-CNMo3IvO.d.cts → spark-wallet.browser-Ck9No4Ks.d.cts} +2 -2
- package/dist/{spark-wallet.node-Og6__NMh.d.ts → spark-wallet.node-BqmKsGPs.d.ts} +2 -2
- package/dist/{spark-wallet.node-BZJhJZKq.d.cts → spark-wallet.node-C2TIkyt4.d.cts} +2 -2
- package/dist/tests/test-utils.cjs +1304 -1236
- package/dist/tests/test-utils.d.cts +18 -4
- package/dist/tests/test-utils.d.ts +18 -4
- package/dist/tests/test-utils.js +7 -7
- package/dist/{token-transactions-CLR3rnYi.d.cts → token-transactions-Db8mkjnU.d.cts} +2 -2
- package/dist/{token-transactions-C7yefB2S.d.ts → token-transactions-DoMcrxXQ.d.ts} +2 -2
- package/dist/types/index.cjs +256 -0
- package/dist/types/index.d.cts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +2 -2
- package/dist/{wallet-config-BoyMVa6n.d.ts → wallet-config-Bg3kWltL.d.ts} +42 -35
- package/dist/{wallet-config-xom-9UFF.d.cts → wallet-config-CuZKNo9S.d.cts} +42 -35
- package/ios/spark_frostFFI.xcframework/ios-arm64/SparkFrost +0 -0
- package/ios/spark_frostFFI.xcframework/ios-arm64/spark_frostFFI.framework/spark_frostFFI +0 -0
- package/ios/spark_frostFFI.xcframework/ios-arm64_x86_64-simulator/SparkFrost +0 -0
- package/ios/spark_frostFFI.xcframework/ios-arm64_x86_64-simulator/spark_frostFFI.framework/spark_frostFFI +0 -0
- package/ios/spark_frostFFI.xcframework/macos-arm64_x86_64/spark_frostFFI.framework/spark_frostFFI +0 -0
- package/package.json +1 -1
- package/src/index.react-native.ts +8 -2
- package/src/proto/spark.ts +348 -4
- package/src/services/config.ts +5 -0
- package/src/services/coop-exit.ts +26 -107
- package/src/services/deposit.ts +12 -48
- package/src/services/signing.ts +62 -49
- package/src/services/transfer.ts +437 -722
- package/src/services/wallet-config.ts +10 -0
- package/src/services/xhr-transport.ts +13 -3
- package/src/signer/signer.react-native.ts +73 -1
- package/src/spark-wallet/proto-descriptors.ts +1 -1
- package/src/spark-wallet/spark-wallet.ts +162 -315
- package/src/spark-wallet/types.ts +2 -2
- package/src/spark_descriptors.pb +0 -0
- package/src/tests/integration/lightning.test.ts +1 -27
- package/src/tests/integration/static_deposit.test.ts +6 -9
- package/src/tests/integration/unilateral-exit.test.ts +117 -0
- package/src/tests/optimize.test.ts +31 -1
- package/src/tests/utils/signing.ts +33 -0
- package/src/tests/utils/test-faucet.ts +61 -0
- package/src/utils/optimize.ts +42 -0
- package/src/utils/transaction.ts +250 -249
- package/src/utils/unilateral-exit.ts +1 -40
package/src/services/deposit.ts
CHANGED
|
@@ -12,15 +12,13 @@ import {
|
|
|
12
12
|
StartDepositTreeCreationResponse,
|
|
13
13
|
} from "../proto/spark.js";
|
|
14
14
|
import { KeyDerivation } from "../signer/types.js";
|
|
15
|
-
import { getSigHashFromTx
|
|
15
|
+
import { getSigHashFromTx } from "../utils/bitcoin.js";
|
|
16
16
|
import { subtractPublicKeys } from "../utils/keys.js";
|
|
17
17
|
import { getNetwork } from "../utils/network.js";
|
|
18
18
|
import { proofOfPossessionMessageHashForDepositAddress } from "../utils/proof.js";
|
|
19
19
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
INITIAL_DIRECT_SEQUENCE,
|
|
23
|
-
INITIAL_SEQUENCE,
|
|
20
|
+
createInitialTimelockRefundTxs,
|
|
21
|
+
createRootNodeTx,
|
|
24
22
|
} from "../utils/transaction.js";
|
|
25
23
|
import { WalletConfigService } from "./config.js";
|
|
26
24
|
import { ConnectionManager } from "./connection/connection.js";
|
|
@@ -250,28 +248,10 @@ export class DepositService {
|
|
|
250
248
|
expected: "Valid output index",
|
|
251
249
|
});
|
|
252
250
|
}
|
|
253
|
-
const script = output.script;
|
|
254
|
-
const amount = output.amount;
|
|
255
|
-
if (!script || !amount) {
|
|
256
|
-
throw new ValidationError("No script or amount found in deposit tx", {
|
|
257
|
-
field: "output",
|
|
258
|
-
value: output,
|
|
259
|
-
expected: "Output with script and amount",
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
251
|
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
};
|
|
267
|
-
const depositTxOut = {
|
|
268
|
-
script,
|
|
269
|
-
amount,
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
const [cpfpRootTx, directRootTx] = createRootTx(
|
|
273
|
-
depositOutPoint,
|
|
274
|
-
depositTxOut,
|
|
252
|
+
const { nodeTx: cpfpRootTx, directNodeTx: directRootTx } = createRootNodeTx(
|
|
253
|
+
depositTx,
|
|
254
|
+
vout,
|
|
275
255
|
);
|
|
276
256
|
|
|
277
257
|
// Create nonce commitments for root transactions
|
|
@@ -287,14 +267,10 @@ export class DepositService {
|
|
|
287
267
|
const signingPubKey =
|
|
288
268
|
await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
289
269
|
|
|
290
|
-
// Create refund transactions (CPFP and direct)
|
|
291
270
|
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
input: { txid: hexToBytes(getTxId(cpfpRootTx)), index: 0 },
|
|
296
|
-
directInput: { txid: hexToBytes(getTxId(directRootTx)), index: 0 },
|
|
297
|
-
amountSats: amount,
|
|
271
|
+
createInitialTimelockRefundTxs({
|
|
272
|
+
nodeTx: cpfpRootTx,
|
|
273
|
+
directNodeTx: directRootTx,
|
|
298
274
|
receivingPubkey: signingPubKey,
|
|
299
275
|
network: this.config.getNetwork(),
|
|
300
276
|
});
|
|
@@ -675,16 +651,7 @@ export class DepositService {
|
|
|
675
651
|
});
|
|
676
652
|
}
|
|
677
653
|
|
|
678
|
-
const
|
|
679
|
-
txid: hexToBytes(getTxId(depositTx)),
|
|
680
|
-
index: vout,
|
|
681
|
-
};
|
|
682
|
-
const depositTxOut = {
|
|
683
|
-
script,
|
|
684
|
-
amount,
|
|
685
|
-
};
|
|
686
|
-
|
|
687
|
-
const [cpfpRootTx, _] = createRootTx(depositOutPoint, depositTxOut);
|
|
654
|
+
const { nodeTx: cpfpRootTx } = createRootNodeTx(depositTx, vout);
|
|
688
655
|
|
|
689
656
|
// Create nonce commitments for root transactions
|
|
690
657
|
const cpfpRootNonceCommitment =
|
|
@@ -696,11 +663,8 @@ export class DepositService {
|
|
|
696
663
|
const signingPubKey =
|
|
697
664
|
await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
698
665
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
sequence: INITIAL_SEQUENCE,
|
|
702
|
-
input: { txid: hexToBytes(getTxId(cpfpRootTx)), index: 0 },
|
|
703
|
-
amountSats: amount,
|
|
666
|
+
const { cpfpRefundTx } = createInitialTimelockRefundTxs({
|
|
667
|
+
nodeTx: cpfpRootTx,
|
|
704
668
|
receivingPubkey: signingPubKey,
|
|
705
669
|
network: this.config.getNetwork(),
|
|
706
670
|
});
|
package/src/services/signing.ts
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
import { hexToBytes } from "@noble/curves/utils";
|
|
2
1
|
import { Transaction } from "@scure/btc-signer";
|
|
3
|
-
import { TransactionInput } from "@scure/btc-signer/psbt";
|
|
4
2
|
import { ValidationError } from "../errors/types.js";
|
|
5
3
|
import { SigningCommitment } from "../proto/common.js";
|
|
6
4
|
import {
|
|
7
5
|
RequestedSigningCommitments,
|
|
8
6
|
UserSignedTxSigningJob,
|
|
9
7
|
} from "../proto/spark.js";
|
|
8
|
+
import { getSigHashFromTx, getTxFromRawTxBytes } from "../utils/bitcoin.js";
|
|
9
|
+
import { createRefundTxsForLightning } from "../utils/htlc-transactions.js";
|
|
10
|
+
import { getNetwork } from "../utils/network.js";
|
|
10
11
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
getTxId,
|
|
14
|
-
} from "../utils/bitcoin.js";
|
|
15
|
-
import {
|
|
16
|
-
createRefundTxs,
|
|
12
|
+
createDecrementedTimelockRefundTxs,
|
|
13
|
+
getCurrentTimelock,
|
|
17
14
|
getNextHTLCTransactionSequence,
|
|
18
|
-
getNextTransactionSequence,
|
|
19
15
|
} from "../utils/transaction.js";
|
|
20
|
-
import { createRefundTxsForLightning } from "../utils/htlc-transactions.js";
|
|
21
|
-
import { getNetwork } from "../utils/network.js";
|
|
22
16
|
import { WalletConfigService } from "./config.js";
|
|
23
|
-
import type {
|
|
17
|
+
import type {
|
|
18
|
+
LeafKeyTweak,
|
|
19
|
+
SigningJobType,
|
|
20
|
+
SigningJobWithOptionalNonce,
|
|
21
|
+
} from "./transfer.js";
|
|
24
22
|
|
|
25
23
|
export class SigningService {
|
|
26
24
|
private readonly config: WalletConfigService;
|
|
@@ -105,24 +103,9 @@ export class SigningService {
|
|
|
105
103
|
}
|
|
106
104
|
|
|
107
105
|
const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
108
|
-
const cpfpNodeOutPoint: TransactionInput = {
|
|
109
|
-
txid: hexToBytes(getTxId(nodeTx)),
|
|
110
|
-
index: 0,
|
|
111
|
-
};
|
|
112
106
|
|
|
113
107
|
const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
|
|
114
108
|
|
|
115
|
-
const sequence = currRefundTx.getInput(0).sequence;
|
|
116
|
-
if (!sequence) {
|
|
117
|
-
throw new ValidationError("Invalid refund transaction", {
|
|
118
|
-
field: "sequence",
|
|
119
|
-
value: currRefundTx.getInput(0),
|
|
120
|
-
expected: "Non-null sequence",
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
const { nextSequence, nextDirectSequence } =
|
|
124
|
-
getNextTransactionSequence(sequence);
|
|
125
|
-
|
|
126
109
|
const amountSats = currRefundTx.getOutput(0).amount;
|
|
127
110
|
if (amountSats === undefined) {
|
|
128
111
|
throw new ValidationError("Invalid refund transaction", {
|
|
@@ -133,22 +116,24 @@ export class SigningService {
|
|
|
133
116
|
}
|
|
134
117
|
|
|
135
118
|
let directNodeTx: Transaction | undefined;
|
|
136
|
-
let directNodeOutPoint: TransactionInput | undefined;
|
|
137
119
|
if (leaf.leaf.directTx.length > 0) {
|
|
138
120
|
directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const currentSequence = currRefundTx.getInput(0).sequence;
|
|
124
|
+
if (!currentSequence) {
|
|
125
|
+
throw new ValidationError("Invalid refund transaction", {
|
|
126
|
+
field: "sequence",
|
|
127
|
+
value: currRefundTx.getInput(0),
|
|
128
|
+
expected: "Non-null sequence",
|
|
129
|
+
});
|
|
143
130
|
}
|
|
144
131
|
|
|
145
132
|
const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
directInput: directNodeOutPoint,
|
|
151
|
-
amountSats,
|
|
133
|
+
createDecrementedTimelockRefundTxs({
|
|
134
|
+
nodeTx: nodeTx,
|
|
135
|
+
directNodeTx: directNodeTx,
|
|
136
|
+
sequence: currentSequence,
|
|
152
137
|
receivingPubkey: receiverIdentityPubkey,
|
|
153
138
|
network: this.config.getNetwork(),
|
|
154
139
|
});
|
|
@@ -167,7 +152,8 @@ export class SigningService {
|
|
|
167
152
|
|
|
168
153
|
cpfpLeafSigningJobs.push(...signingJobs);
|
|
169
154
|
|
|
170
|
-
|
|
155
|
+
const isZeroNode = getCurrentTimelock(nodeTx.getInput(0).sequence);
|
|
156
|
+
if (directRefundTx && !isZeroNode) {
|
|
171
157
|
if (!directNodeTx) {
|
|
172
158
|
throw new ValidationError(
|
|
173
159
|
"Direct node transaction undefined while direct refund transaction is defined",
|
|
@@ -193,16 +179,6 @@ export class SigningService {
|
|
|
193
179
|
}
|
|
194
180
|
|
|
195
181
|
if (directFromCpfpRefundTx) {
|
|
196
|
-
if (!directNodeTx) {
|
|
197
|
-
throw new ValidationError(
|
|
198
|
-
"Direct node transaction undefined while direct from CPFP refund transaction is defined",
|
|
199
|
-
{
|
|
200
|
-
field: "directNodeTx",
|
|
201
|
-
value: directNodeTx,
|
|
202
|
-
expected: "Non-null direct node transaction",
|
|
203
|
-
},
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
182
|
const refundSighash = getSigHashFromTx(
|
|
207
183
|
directFromCpfpRefundTx,
|
|
208
184
|
0,
|
|
@@ -358,4 +334,41 @@ export class SigningService {
|
|
|
358
334
|
directFromCpfpLeafSigningJobs,
|
|
359
335
|
};
|
|
360
336
|
}
|
|
337
|
+
|
|
338
|
+
async signSigningJobs(
|
|
339
|
+
signingJobs: (SigningJobWithOptionalNonce & RequestedSigningCommitments)[],
|
|
340
|
+
): Promise<Map<SigningJobType, UserSignedTxSigningJob>> {
|
|
341
|
+
const userSignedTxSigningJobs: Map<SigningJobType, UserSignedTxSigningJob> =
|
|
342
|
+
new Map();
|
|
343
|
+
|
|
344
|
+
for (const signingJob of signingJobs) {
|
|
345
|
+
const rawTx = getTxFromRawTxBytes(signingJob.rawTx);
|
|
346
|
+
const txOut = signingJob.parentTxOut;
|
|
347
|
+
const rawTxSighash = getSigHashFromTx(rawTx, 0, txOut);
|
|
348
|
+
const userSignature = await this.config.signer.signFrost({
|
|
349
|
+
message: rawTxSighash,
|
|
350
|
+
keyDerivation: signingJob.keyDerivation,
|
|
351
|
+
publicKey: signingJob.signingPublicKey,
|
|
352
|
+
verifyingKey: signingJob.verifyingKey,
|
|
353
|
+
selfCommitment: signingJob.signingNonceCommitment,
|
|
354
|
+
statechainCommitments: signingJob.signingNonceCommitments,
|
|
355
|
+
adaptorPubKey: new Uint8Array(),
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
const userSignedTxSigningJob: UserSignedTxSigningJob = {
|
|
359
|
+
leafId: signingJob.leafId,
|
|
360
|
+
signingPublicKey: signingJob.signingPublicKey,
|
|
361
|
+
rawTx: rawTx.toBytes(),
|
|
362
|
+
signingNonceCommitment: signingJob.signingNonceCommitment.commitment,
|
|
363
|
+
signingCommitments: {
|
|
364
|
+
signingCommitments: signingJob.signingNonceCommitments,
|
|
365
|
+
},
|
|
366
|
+
userSignature,
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
userSignedTxSigningJobs.set(signingJob.type, userSignedTxSigningJob);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return userSignedTxSigningJobs;
|
|
373
|
+
}
|
|
361
374
|
}
|