@buildonspark/spark-sdk 0.1.46 → 0.2.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 +26 -0
- package/dist/{chunk-BGGEVUJK.js → chunk-2ENZX6LT.js} +241 -7
- package/dist/{chunk-LHRD2WT6.js → chunk-4JD4HIAN.js} +23 -3
- package/dist/{chunk-I54FARY2.js → chunk-CDLETEDT.js} +11 -3
- package/dist/{chunk-OBFKIEMP.js → chunk-TM6CHQXC.js} +1 -1
- package/dist/chunk-UDK3EBE5.js +13514 -0
- package/dist/chunk-XYTKKLCV.js +7 -0
- package/dist/{RequestLightningSendInput-2cSh_In4.d.cts → client-DKbwpcnl.d.ts} +434 -212
- package/dist/{RequestLightningSendInput-CN6BNg_g.d.ts → client-Drs5Lapg.d.cts} +434 -212
- package/dist/{services/config.cjs → debug.cjs} +31007 -1003
- package/dist/debug.d.cts +126 -0
- package/dist/debug.d.ts +126 -0
- package/dist/debug.js +21 -0
- package/dist/graphql/objects/index.d.cts +4 -11
- package/dist/graphql/objects/index.d.ts +4 -11
- package/dist/graphql/objects/index.js +2 -4
- package/dist/index.cjs +18219 -20818
- package/dist/index.d.cts +15 -768
- package/dist/index.d.ts +15 -768
- package/dist/index.js +82 -76
- package/dist/index.node.cjs +23831 -26538
- package/dist/index.node.d.cts +191 -33
- package/dist/index.node.d.ts +191 -33
- package/dist/index.node.js +87 -181
- package/dist/native/index.cjs +17835 -20519
- package/dist/native/index.d.cts +1466 -1546
- package/dist/native/index.d.ts +1466 -1546
- package/dist/native/index.js +22605 -25286
- package/dist/proto/lrc20.d.cts +2 -2
- package/dist/proto/lrc20.d.ts +2 -2
- package/dist/proto/lrc20.js +3098 -46
- package/dist/proto/spark.cjs +241 -7
- 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.cjs +22 -2
- package/dist/proto/spark_token.d.cts +8 -1
- package/dist/proto/spark_token.d.ts +8 -1
- package/dist/proto/spark_token.js +2 -2
- package/dist/{sdk-types-CKBsylfW.d.ts → sdk-types-DCIVdKUT.d.ts} +1 -1
- package/dist/{sdk-types-Ct8xmN7l.d.cts → sdk-types-DJ2ve9YY.d.cts} +1 -1
- package/dist/{spark-DbzGfse6.d.ts → spark-BUOx3U7Q.d.cts} +103 -5
- package/dist/{spark-DbzGfse6.d.cts → spark-BUOx3U7Q.d.ts} +103 -5
- package/dist/spark-wallet-CF8Oxjqs.d.ts +935 -0
- package/dist/spark-wallet-DOLSa3oF.d.cts +935 -0
- package/dist/spark_bindings/native/index.d.cts +1 -1
- package/dist/spark_bindings/native/index.d.ts +1 -1
- package/dist/spark_bindings/wasm/index.d.cts +1 -1
- package/dist/spark_bindings/wasm/index.d.ts +1 -1
- package/dist/{services/index.cjs → tests/test-utils.cjs} +9788 -10263
- package/dist/tests/test-utils.d.cts +79 -0
- package/dist/tests/test-utils.d.ts +79 -0
- package/dist/tests/test-utils.js +93 -0
- package/dist/types/index.cjs +239 -7
- package/dist/types/index.d.cts +5 -9
- package/dist/types/index.d.ts +5 -9
- package/dist/types/index.js +4 -6
- package/dist/{types-C-Rp0Oo7.d.ts → types-BADxR3bm.d.cts} +1 -1
- package/dist/{types-C-Rp0Oo7.d.cts → types-BADxR3bm.d.ts} +1 -1
- package/dist/{index-COm59SPw.d.ts → xchain-address-C2xMs9nz.d.cts} +6 -94
- package/dist/{index-CKL5DodV.d.cts → xchain-address-Ckto9oEz.d.ts} +6 -94
- package/package.json +9 -33
- package/src/debug.ts +13 -0
- package/src/graphql/client.ts +59 -20
- package/src/index.node.ts +28 -2
- package/src/index.ts +31 -1
- package/src/native/index.ts +16 -2
- package/src/proto/mock.ts +76 -0
- package/src/proto/spark.ts +354 -6
- package/src/proto/spark_token.ts +34 -2
- package/src/services/config.ts +4 -6
- package/src/services/connection.ts +131 -64
- package/src/services/coop-exit.ts +6 -3
- package/src/services/deposit.ts +9 -8
- package/src/services/lightning.ts +4 -3
- package/src/services/signing.ts +10 -6
- package/src/services/token-transactions.ts +100 -85
- package/src/services/transfer.ts +88 -60
- package/src/services/tree-creation.ts +17 -9
- package/src/services/wallet-config.ts +17 -9
- package/src/signer/signer.react-native.ts +5 -10
- package/src/signer/signer.ts +269 -339
- package/src/signer/types.ts +63 -0
- package/src/spark-wallet/spark-wallet.ts +226 -149
- package/src/spark-wallet/types.ts +22 -8
- package/src/tests/integration/adaptor-signature.test.ts +8 -9
- package/src/tests/integration/coop-exit.test.ts +214 -202
- package/src/tests/integration/lightning.test.ts +128 -103
- package/src/tests/integration/swap.test.ts +116 -84
- package/src/tests/integration/transfer.test.ts +291 -214
- package/src/tests/integration/tree-creation.test.ts +0 -5
- package/src/tests/integration/wallet.test.ts +1 -0
- package/src/tests/isHermeticTest.ts +3 -24
- package/src/tests/{test-util.ts → test-utils.ts} +13 -11
- package/src/tests/token-identifier.test.ts +6 -6
- package/src/tests/wrapWithOtelSpan.test.ts +1 -1
- package/src/{address → utils}/address.ts +1 -1
- package/src/utils/crypto.ts +19 -9
- package/src/utils/index.ts +2 -0
- package/src/utils/network.ts +17 -0
- package/src/utils/secret-sharing.ts +1 -2
- package/src/utils/signing.ts +1 -1
- package/src/utils/token-identifier.ts +27 -21
- package/src/utils/token-transaction-validation.ts +34 -0
- package/src/utils/token-transactions.ts +12 -8
- package/src/utils/unilateral-exit.ts +32 -0
- package/src/utils/xchain-address.ts +1 -1
- package/dist/BitcoinNetwork-TnABML0T.d.cts +0 -18
- package/dist/BitcoinNetwork-TnABML0T.d.ts +0 -18
- package/dist/LightningSendFeeEstimateInput-BgOhEAI-.d.cts +0 -10
- package/dist/LightningSendFeeEstimateInput-BgOhEAI-.d.ts +0 -10
- package/dist/address/index.cjs +0 -458
- package/dist/address/index.d.cts +0 -32
- package/dist/address/index.d.ts +0 -32
- package/dist/address/index.js +0 -17
- package/dist/chunk-4EMV7HHW.js +0 -277
- package/dist/chunk-C2S227QR.js +0 -2336
- package/dist/chunk-DXR2PXJU.js +0 -1122
- package/dist/chunk-GSI4OLXZ.js +0 -117
- package/dist/chunk-HHNQ3ZHC.js +0 -170
- package/dist/chunk-HMLOC6TE.js +0 -14
- package/dist/chunk-HSCLBJEL.js +0 -113
- package/dist/chunk-HWJWKEIU.js +0 -75
- package/dist/chunk-JB64OQES.js +0 -7095
- package/dist/chunk-KMUMFYFX.js +0 -137
- package/dist/chunk-N5VZVCGJ.js +0 -622
- package/dist/chunk-NSJF5F5O.js +0 -325
- package/dist/chunk-NTFKFRQ2.js +0 -3146
- package/dist/chunk-OFCJFZ4I.js +0 -24
- package/dist/chunk-QNNSEJ4P.js +0 -232
- package/dist/chunk-UXDODSDT.js +0 -838
- package/dist/chunk-VTUGIIWI.js +0 -0
- package/dist/chunk-Z5HIAYFT.js +0 -84
- package/dist/network-Css46DAz.d.cts +0 -46
- package/dist/network-hynb7iTZ.d.ts +0 -46
- package/dist/services/config.d.cts +0 -42
- package/dist/services/config.d.ts +0 -42
- package/dist/services/config.js +0 -17
- package/dist/services/connection.cjs +0 -17691
- package/dist/services/connection.d.cts +0 -95
- package/dist/services/connection.d.ts +0 -95
- package/dist/services/connection.js +0 -11
- package/dist/services/index.d.cts +0 -21
- package/dist/services/index.d.ts +0 -21
- package/dist/services/index.js +0 -58
- package/dist/services/lrc-connection.cjs +0 -4713
- package/dist/services/lrc-connection.d.cts +0 -34
- package/dist/services/lrc-connection.d.ts +0 -34
- package/dist/services/lrc-connection.js +0 -11
- package/dist/services/token-transactions.cjs +0 -2877
- package/dist/services/token-transactions.d.cts +0 -75
- package/dist/services/token-transactions.d.ts +0 -75
- package/dist/services/token-transactions.js +0 -15
- package/dist/services/wallet-config.cjs +0 -340
- package/dist/services/wallet-config.d.cts +0 -56
- package/dist/services/wallet-config.d.ts +0 -56
- package/dist/services/wallet-config.js +0 -33
- package/dist/signer/signer.cjs +0 -2004
- package/dist/signer/signer.d.cts +0 -10
- package/dist/signer/signer.d.ts +0 -10
- package/dist/signer/signer.js +0 -24
- package/dist/signer-BP6F__oR.d.cts +0 -187
- package/dist/signer-BVZJXcq7.d.ts +0 -187
- package/dist/utils/index.cjs +0 -2947
- package/dist/utils/index.d.cts +0 -18
- package/dist/utils/index.d.ts +0 -18
- package/dist/utils/index.js +0 -157
- package/ios/spark_frost.kt +0 -1900
- package/src/address/index.ts +0 -1
- package/src/services/lrc-connection.ts +0 -215
- /package/dist/{chunk-L3EHBOUX.js → chunk-BYXBJQAS.js} +0 -0
package/src/proto/spark_token.ts
CHANGED
|
@@ -332,7 +332,16 @@ export interface TokenTransactionConfirmationMetadata {
|
|
|
332
332
|
export interface TokenTransactionWithStatus {
|
|
333
333
|
tokenTransaction: TokenTransaction | undefined;
|
|
334
334
|
status: TokenTransactionStatus;
|
|
335
|
-
confirmationMetadata:
|
|
335
|
+
confirmationMetadata:
|
|
336
|
+
| TokenTransactionConfirmationMetadata
|
|
337
|
+
| undefined;
|
|
338
|
+
/**
|
|
339
|
+
* In rare cases the above reconstructed token transaction may not match the original token transaction due to:
|
|
340
|
+
* a) a pre-empted transfer transaction having its input TTXOs remapped to the newer transaction
|
|
341
|
+
* b) proto migrations or field deprecations resulting in missing/swapped fields (eg. token public key -> token identifier)
|
|
342
|
+
* Include the original hash to ensure clients can reconcile this transaction with the original if needed.
|
|
343
|
+
*/
|
|
344
|
+
tokenTransactionHash: Uint8Array;
|
|
336
345
|
}
|
|
337
346
|
|
|
338
347
|
function createBaseTokenOutputToSpend(): TokenOutputToSpend {
|
|
@@ -2674,7 +2683,12 @@ export const TokenTransactionConfirmationMetadata: MessageFns<TokenTransactionCo
|
|
|
2674
2683
|
};
|
|
2675
2684
|
|
|
2676
2685
|
function createBaseTokenTransactionWithStatus(): TokenTransactionWithStatus {
|
|
2677
|
-
return {
|
|
2686
|
+
return {
|
|
2687
|
+
tokenTransaction: undefined,
|
|
2688
|
+
status: 0,
|
|
2689
|
+
confirmationMetadata: undefined,
|
|
2690
|
+
tokenTransactionHash: new Uint8Array(0),
|
|
2691
|
+
};
|
|
2678
2692
|
}
|
|
2679
2693
|
|
|
2680
2694
|
export const TokenTransactionWithStatus: MessageFns<TokenTransactionWithStatus> = {
|
|
@@ -2688,6 +2702,9 @@ export const TokenTransactionWithStatus: MessageFns<TokenTransactionWithStatus>
|
|
|
2688
2702
|
if (message.confirmationMetadata !== undefined) {
|
|
2689
2703
|
TokenTransactionConfirmationMetadata.encode(message.confirmationMetadata, writer.uint32(26).fork()).join();
|
|
2690
2704
|
}
|
|
2705
|
+
if (message.tokenTransactionHash.length !== 0) {
|
|
2706
|
+
writer.uint32(34).bytes(message.tokenTransactionHash);
|
|
2707
|
+
}
|
|
2691
2708
|
return writer;
|
|
2692
2709
|
},
|
|
2693
2710
|
|
|
@@ -2722,6 +2739,14 @@ export const TokenTransactionWithStatus: MessageFns<TokenTransactionWithStatus>
|
|
|
2722
2739
|
message.confirmationMetadata = TokenTransactionConfirmationMetadata.decode(reader, reader.uint32());
|
|
2723
2740
|
continue;
|
|
2724
2741
|
}
|
|
2742
|
+
case 4: {
|
|
2743
|
+
if (tag !== 34) {
|
|
2744
|
+
break;
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
message.tokenTransactionHash = reader.bytes();
|
|
2748
|
+
continue;
|
|
2749
|
+
}
|
|
2725
2750
|
}
|
|
2726
2751
|
if ((tag & 7) === 4 || tag === 0) {
|
|
2727
2752
|
break;
|
|
@@ -2738,6 +2763,9 @@ export const TokenTransactionWithStatus: MessageFns<TokenTransactionWithStatus>
|
|
|
2738
2763
|
confirmationMetadata: isSet(object.confirmationMetadata)
|
|
2739
2764
|
? TokenTransactionConfirmationMetadata.fromJSON(object.confirmationMetadata)
|
|
2740
2765
|
: undefined,
|
|
2766
|
+
tokenTransactionHash: isSet(object.tokenTransactionHash)
|
|
2767
|
+
? bytesFromBase64(object.tokenTransactionHash)
|
|
2768
|
+
: new Uint8Array(0),
|
|
2741
2769
|
};
|
|
2742
2770
|
},
|
|
2743
2771
|
|
|
@@ -2752,6 +2780,9 @@ export const TokenTransactionWithStatus: MessageFns<TokenTransactionWithStatus>
|
|
|
2752
2780
|
if (message.confirmationMetadata !== undefined) {
|
|
2753
2781
|
obj.confirmationMetadata = TokenTransactionConfirmationMetadata.toJSON(message.confirmationMetadata);
|
|
2754
2782
|
}
|
|
2783
|
+
if (message.tokenTransactionHash.length !== 0) {
|
|
2784
|
+
obj.tokenTransactionHash = base64FromBytes(message.tokenTransactionHash);
|
|
2785
|
+
}
|
|
2755
2786
|
return obj;
|
|
2756
2787
|
},
|
|
2757
2788
|
|
|
@@ -2767,6 +2798,7 @@ export const TokenTransactionWithStatus: MessageFns<TokenTransactionWithStatus>
|
|
|
2767
2798
|
message.confirmationMetadata = (object.confirmationMetadata !== undefined && object.confirmationMetadata !== null)
|
|
2768
2799
|
? TokenTransactionConfirmationMetadata.fromPartial(object.confirmationMetadata)
|
|
2769
2800
|
: undefined;
|
|
2801
|
+
message.tokenTransactionHash = object.tokenTransactionHash ?? new Uint8Array(0);
|
|
2770
2802
|
return message;
|
|
2771
2803
|
},
|
|
2772
2804
|
};
|
package/src/services/config.ts
CHANGED
|
@@ -8,9 +8,7 @@ import { DefaultSparkSigner, SparkSigner } from "../signer/signer.js";
|
|
|
8
8
|
import { Network, NetworkToProto, NetworkType } from "../utils/network.js";
|
|
9
9
|
import {
|
|
10
10
|
ConfigOptions,
|
|
11
|
-
|
|
12
|
-
MAINNET_WALLET_CONFIG,
|
|
13
|
-
REGTEST_WALLET_CONFIG,
|
|
11
|
+
WalletConfig,
|
|
14
12
|
SigningOperator,
|
|
15
13
|
} from "./wallet-config.js";
|
|
16
14
|
import { ConfigurationError } from "../errors/types.js";
|
|
@@ -39,11 +37,11 @@ export class WalletConfigService
|
|
|
39
37
|
private getDefaultConfig(network: Network): Required<ConfigOptions> {
|
|
40
38
|
switch (network) {
|
|
41
39
|
case Network.MAINNET:
|
|
42
|
-
return
|
|
40
|
+
return WalletConfig.MAINNET;
|
|
43
41
|
case Network.REGTEST:
|
|
44
|
-
return
|
|
42
|
+
return WalletConfig.REGTEST;
|
|
45
43
|
default:
|
|
46
|
-
return
|
|
44
|
+
return WalletConfig.LOCAL;
|
|
47
45
|
}
|
|
48
46
|
}
|
|
49
47
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isNode } from "@lightsparkdev/core";
|
|
1
|
+
import { isError, isNode } from "@lightsparkdev/core";
|
|
2
2
|
import { sha256 } from "@noble/hashes/sha2";
|
|
3
3
|
import type { Channel, ClientFactory } from "nice-grpc";
|
|
4
4
|
import { retryMiddleware } from "nice-grpc-client-middleware-retry";
|
|
@@ -23,6 +23,10 @@ import {
|
|
|
23
23
|
SparkTokenServiceDefinition,
|
|
24
24
|
} from "../proto/spark_token.js";
|
|
25
25
|
|
|
26
|
+
type SparkAuthnServiceClientWithClose = SparkAuthnServiceClient & {
|
|
27
|
+
close?: () => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
26
30
|
export class ConnectionManager {
|
|
27
31
|
private config: WalletConfigService;
|
|
28
32
|
private clients: Map<
|
|
@@ -52,6 +56,9 @@ export class ConnectionManager {
|
|
|
52
56
|
}
|
|
53
57
|
> = new Map();
|
|
54
58
|
|
|
59
|
+
// Tracks in-flight authenticate() promises so concurrent callers share one
|
|
60
|
+
private authPromises: Map<string, Promise<string>> = new Map();
|
|
61
|
+
|
|
55
62
|
constructor(config: WalletConfigService) {
|
|
56
63
|
this.config = config;
|
|
57
64
|
}
|
|
@@ -231,57 +238,105 @@ export class ConnectionManager {
|
|
|
231
238
|
}
|
|
232
239
|
|
|
233
240
|
private async authenticate(address: string, certPath?: string) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
241
|
+
const existing = this.authPromises.get(address);
|
|
242
|
+
if (existing) {
|
|
243
|
+
return existing;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const authPromise = (async () => {
|
|
247
|
+
const MAX_ATTEMPTS = 3;
|
|
248
|
+
let lastError: Error | undefined;
|
|
249
|
+
|
|
250
|
+
/* React Native can cause some outgoing requests to be paused which can result
|
|
251
|
+
in challenges expiring, so we'll retry any authentication failures: */
|
|
252
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
253
|
+
let sparkAuthnClient: SparkAuthnServiceClientWithClose | undefined;
|
|
254
|
+
try {
|
|
255
|
+
const identityPublicKey =
|
|
256
|
+
await this.config.signer.getIdentityPublicKey();
|
|
257
|
+
sparkAuthnClient = await this.createSparkAuthnGrpcConnection(
|
|
258
|
+
address,
|
|
259
|
+
certPath,
|
|
260
|
+
);
|
|
240
261
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
262
|
+
const challengeResp = await sparkAuthnClient.get_challenge({
|
|
263
|
+
publicKey: identityPublicKey,
|
|
264
|
+
});
|
|
244
265
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
266
|
+
if (!challengeResp.protectedChallenge?.challenge) {
|
|
267
|
+
throw new AuthenticationError("Invalid challenge response", {
|
|
268
|
+
endpoint: "get_challenge",
|
|
269
|
+
reason: "Missing challenge in response",
|
|
270
|
+
});
|
|
271
|
+
}
|
|
251
272
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
273
|
+
const challengeBytes = Challenge.encode(
|
|
274
|
+
challengeResp.protectedChallenge.challenge,
|
|
275
|
+
).finish();
|
|
276
|
+
const hash = sha256(challengeBytes);
|
|
256
277
|
|
|
257
|
-
|
|
258
|
-
|
|
278
|
+
const derSignatureBytes =
|
|
279
|
+
await this.config.signer.signMessageWithIdentityKey(hash);
|
|
259
280
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
281
|
+
const verifyResp = await sparkAuthnClient.verify_challenge({
|
|
282
|
+
protectedChallenge: challengeResp.protectedChallenge,
|
|
283
|
+
signature: derSignatureBytes,
|
|
284
|
+
publicKey: identityPublicKey,
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
sparkAuthnClient.close?.();
|
|
288
|
+
return verifyResp.sessionToken;
|
|
289
|
+
} catch (error: unknown) {
|
|
290
|
+
if (isError(error)) {
|
|
291
|
+
sparkAuthnClient?.close?.();
|
|
292
|
+
|
|
293
|
+
if (error.message.includes("challenge expired")) {
|
|
294
|
+
console.warn(
|
|
295
|
+
`Authentication attempt ${attempt + 1} failed due to expired challenge, retrying...`,
|
|
296
|
+
);
|
|
297
|
+
lastError = error;
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
throw new AuthenticationError(
|
|
302
|
+
"Authentication failed",
|
|
303
|
+
{
|
|
304
|
+
endpoint: "authenticate",
|
|
305
|
+
reason: error.message,
|
|
306
|
+
},
|
|
307
|
+
error,
|
|
308
|
+
);
|
|
309
|
+
} else {
|
|
310
|
+
lastError = new Error(
|
|
311
|
+
`Unknown error during authentication: ${String(error)}`,
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
265
316
|
|
|
266
|
-
sparkAuthnClient.close?.();
|
|
267
|
-
return verifyResp.sessionToken;
|
|
268
|
-
} catch (error: any) {
|
|
269
|
-
console.error("Authentication error:", error);
|
|
270
317
|
throw new AuthenticationError(
|
|
271
|
-
"Authentication failed",
|
|
318
|
+
"Authentication failed after retrying expired challenges",
|
|
272
319
|
{
|
|
273
320
|
endpoint: "authenticate",
|
|
274
|
-
reason: error
|
|
321
|
+
reason: lastError?.message ?? "Unknown error",
|
|
275
322
|
},
|
|
276
|
-
|
|
323
|
+
lastError,
|
|
277
324
|
);
|
|
325
|
+
})();
|
|
326
|
+
|
|
327
|
+
this.authPromises.set(address, authPromise);
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
return await authPromise;
|
|
331
|
+
} finally {
|
|
332
|
+
this.authPromises.delete(address);
|
|
278
333
|
}
|
|
279
334
|
}
|
|
280
335
|
|
|
281
336
|
private async createSparkAuthnGrpcConnection(
|
|
282
337
|
address: string,
|
|
283
338
|
certPath?: string,
|
|
284
|
-
): Promise<
|
|
339
|
+
): Promise<SparkAuthnServiceClientWithClose> {
|
|
285
340
|
const channel = await this.createChannelWithTLS(address, certPath);
|
|
286
341
|
const authnMiddleware = this.createAuthnMiddleware();
|
|
287
342
|
return this.createGrpcClient<SparkAuthnServiceClient>(
|
|
@@ -335,6 +390,32 @@ export class ConnectionManager {
|
|
|
335
390
|
}
|
|
336
391
|
}
|
|
337
392
|
|
|
393
|
+
private async *handleMiddlewareError(
|
|
394
|
+
error: unknown,
|
|
395
|
+
address: string,
|
|
396
|
+
call: ClientMiddlewareCall<any, any>,
|
|
397
|
+
metadata: Metadata,
|
|
398
|
+
options: SparkCallOptions,
|
|
399
|
+
) {
|
|
400
|
+
if (isError(error)) {
|
|
401
|
+
if (error.message.includes("token has expired")) {
|
|
402
|
+
const newAuthToken = await this.authenticate(address);
|
|
403
|
+
const clientData = this.clients.get(address);
|
|
404
|
+
if (!clientData) {
|
|
405
|
+
throw new Error(`No client found for address: ${address}`);
|
|
406
|
+
}
|
|
407
|
+
clientData.authToken = newAuthToken;
|
|
408
|
+
|
|
409
|
+
return yield* call.next(call.request, {
|
|
410
|
+
...options,
|
|
411
|
+
metadata: metadata.set("Authorization", `Bearer ${newAuthToken}`),
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
throw error;
|
|
417
|
+
}
|
|
418
|
+
|
|
338
419
|
private createNodeMiddleware(address: string, initialAuthToken: string) {
|
|
339
420
|
return async function* (
|
|
340
421
|
this: ConnectionManager,
|
|
@@ -353,21 +434,14 @@ export class ConnectionManager {
|
|
|
353
434
|
`Bearer ${this.clients.get(address)?.authToken || initialAuthToken}`,
|
|
354
435
|
),
|
|
355
436
|
});
|
|
356
|
-
} catch (error:
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
return yield* call.next(call.request, {
|
|
366
|
-
...options,
|
|
367
|
-
metadata: metadata.set("Authorization", `Bearer ${newAuthToken}`),
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
throw error;
|
|
437
|
+
} catch (error: unknown) {
|
|
438
|
+
return yield* this.handleMiddlewareError(
|
|
439
|
+
error,
|
|
440
|
+
address,
|
|
441
|
+
call,
|
|
442
|
+
metadata,
|
|
443
|
+
options,
|
|
444
|
+
);
|
|
371
445
|
}
|
|
372
446
|
}.bind(this);
|
|
373
447
|
}
|
|
@@ -393,20 +467,13 @@ export class ConnectionManager {
|
|
|
393
467
|
),
|
|
394
468
|
});
|
|
395
469
|
} catch (error: any) {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
return yield* call.next(call.request, {
|
|
405
|
-
...options,
|
|
406
|
-
metadata: metadata.set("Authorization", `Bearer ${newAuthToken}`),
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
throw error;
|
|
470
|
+
return yield* this.handleMiddlewareError(
|
|
471
|
+
error,
|
|
472
|
+
address,
|
|
473
|
+
call,
|
|
474
|
+
metadata,
|
|
475
|
+
options,
|
|
476
|
+
);
|
|
410
477
|
}
|
|
411
478
|
}.bind(this);
|
|
412
479
|
}
|
|
@@ -16,8 +16,8 @@ import { getNextTransactionSequence } from "../utils/transaction.js";
|
|
|
16
16
|
import { WalletConfigService } from "./config.js";
|
|
17
17
|
import { ConnectionManager } from "./connection.js";
|
|
18
18
|
import { SigningService } from "./signing.js";
|
|
19
|
-
import { BaseTransferService, LeafRefundSigningData } from "./transfer.js";
|
|
20
19
|
import type { LeafKeyTweak } from "./transfer.js";
|
|
20
|
+
import { BaseTransferService, LeafRefundSigningData } from "./transfer.js";
|
|
21
21
|
|
|
22
22
|
export type GetConnectorRefundSignaturesParams = {
|
|
23
23
|
leaves: LeafKeyTweak[];
|
|
@@ -50,6 +50,7 @@ export class CoopExitService extends BaseTransferService {
|
|
|
50
50
|
connectorOutputs,
|
|
51
51
|
receiverPubKey,
|
|
52
52
|
);
|
|
53
|
+
|
|
53
54
|
const transferTweak = await this.deliverTransferPackage(
|
|
54
55
|
transfer,
|
|
55
56
|
leaves,
|
|
@@ -152,7 +153,9 @@ export class CoopExitService extends BaseTransferService {
|
|
|
152
153
|
const signingJob: LeafRefundTxSigningJob = {
|
|
153
154
|
leafId: leaf.leaf.id,
|
|
154
155
|
refundTxSigningJob: {
|
|
155
|
-
signingPublicKey:
|
|
156
|
+
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
157
|
+
leaf.keyDerivation,
|
|
158
|
+
),
|
|
156
159
|
rawTx: refundTx.toBytes(),
|
|
157
160
|
signingNonceCommitment: signingNonceCommitment,
|
|
158
161
|
},
|
|
@@ -164,7 +167,7 @@ export class CoopExitService extends BaseTransferService {
|
|
|
164
167
|
signingJobs.push(signingJob);
|
|
165
168
|
const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
|
|
166
169
|
leafDataMap.set(leaf.leaf.id, {
|
|
167
|
-
|
|
170
|
+
keyDerivation: leaf.keyDerivation,
|
|
168
171
|
refundTx,
|
|
169
172
|
signingNonceCommitment,
|
|
170
173
|
tx,
|
package/src/services/deposit.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
GenerateDepositAddressResponse,
|
|
13
13
|
StartDepositTreeCreationResponse,
|
|
14
14
|
} from "../proto/spark.js";
|
|
15
|
+
import { KeyDerivation } from "../signer/types.js";
|
|
15
16
|
import {
|
|
16
17
|
getP2TRAddressFromPublicKey,
|
|
17
18
|
getSigHashFromTx,
|
|
@@ -20,10 +21,7 @@ import {
|
|
|
20
21
|
import { subtractPublicKeys } from "../utils/keys.js";
|
|
21
22
|
import { getNetwork } from "../utils/network.js";
|
|
22
23
|
import { proofOfPossessionMessageHashForDepositAddress } from "../utils/proof.js";
|
|
23
|
-
import {
|
|
24
|
-
DEFAULT_FEE_SATS,
|
|
25
|
-
getEphemeralAnchorOutput,
|
|
26
|
-
} from "../utils/transaction.js";
|
|
24
|
+
import { getEphemeralAnchorOutput } from "../utils/transaction.js";
|
|
27
25
|
import { WalletConfigService } from "./config.js";
|
|
28
26
|
import { ConnectionManager } from "./connection.js";
|
|
29
27
|
|
|
@@ -39,7 +37,7 @@ export type GenerateDepositAddressParams = {
|
|
|
39
37
|
};
|
|
40
38
|
|
|
41
39
|
export type CreateTreeRootParams = {
|
|
42
|
-
|
|
40
|
+
keyDerivation: KeyDerivation;
|
|
43
41
|
verifyingKey: Uint8Array;
|
|
44
42
|
depositTx: Transaction;
|
|
45
43
|
vout: number;
|
|
@@ -182,7 +180,7 @@ export class DepositService {
|
|
|
182
180
|
}
|
|
183
181
|
|
|
184
182
|
async createTreeRoot({
|
|
185
|
-
|
|
183
|
+
keyDerivation,
|
|
186
184
|
verifyingKey,
|
|
187
185
|
depositTx,
|
|
188
186
|
vout,
|
|
@@ -242,6 +240,9 @@ export class DepositService {
|
|
|
242
240
|
sequence,
|
|
243
241
|
});
|
|
244
242
|
|
|
243
|
+
const signingPubKey =
|
|
244
|
+
await this.config.signer.getPublicKeyFromDerivation(keyDerivation);
|
|
245
|
+
|
|
245
246
|
const refundP2trAddress = getP2TRAddressFromPublicKey(
|
|
246
247
|
signingPubKey,
|
|
247
248
|
this.config.getNetwork(),
|
|
@@ -346,7 +347,7 @@ export class DepositService {
|
|
|
346
347
|
const rootSignature = await this.config.signer.signFrost({
|
|
347
348
|
message: rootTxSighash,
|
|
348
349
|
publicKey: signingPubKey,
|
|
349
|
-
|
|
350
|
+
keyDerivation,
|
|
350
351
|
verifyingKey,
|
|
351
352
|
selfCommitment: rootNonceCommitment,
|
|
352
353
|
statechainCommitments:
|
|
@@ -358,7 +359,7 @@ export class DepositService {
|
|
|
358
359
|
const refundSignature = await this.config.signer.signFrost({
|
|
359
360
|
message: refundTxSighash,
|
|
360
361
|
publicKey: signingPubKey,
|
|
361
|
-
|
|
362
|
+
keyDerivation,
|
|
362
363
|
verifyingKey,
|
|
363
364
|
selfCommitment: refundNonceCommitment,
|
|
364
365
|
statechainCommitments:
|
|
@@ -25,8 +25,6 @@ import { SigningService } from "./signing.js";
|
|
|
25
25
|
import type { LeafKeyTweak } from "./transfer.js";
|
|
26
26
|
import { decodeInvoice } from "./bolt11-spark.js";
|
|
27
27
|
|
|
28
|
-
const crypto = getCrypto();
|
|
29
|
-
|
|
30
28
|
export type CreateLightningInvoiceParams = {
|
|
31
29
|
invoiceCreator: (
|
|
32
30
|
amountSats: number,
|
|
@@ -76,6 +74,7 @@ export class LightningService {
|
|
|
76
74
|
receiverIdentityPubkey,
|
|
77
75
|
descriptionHash,
|
|
78
76
|
}: CreateLightningInvoiceParams): Promise<LightningReceiveRequest> {
|
|
77
|
+
const crypto = getCrypto();
|
|
79
78
|
const randBytes = crypto.getRandomValues(new Uint8Array(32));
|
|
80
79
|
const preimage = numberToBytesBE(
|
|
81
80
|
bytesToNumberBE(randBytes) % secp256k1.CURVE.n,
|
|
@@ -237,7 +236,9 @@ export class LightningService {
|
|
|
237
236
|
);
|
|
238
237
|
}
|
|
239
238
|
|
|
240
|
-
amountSats = isZeroAmountInvoice
|
|
239
|
+
amountSats = isZeroAmountInvoice
|
|
240
|
+
? amountSatsToSend!
|
|
241
|
+
: Math.ceil(amountMsats / 1000);
|
|
241
242
|
|
|
242
243
|
if (isNaN(amountSats) || amountSats <= 0) {
|
|
243
244
|
throw new ValidationError("Invalid amount", {
|
package/src/services/signing.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { TransactionInput } from "@scure/btc-signer/psbt";
|
|
2
1
|
import { hexToBytes } from "@noble/curves/abstract/utils";
|
|
2
|
+
import { TransactionInput } from "@scure/btc-signer/psbt";
|
|
3
3
|
import { ValidationError } from "../errors/types.js";
|
|
4
4
|
import {
|
|
5
5
|
RequestedSigningCommitments,
|
|
6
6
|
UserSignedTxSigningJob,
|
|
7
7
|
} from "../proto/spark.js";
|
|
8
|
-
import type { LeafKeyTweak } from "./transfer.js";
|
|
9
|
-
import { WalletConfigService } from "./config.js";
|
|
10
8
|
import {
|
|
11
9
|
getSigHashFromTx,
|
|
12
10
|
getTxFromRawTxBytes,
|
|
@@ -16,6 +14,8 @@ import {
|
|
|
16
14
|
createRefundTx,
|
|
17
15
|
getNextTransactionSequence,
|
|
18
16
|
} from "../utils/transaction.js";
|
|
17
|
+
import { WalletConfigService } from "./config.js";
|
|
18
|
+
import type { LeafKeyTweak } from "./transfer.js";
|
|
19
19
|
|
|
20
20
|
export class SigningService {
|
|
21
21
|
private readonly config: WalletConfigService;
|
|
@@ -83,8 +83,10 @@ export class SigningService {
|
|
|
83
83
|
}
|
|
84
84
|
const signingResult = await this.config.signer.signFrost({
|
|
85
85
|
message: sighash,
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
keyDerivation: leaf.keyDerivation,
|
|
87
|
+
publicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
88
|
+
leaf.keyDerivation,
|
|
89
|
+
),
|
|
88
90
|
selfCommitment: signingCommitment,
|
|
89
91
|
statechainCommitments: signingNonceCommitments,
|
|
90
92
|
adaptorPubKey: new Uint8Array(),
|
|
@@ -93,7 +95,9 @@ export class SigningService {
|
|
|
93
95
|
|
|
94
96
|
leafSigningJobs.push({
|
|
95
97
|
leafId: leaf.leaf.id,
|
|
96
|
-
signingPublicKey:
|
|
98
|
+
signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
|
|
99
|
+
leaf.keyDerivation,
|
|
100
|
+
),
|
|
97
101
|
rawTx: refundTx.toBytes(),
|
|
98
102
|
signingNonceCommitment: signingCommitment,
|
|
99
103
|
userSignature: signingResult,
|