@buildonspark/spark-sdk 0.3.9 → 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 +11 -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 +322 -142
- package/dist/bare/index.d.cts +13 -3
- package/dist/bare/index.d.ts +13 -3
- package/dist/bare/index.js +321 -142
- package/dist/{chunk-S55NZT4P.js → chunk-27ILUWDJ.js} +1 -1
- package/dist/{chunk-O4C4HGQL.js → chunk-G3LHXHF3.js} +313 -133
- package/dist/{chunk-WRE2T22S.js → chunk-LOXWCMZL.js} +1 -1
- package/dist/{chunk-MFCM6GUD.js → chunk-WICAF6BS.js} +1 -1
- package/dist/debug.cjs +322 -143
- package/dist/debug.d.cts +5 -4
- package/dist/debug.d.ts +5 -4
- package/dist/debug.js +2 -2
- package/dist/index.cjs +323 -143
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +5 -3
- package/dist/index.node.cjs +323 -143
- package/dist/index.node.d.cts +4 -4
- package/dist/index.node.d.ts +4 -4
- package/dist/index.node.js +4 -2
- package/dist/{logging-DDeMLsVN.d.ts → logging-BNGm6dBp.d.ts} +3 -2
- package/dist/{logging-CXhvuqJJ.d.cts → logging-D3IfXfHG.d.cts} +3 -2
- package/dist/native/index.react-native.cjs +466 -145
- package/dist/native/index.react-native.d.cts +21 -3
- package/dist/native/index.react-native.d.ts +21 -3
- package/dist/native/index.react-native.js +462 -144
- package/dist/{spark-wallet.browser-Cz8c4kOW.d.ts → spark-wallet.browser-B2rGwjuM.d.ts} +1 -1
- package/dist/{spark-wallet.browser-CbYo8A_U.d.cts → spark-wallet.browser-Ck9No4Ks.d.cts} +1 -1
- package/dist/{spark-wallet.node-CmIvxtcC.d.ts → spark-wallet.node-BqmKsGPs.d.ts} +1 -1
- package/dist/{spark-wallet.node-4WQgWwB2.d.cts → spark-wallet.node-C2TIkyt4.d.cts} +1 -1
- package/dist/tests/test-utils.cjs +321 -143
- package/dist/tests/test-utils.d.cts +16 -2
- package/dist/tests/test-utils.d.ts +16 -2
- package/dist/tests/test-utils.js +4 -4
- package/dist/{token-transactions-CV8QD3I7.d.cts → token-transactions-Db8mkjnU.d.cts} +1 -1
- package/dist/{token-transactions-Bu023ztN.d.ts → token-transactions-DoMcrxXQ.d.ts} +1 -1
- package/dist/{wallet-config-Bmk2eAn8.d.ts → wallet-config-Bg3kWltL.d.ts} +11 -2
- package/dist/{wallet-config-DQw5llqA.d.cts → wallet-config-CuZKNo9S.d.cts} +11 -2
- 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/services/config.ts +5 -0
- 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/spark-wallet.ts +98 -76
- package/src/tests/integration/lightning.test.ts +0 -28
- package/src/tests/integration/static_deposit.test.ts +4 -8
- 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/unilateral-exit.ts +1 -40
|
@@ -17108,7 +17108,11 @@ var BASE_CONFIG = {
|
|
|
17108
17108
|
console: {
|
|
17109
17109
|
otel: false
|
|
17110
17110
|
},
|
|
17111
|
-
events: {}
|
|
17111
|
+
events: {},
|
|
17112
|
+
optimizationOptions: {
|
|
17113
|
+
auto: true,
|
|
17114
|
+
multiplicity: 0
|
|
17115
|
+
}
|
|
17112
17116
|
};
|
|
17113
17117
|
var LOCAL_WALLET_CONFIG = {
|
|
17114
17118
|
...BASE_CONFIG,
|
|
@@ -19714,7 +19718,7 @@ var isWebExtension = (
|
|
|
19714
19718
|
"chrome" in globalThis && globalThis.chrome.runtime?.id
|
|
19715
19719
|
);
|
|
19716
19720
|
var userAgent = "navigator" in globalThis ? globalThis.navigator.userAgent || "unknown-user-agent" : void 0;
|
|
19717
|
-
var packageVersion = true ? "0.
|
|
19721
|
+
var packageVersion = true ? "0.4.0" : "unknown";
|
|
19718
19722
|
var baseEnvStr = "unknown";
|
|
19719
19723
|
if (isBun) {
|
|
19720
19724
|
const bunVersion = "version" in globalThis.Bun ? globalThis.Bun.version : "unknown-version";
|
|
@@ -19790,6 +19794,63 @@ var DefaultSparkKeysGenerator = class {
|
|
|
19790
19794
|
};
|
|
19791
19795
|
}
|
|
19792
19796
|
};
|
|
19797
|
+
var TaprootOutputKeysGenerator = class {
|
|
19798
|
+
constructor(useAddressIndex = false) {
|
|
19799
|
+
this.useAddressIndex = useAddressIndex;
|
|
19800
|
+
}
|
|
19801
|
+
async deriveKeysFromSeed(seed, accountNumber) {
|
|
19802
|
+
const hdkey = HDKey.fromMasterSeed(seed);
|
|
19803
|
+
if (!hdkey.privateKey || !hdkey.publicKey) {
|
|
19804
|
+
throw new ValidationError("Failed to derive keys from seed", {
|
|
19805
|
+
field: "hdkey",
|
|
19806
|
+
value: seed
|
|
19807
|
+
});
|
|
19808
|
+
}
|
|
19809
|
+
const derivationPath = this.useAddressIndex ? `m/86'/0'/0'/0/${accountNumber}` : `m/86'/0'/${accountNumber}'/0/0`;
|
|
19810
|
+
const taprootInternalKey = hdkey.derive(derivationPath);
|
|
19811
|
+
let tweakedPrivateKey = taprootTweakPrivKey(taprootInternalKey.privateKey);
|
|
19812
|
+
let tweakedPublicKey = secp256k17.getPublicKey(tweakedPrivateKey);
|
|
19813
|
+
if (tweakedPublicKey[0] === 3) {
|
|
19814
|
+
tweakedPrivateKey = privateNegate(tweakedPrivateKey);
|
|
19815
|
+
tweakedPublicKey = secp256k17.getPublicKey(tweakedPrivateKey);
|
|
19816
|
+
}
|
|
19817
|
+
const identityKey = {
|
|
19818
|
+
publicKey: tweakedPublicKey,
|
|
19819
|
+
privateKey: tweakedPrivateKey
|
|
19820
|
+
};
|
|
19821
|
+
const signingKey = hdkey.derive(`${derivationPath}/1'`);
|
|
19822
|
+
const depositKey = hdkey.derive(`${derivationPath}/2'`);
|
|
19823
|
+
const staticDepositKey = hdkey.derive(`${derivationPath}/3'`);
|
|
19824
|
+
if (!signingKey.privateKey || !signingKey.publicKey || !depositKey.privateKey || !depositKey.publicKey || !staticDepositKey.privateKey || !staticDepositKey.publicKey) {
|
|
19825
|
+
throw new ValidationError(
|
|
19826
|
+
"Failed to derive all required keys from seed",
|
|
19827
|
+
{
|
|
19828
|
+
field: "derivedKeys"
|
|
19829
|
+
}
|
|
19830
|
+
);
|
|
19831
|
+
}
|
|
19832
|
+
return {
|
|
19833
|
+
identityKey: {
|
|
19834
|
+
privateKey: identityKey.privateKey,
|
|
19835
|
+
publicKey: identityKey.publicKey
|
|
19836
|
+
},
|
|
19837
|
+
signingHDKey: {
|
|
19838
|
+
hdKey: signingKey,
|
|
19839
|
+
privateKey: signingKey.privateKey,
|
|
19840
|
+
publicKey: signingKey.publicKey
|
|
19841
|
+
},
|
|
19842
|
+
depositKey: {
|
|
19843
|
+
privateKey: depositKey.privateKey,
|
|
19844
|
+
publicKey: depositKey.publicKey
|
|
19845
|
+
},
|
|
19846
|
+
staticDepositHDKey: {
|
|
19847
|
+
hdKey: staticDepositKey,
|
|
19848
|
+
privateKey: staticDepositKey.privateKey,
|
|
19849
|
+
publicKey: staticDepositKey.publicKey
|
|
19850
|
+
}
|
|
19851
|
+
};
|
|
19852
|
+
}
|
|
19853
|
+
};
|
|
19793
19854
|
var DefaultSparkSigner = class {
|
|
19794
19855
|
constructor({
|
|
19795
19856
|
sparkKeysGenerator
|
|
@@ -20108,6 +20169,13 @@ var DefaultSparkSigner = class {
|
|
|
20108
20169
|
tx.signIdx(privateKey, index);
|
|
20109
20170
|
}
|
|
20110
20171
|
};
|
|
20172
|
+
var TaprootSparkSigner = class extends DefaultSparkSigner {
|
|
20173
|
+
constructor(useAddressIndex = false) {
|
|
20174
|
+
super({
|
|
20175
|
+
sparkKeysGenerator: new TaprootOutputKeysGenerator(useAddressIndex)
|
|
20176
|
+
});
|
|
20177
|
+
}
|
|
20178
|
+
};
|
|
20111
20179
|
|
|
20112
20180
|
// src/signer/signer.react-native.ts
|
|
20113
20181
|
var ReactNativeSparkSigner = class extends DefaultSparkSigner {
|
|
@@ -20171,6 +20239,70 @@ var ReactNativeSparkSigner = class extends DefaultSparkSigner {
|
|
|
20171
20239
|
});
|
|
20172
20240
|
}
|
|
20173
20241
|
};
|
|
20242
|
+
var ReactNativeTaprootSparkSigner = class extends TaprootSparkSigner {
|
|
20243
|
+
constructor(useAddressIndex = false) {
|
|
20244
|
+
super(useAddressIndex);
|
|
20245
|
+
}
|
|
20246
|
+
async signFrost({
|
|
20247
|
+
message,
|
|
20248
|
+
keyDerivation,
|
|
20249
|
+
publicKey,
|
|
20250
|
+
verifyingKey,
|
|
20251
|
+
selfCommitment,
|
|
20252
|
+
statechainCommitments,
|
|
20253
|
+
adaptorPubKey
|
|
20254
|
+
}) {
|
|
20255
|
+
const signingPrivateKey = await this.getSigningPrivateKeyFromDerivation(keyDerivation);
|
|
20256
|
+
if (!signingPrivateKey) {
|
|
20257
|
+
throw new ValidationError("Private key not found for public key", {
|
|
20258
|
+
field: "privateKey"
|
|
20259
|
+
});
|
|
20260
|
+
}
|
|
20261
|
+
const commitment = selfCommitment.commitment;
|
|
20262
|
+
const nonce = this.commitmentToNonceMap.get(commitment);
|
|
20263
|
+
if (!nonce) {
|
|
20264
|
+
throw new ValidationError("Nonce not found for commitment", {
|
|
20265
|
+
field: "nonce"
|
|
20266
|
+
});
|
|
20267
|
+
}
|
|
20268
|
+
const keyPackage = {
|
|
20269
|
+
secretKey: signingPrivateKey,
|
|
20270
|
+
publicKey,
|
|
20271
|
+
verifyingKey
|
|
20272
|
+
};
|
|
20273
|
+
return NativeSparkFrost.signFrost({
|
|
20274
|
+
message,
|
|
20275
|
+
keyPackage,
|
|
20276
|
+
nonce,
|
|
20277
|
+
selfCommitment: commitment,
|
|
20278
|
+
statechainCommitments,
|
|
20279
|
+
adaptorPubKey
|
|
20280
|
+
});
|
|
20281
|
+
}
|
|
20282
|
+
async aggregateFrost({
|
|
20283
|
+
message,
|
|
20284
|
+
publicKey,
|
|
20285
|
+
verifyingKey,
|
|
20286
|
+
selfCommitment,
|
|
20287
|
+
statechainCommitments,
|
|
20288
|
+
adaptorPubKey,
|
|
20289
|
+
selfSignature,
|
|
20290
|
+
statechainSignatures,
|
|
20291
|
+
statechainPublicKeys
|
|
20292
|
+
}) {
|
|
20293
|
+
return NativeSparkFrost.aggregateFrost({
|
|
20294
|
+
message,
|
|
20295
|
+
statechainSignatures,
|
|
20296
|
+
statechainPublicKeys,
|
|
20297
|
+
verifyingKey,
|
|
20298
|
+
statechainCommitments,
|
|
20299
|
+
selfCommitment: selfCommitment.commitment,
|
|
20300
|
+
selfPublicKey: publicKey,
|
|
20301
|
+
selfSignature,
|
|
20302
|
+
adaptorPubKey
|
|
20303
|
+
});
|
|
20304
|
+
}
|
|
20305
|
+
};
|
|
20174
20306
|
|
|
20175
20307
|
// src/services/xhr-transport.ts
|
|
20176
20308
|
import { throwIfAborted } from "abort-controller-x";
|
|
@@ -20308,7 +20440,16 @@ function headersToMetadata(headers) {
|
|
|
20308
20440
|
const parts = line.split(": ");
|
|
20309
20441
|
const header = parts.shift() ?? "";
|
|
20310
20442
|
const value = parts.join(": ");
|
|
20311
|
-
|
|
20443
|
+
if (header.endsWith("-bin")) {
|
|
20444
|
+
try {
|
|
20445
|
+
metadata.set(header, Base64.toUint8Array(value));
|
|
20446
|
+
} catch (e) {
|
|
20447
|
+
console.warn(`Failed to decode binary metadata ${header}:`, e);
|
|
20448
|
+
metadata.set(header, value);
|
|
20449
|
+
}
|
|
20450
|
+
} else {
|
|
20451
|
+
metadata.set(header, value);
|
|
20452
|
+
}
|
|
20312
20453
|
});
|
|
20313
20454
|
return metadata;
|
|
20314
20455
|
}
|
|
@@ -20334,7 +20475,7 @@ function getStatusFromHttpCode(statusCode) {
|
|
|
20334
20475
|
}
|
|
20335
20476
|
}
|
|
20336
20477
|
function getErrorDetailsFromHttpResponse(statusCode, responseText) {
|
|
20337
|
-
return `Received HTTP ${statusCode} response: ` + (responseText
|
|
20478
|
+
return `Received HTTP ${statusCode} response: ` + (responseText?.length > 1e3 ? responseText?.slice(0, 1e3) + "... (truncated)" : responseText);
|
|
20338
20479
|
}
|
|
20339
20480
|
|
|
20340
20481
|
// src/spark-wallet/spark-wallet.ts
|
|
@@ -21566,6 +21707,9 @@ var WalletConfigService = class {
|
|
|
21566
21707
|
getEvents() {
|
|
21567
21708
|
return this.config.events;
|
|
21568
21709
|
}
|
|
21710
|
+
getOptimizationOptions() {
|
|
21711
|
+
return this.config.optimizationOptions;
|
|
21712
|
+
}
|
|
21569
21713
|
};
|
|
21570
21714
|
|
|
21571
21715
|
// src/services/coop-exit.ts
|
|
@@ -29438,6 +29582,14 @@ var _BitcoinFaucet = class _BitcoinFaucet {
|
|
|
29438
29582
|
async mineBlocks(numBlocks) {
|
|
29439
29583
|
return await this.generateToAddress(numBlocks, this.miningAddress);
|
|
29440
29584
|
}
|
|
29585
|
+
async mineBlocksAndWaitForMiningToComplete(numBlocks) {
|
|
29586
|
+
const startBlock = await this.getBlockCount();
|
|
29587
|
+
await this.mineBlocks(numBlocks);
|
|
29588
|
+
await this.waitForBlocksMined({
|
|
29589
|
+
startBlock,
|
|
29590
|
+
expectedIncrease: numBlocks
|
|
29591
|
+
});
|
|
29592
|
+
}
|
|
29441
29593
|
async call(method, params) {
|
|
29442
29594
|
try {
|
|
29443
29595
|
const { fetch, Headers: Headers2 } = getFetch();
|
|
@@ -29490,15 +29642,50 @@ var _BitcoinFaucet = class _BitcoinFaucet {
|
|
|
29490
29642
|
async getBlock(blockHash) {
|
|
29491
29643
|
return await this.call("getblock", [blockHash, 2]);
|
|
29492
29644
|
}
|
|
29645
|
+
async getBlockCount() {
|
|
29646
|
+
return await this.call("getblockcount", []);
|
|
29647
|
+
}
|
|
29648
|
+
async waitForBlocksMined({
|
|
29649
|
+
startBlock,
|
|
29650
|
+
expectedIncrease,
|
|
29651
|
+
timeoutMs = 3e4,
|
|
29652
|
+
intervalMs = 5e3
|
|
29653
|
+
}) {
|
|
29654
|
+
const deadline = Date.now() + timeoutMs;
|
|
29655
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
29656
|
+
const start = startBlock;
|
|
29657
|
+
const target = start + expectedIncrease;
|
|
29658
|
+
while (Date.now() < deadline) {
|
|
29659
|
+
const currentBlock = await this.getBlockCount();
|
|
29660
|
+
if (currentBlock >= target) return currentBlock;
|
|
29661
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
29662
|
+
}
|
|
29663
|
+
throw new Error(
|
|
29664
|
+
`Timed out waiting for ${expectedIncrease} blocks (target height ${target})`
|
|
29665
|
+
);
|
|
29666
|
+
}
|
|
29493
29667
|
async broadcastTx(txHex) {
|
|
29494
29668
|
let response = await this.call("sendrawtransaction", [txHex, 0]);
|
|
29495
29669
|
return response;
|
|
29496
29670
|
}
|
|
29671
|
+
async submitPackage(txHexs) {
|
|
29672
|
+
let response = await this.call("submitpackage", [txHexs]);
|
|
29673
|
+
return response;
|
|
29674
|
+
}
|
|
29497
29675
|
async getNewAddress() {
|
|
29498
29676
|
const key = secp256k112.utils.randomPrivateKey();
|
|
29499
29677
|
const pubKey = secp256k112.getPublicKey(key);
|
|
29500
29678
|
return getP2TRAddressFromPublicKey(pubKey, 4 /* LOCAL */);
|
|
29501
29679
|
}
|
|
29680
|
+
async getNewExternalWallet() {
|
|
29681
|
+
const key = secp256k112.utils.randomPrivateKey();
|
|
29682
|
+
const pubKey = secp256k112.getPublicKey(key);
|
|
29683
|
+
return {
|
|
29684
|
+
address: getP2TRAddressFromPublicKey(pubKey, 4 /* LOCAL */),
|
|
29685
|
+
key,
|
|
29686
|
+
pubKey
|
|
29687
|
+
};
|
|
29688
|
+
}
|
|
29502
29689
|
async sendToAddress(address, amount, blocksToGenerate = 1) {
|
|
29503
29690
|
const coin = await this.fund();
|
|
29504
29691
|
if (!coin) {
|
|
@@ -29556,75 +29743,6 @@ function chunkArray(arr, size) {
|
|
|
29556
29743
|
return chunks;
|
|
29557
29744
|
}
|
|
29558
29745
|
|
|
29559
|
-
// src/utils/optimize.ts
|
|
29560
|
-
var DENOMINATIONS = Array.from({ length: 28 }, (_, i) => 2 ** i);
|
|
29561
|
-
function assert(condition, message) {
|
|
29562
|
-
if (!condition) {
|
|
29563
|
-
throw new InternalValidationError(message || "Assertion failed");
|
|
29564
|
-
}
|
|
29565
|
-
}
|
|
29566
|
-
function sum(arr) {
|
|
29567
|
-
return arr.reduce((a, b) => a + b, 0);
|
|
29568
|
-
}
|
|
29569
|
-
function sorted(arr) {
|
|
29570
|
-
return [...arr].sort((a, b) => a - b);
|
|
29571
|
-
}
|
|
29572
|
-
function equals(a, b) {
|
|
29573
|
-
return a.length === b.length && a.every((val, index) => val === b[index]);
|
|
29574
|
-
}
|
|
29575
|
-
function greedyLeaves(amount) {
|
|
29576
|
-
const leaves = [];
|
|
29577
|
-
let remaining = amount;
|
|
29578
|
-
for (let i = DENOMINATIONS.length - 1; i >= 0; i--) {
|
|
29579
|
-
const leaf = DENOMINATIONS[i];
|
|
29580
|
-
if (typeof leaf === "number" && leaf > 0) {
|
|
29581
|
-
while (remaining >= leaf) {
|
|
29582
|
-
remaining -= leaf;
|
|
29583
|
-
leaves.push(leaf);
|
|
29584
|
-
}
|
|
29585
|
-
}
|
|
29586
|
-
}
|
|
29587
|
-
assert(sum(leaves) === amount, "greedy_leaves: sum mismatch");
|
|
29588
|
-
return sorted(leaves);
|
|
29589
|
-
}
|
|
29590
|
-
var Swap = class {
|
|
29591
|
-
constructor(inLeaves, outLeaves) {
|
|
29592
|
-
__publicField(this, "inLeaves");
|
|
29593
|
-
__publicField(this, "outLeaves");
|
|
29594
|
-
this.inLeaves = [...inLeaves];
|
|
29595
|
-
this.outLeaves = [...outLeaves];
|
|
29596
|
-
assert(
|
|
29597
|
-
sum(this.inLeaves) === sum(this.outLeaves),
|
|
29598
|
-
"Swap in/out leaves must sum to same value for swap: " + this.toString()
|
|
29599
|
-
);
|
|
29600
|
-
}
|
|
29601
|
-
toString() {
|
|
29602
|
-
return `Swap(in=${JSON.stringify(this.inLeaves)}, out=${JSON.stringify(this.outLeaves)})`;
|
|
29603
|
-
}
|
|
29604
|
-
};
|
|
29605
|
-
function maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap = 64) {
|
|
29606
|
-
const swaps = [];
|
|
29607
|
-
let batch = [];
|
|
29608
|
-
let leaves = sorted(inputLeaves);
|
|
29609
|
-
while (leaves.length > 0) {
|
|
29610
|
-
batch.push(leaves.shift());
|
|
29611
|
-
const target = greedyLeaves(sum(batch));
|
|
29612
|
-
if (batch.length >= maxLeavesPerSwap || target.length >= maxLeavesPerSwap) {
|
|
29613
|
-
if (!equals(target, batch)) {
|
|
29614
|
-
swaps.push(new Swap([...batch], target));
|
|
29615
|
-
}
|
|
29616
|
-
batch = [];
|
|
29617
|
-
}
|
|
29618
|
-
}
|
|
29619
|
-
if (batch.length > 0) {
|
|
29620
|
-
const target = greedyLeaves(sum(batch));
|
|
29621
|
-
if (!equals(target, batch)) {
|
|
29622
|
-
swaps.push(new Swap([...batch], target));
|
|
29623
|
-
}
|
|
29624
|
-
}
|
|
29625
|
-
return swaps;
|
|
29626
|
-
}
|
|
29627
|
-
|
|
29628
29746
|
// src/utils/retry.ts
|
|
29629
29747
|
var DEFAULT_RETRY_CONFIG = {
|
|
29630
29748
|
maxAttempts: 5,
|
|
@@ -29701,6 +29819,199 @@ var SparkWalletEvent = {
|
|
|
29701
29819
|
StreamReconnecting: "stream:reconnecting"
|
|
29702
29820
|
};
|
|
29703
29821
|
|
|
29822
|
+
// src/utils/optimize.ts
|
|
29823
|
+
var DENOMINATIONS = Array.from({ length: 28 }, (_, i) => 2 ** i);
|
|
29824
|
+
function assert(condition, message) {
|
|
29825
|
+
if (!condition) {
|
|
29826
|
+
throw new InternalValidationError(message || "Assertion failed");
|
|
29827
|
+
}
|
|
29828
|
+
}
|
|
29829
|
+
function sum(arr) {
|
|
29830
|
+
return arr.reduce((a, b) => a + b, 0);
|
|
29831
|
+
}
|
|
29832
|
+
function sorted(arr) {
|
|
29833
|
+
return [...arr].sort((a, b) => a - b);
|
|
29834
|
+
}
|
|
29835
|
+
function equals(a, b) {
|
|
29836
|
+
return a.length === b.length && a.every((val, index) => val === b[index]);
|
|
29837
|
+
}
|
|
29838
|
+
function countOccurrences(arr) {
|
|
29839
|
+
const map = /* @__PURE__ */ new Map();
|
|
29840
|
+
for (const x of arr) {
|
|
29841
|
+
map.set(x, (map.get(x) ?? 0) + 1);
|
|
29842
|
+
}
|
|
29843
|
+
return map;
|
|
29844
|
+
}
|
|
29845
|
+
function subtractCounters(a, b) {
|
|
29846
|
+
const result = /* @__PURE__ */ new Map();
|
|
29847
|
+
for (const [key, value] of a.entries()) {
|
|
29848
|
+
const diff = value - (b.get(key) ?? 0);
|
|
29849
|
+
if (diff > 0) {
|
|
29850
|
+
result.set(key, diff);
|
|
29851
|
+
}
|
|
29852
|
+
}
|
|
29853
|
+
return result;
|
|
29854
|
+
}
|
|
29855
|
+
function counterToFlatArray(counter) {
|
|
29856
|
+
const arr = [];
|
|
29857
|
+
for (const [k, v] of Array.from(counter.entries()).sort(
|
|
29858
|
+
(a, b) => a[0] - b[0]
|
|
29859
|
+
)) {
|
|
29860
|
+
for (let i = 0; i < v; i++) {
|
|
29861
|
+
arr.push(k);
|
|
29862
|
+
}
|
|
29863
|
+
}
|
|
29864
|
+
return arr;
|
|
29865
|
+
}
|
|
29866
|
+
function greedyLeaves(amount) {
|
|
29867
|
+
const leaves = [];
|
|
29868
|
+
let remaining = amount;
|
|
29869
|
+
for (let i = DENOMINATIONS.length - 1; i >= 0; i--) {
|
|
29870
|
+
const leaf = DENOMINATIONS[i];
|
|
29871
|
+
if (typeof leaf === "number" && leaf > 0) {
|
|
29872
|
+
while (remaining >= leaf) {
|
|
29873
|
+
remaining -= leaf;
|
|
29874
|
+
leaves.push(leaf);
|
|
29875
|
+
}
|
|
29876
|
+
}
|
|
29877
|
+
}
|
|
29878
|
+
assert(sum(leaves) === amount, "greedy_leaves: sum mismatch");
|
|
29879
|
+
return sorted(leaves);
|
|
29880
|
+
}
|
|
29881
|
+
function swapMinimizingLeaves(amount, multiplicity = 1) {
|
|
29882
|
+
const leaves = [];
|
|
29883
|
+
let remaining = amount;
|
|
29884
|
+
assert(multiplicity > 0, "multiplicity must be > 0");
|
|
29885
|
+
for (const leaf of DENOMINATIONS) {
|
|
29886
|
+
if (typeof leaf === "number" && leaf > 0) {
|
|
29887
|
+
for (let i = 0; i < multiplicity; i++) {
|
|
29888
|
+
if (remaining >= leaf) {
|
|
29889
|
+
remaining -= leaf;
|
|
29890
|
+
leaves.push(leaf);
|
|
29891
|
+
}
|
|
29892
|
+
}
|
|
29893
|
+
}
|
|
29894
|
+
}
|
|
29895
|
+
leaves.push(...greedyLeaves(remaining));
|
|
29896
|
+
assert(sum(leaves) === amount, "swap_minimizing_leaves: sum mismatch");
|
|
29897
|
+
return sorted(leaves);
|
|
29898
|
+
}
|
|
29899
|
+
var Swap = class {
|
|
29900
|
+
constructor(inLeaves, outLeaves) {
|
|
29901
|
+
__publicField(this, "inLeaves");
|
|
29902
|
+
__publicField(this, "outLeaves");
|
|
29903
|
+
this.inLeaves = [...inLeaves];
|
|
29904
|
+
this.outLeaves = [...outLeaves];
|
|
29905
|
+
assert(
|
|
29906
|
+
sum(this.inLeaves) === sum(this.outLeaves),
|
|
29907
|
+
"Swap in/out leaves must sum to same value for swap: " + this.toString()
|
|
29908
|
+
);
|
|
29909
|
+
}
|
|
29910
|
+
toString() {
|
|
29911
|
+
return `Swap(in=${JSON.stringify(this.inLeaves)}, out=${JSON.stringify(this.outLeaves)})`;
|
|
29912
|
+
}
|
|
29913
|
+
};
|
|
29914
|
+
function maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap = 64) {
|
|
29915
|
+
const swaps = [];
|
|
29916
|
+
let batch = [];
|
|
29917
|
+
let leaves = sorted(inputLeaves);
|
|
29918
|
+
while (leaves.length > 0) {
|
|
29919
|
+
batch.push(leaves.shift());
|
|
29920
|
+
const target = greedyLeaves(sum(batch));
|
|
29921
|
+
if (batch.length >= maxLeavesPerSwap || target.length >= maxLeavesPerSwap) {
|
|
29922
|
+
if (!equals(target, batch)) {
|
|
29923
|
+
swaps.push(new Swap([...batch], target));
|
|
29924
|
+
}
|
|
29925
|
+
batch = [];
|
|
29926
|
+
}
|
|
29927
|
+
}
|
|
29928
|
+
if (batch.length > 0) {
|
|
29929
|
+
const target = greedyLeaves(sum(batch));
|
|
29930
|
+
if (!equals(target, batch)) {
|
|
29931
|
+
swaps.push(new Swap([...batch], target));
|
|
29932
|
+
}
|
|
29933
|
+
}
|
|
29934
|
+
return swaps;
|
|
29935
|
+
}
|
|
29936
|
+
function minimizeTransferSwap(inputLeaves, multiplicity = 1, maxLeavesPerSwap = 64) {
|
|
29937
|
+
const balance = sum(inputLeaves);
|
|
29938
|
+
const optimalLeaves = swapMinimizingLeaves(balance, multiplicity);
|
|
29939
|
+
const walletCounter = countOccurrences(inputLeaves);
|
|
29940
|
+
const optimalCounter = countOccurrences(optimalLeaves);
|
|
29941
|
+
const leavesToGive = subtractCounters(walletCounter, optimalCounter);
|
|
29942
|
+
const leavesToReceive = subtractCounters(optimalCounter, walletCounter);
|
|
29943
|
+
const leavesToGiveFlat = counterToFlatArray(leavesToGive);
|
|
29944
|
+
const leavesToReceiveFlat = counterToFlatArray(leavesToReceive);
|
|
29945
|
+
const swaps = [];
|
|
29946
|
+
let toGiveBatch = [];
|
|
29947
|
+
let toReceiveBatch = [];
|
|
29948
|
+
let give = [...leavesToGiveFlat];
|
|
29949
|
+
let receive = [...leavesToReceiveFlat];
|
|
29950
|
+
while (give.length > 0 || receive.length > 0) {
|
|
29951
|
+
if (sum(toGiveBatch) > sum(toReceiveBatch)) {
|
|
29952
|
+
if (receive.length === 0) break;
|
|
29953
|
+
toReceiveBatch.push(receive.shift());
|
|
29954
|
+
} else {
|
|
29955
|
+
if (give.length === 0) break;
|
|
29956
|
+
toGiveBatch.push(give.shift());
|
|
29957
|
+
}
|
|
29958
|
+
if (toGiveBatch.length > 0 && toReceiveBatch.length > 0 && sum(toGiveBatch) === sum(toReceiveBatch)) {
|
|
29959
|
+
if (toGiveBatch.length > maxLeavesPerSwap) {
|
|
29960
|
+
for (let i = 0; i < toGiveBatch.length; i += maxLeavesPerSwap) {
|
|
29961
|
+
const subset = toGiveBatch.slice(i, i + maxLeavesPerSwap);
|
|
29962
|
+
swaps.push(new Swap(subset, greedyLeaves(sum(subset))));
|
|
29963
|
+
}
|
|
29964
|
+
} else if (toReceiveBatch.length > maxLeavesPerSwap) {
|
|
29965
|
+
for (let cutoff = maxLeavesPerSwap; cutoff > 0; cutoff--) {
|
|
29966
|
+
const sumCut = sum(toReceiveBatch.slice(0, cutoff));
|
|
29967
|
+
const remainder = sum(toGiveBatch) - sumCut;
|
|
29968
|
+
const alternateBatch = [
|
|
29969
|
+
...toReceiveBatch.slice(0, cutoff),
|
|
29970
|
+
...greedyLeaves(remainder)
|
|
29971
|
+
];
|
|
29972
|
+
if (alternateBatch.length <= maxLeavesPerSwap) {
|
|
29973
|
+
swaps.push(new Swap([...toGiveBatch], alternateBatch));
|
|
29974
|
+
break;
|
|
29975
|
+
}
|
|
29976
|
+
}
|
|
29977
|
+
} else {
|
|
29978
|
+
swaps.push(new Swap([...toGiveBatch], [...toReceiveBatch]));
|
|
29979
|
+
}
|
|
29980
|
+
toGiveBatch = [];
|
|
29981
|
+
toReceiveBatch = [];
|
|
29982
|
+
}
|
|
29983
|
+
}
|
|
29984
|
+
return swaps;
|
|
29985
|
+
}
|
|
29986
|
+
function shouldOptimize(inputLeaves, multiplicity = 1, maxLeavesPerSwap = 64) {
|
|
29987
|
+
if (multiplicity == 0) {
|
|
29988
|
+
const swaps = maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap);
|
|
29989
|
+
const numInputs = sum(swaps.map((swap) => swap.inLeaves.length));
|
|
29990
|
+
const numOutputs = sum(swaps.map((swap) => swap.outLeaves.length));
|
|
29991
|
+
return numOutputs * 5 < numInputs;
|
|
29992
|
+
} else {
|
|
29993
|
+
const swaps = minimizeTransferSwap(
|
|
29994
|
+
inputLeaves,
|
|
29995
|
+
multiplicity,
|
|
29996
|
+
maxLeavesPerSwap
|
|
29997
|
+
);
|
|
29998
|
+
const inputCounter = countOccurrences(
|
|
29999
|
+
swaps.flatMap((swap) => swap.inLeaves)
|
|
30000
|
+
);
|
|
30001
|
+
const outputCounter = countOccurrences(
|
|
30002
|
+
swaps.flatMap((swap) => swap.outLeaves)
|
|
30003
|
+
);
|
|
30004
|
+
return Math.abs(inputCounter.size - outputCounter.size) > 1;
|
|
30005
|
+
}
|
|
30006
|
+
}
|
|
30007
|
+
function optimize(inputLeaves, multiplicity = 1, maxLeavesPerSwap = 64) {
|
|
30008
|
+
if (multiplicity == 0) {
|
|
30009
|
+
return maximizeUnilateralExit(inputLeaves, maxLeavesPerSwap);
|
|
30010
|
+
} else {
|
|
30011
|
+
return minimizeTransferSwap(inputLeaves, multiplicity, maxLeavesPerSwap);
|
|
30012
|
+
}
|
|
30013
|
+
}
|
|
30014
|
+
|
|
29704
30015
|
// src/spark-wallet/spark-wallet.ts
|
|
29705
30016
|
var SparkWallet = class extends EventEmitter {
|
|
29706
30017
|
constructor(options, signerArg) {
|
|
@@ -29805,8 +30116,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
29805
30116
|
if (event.transfer.transfer && !equalBytes6(senderIdentityPublicKey, receiverIdentityPublicKey)) {
|
|
29806
30117
|
await this.claimTransfer({
|
|
29807
30118
|
transfer: event.transfer.transfer,
|
|
29808
|
-
emit: true
|
|
29809
|
-
optimize: true
|
|
30119
|
+
emit: true
|
|
29810
30120
|
});
|
|
29811
30121
|
}
|
|
29812
30122
|
} else if (isDepositStreamEvent(event)) {
|
|
@@ -30097,73 +30407,84 @@ var SparkWallet = class extends EventEmitter {
|
|
|
30097
30407
|
}
|
|
30098
30408
|
return nodes;
|
|
30099
30409
|
}
|
|
30100
|
-
|
|
30101
|
-
const
|
|
30102
|
-
if (
|
|
30103
|
-
|
|
30410
|
+
async *optimizeLeaves(multiplicity = void 0) {
|
|
30411
|
+
const multiplicityValue = multiplicity ?? this.config.getOptimizationOptions().multiplicity ?? 0;
|
|
30412
|
+
if (multiplicityValue < 0) {
|
|
30413
|
+
throw new ValidationError("Multiplicity cannot be negative");
|
|
30414
|
+
} else if (multiplicityValue > 5) {
|
|
30415
|
+
throw new ValidationError("Multiplicity cannot be greater than 5");
|
|
30104
30416
|
}
|
|
30105
|
-
|
|
30106
|
-
|
|
30107
|
-
|
|
30108
|
-
|
|
30109
|
-
const denomination = 2 ** i;
|
|
30110
|
-
while (remainingAmount >= denomination) {
|
|
30111
|
-
remainingAmount -= denomination;
|
|
30112
|
-
optimalLeavesLength++;
|
|
30113
|
-
}
|
|
30114
|
-
}
|
|
30115
|
-
return this.leaves.length > optimalLeavesLength * 5;
|
|
30116
|
-
}
|
|
30117
|
-
async optimizeLeaves() {
|
|
30118
|
-
if (this.optimizationInProgress || !this.areLeavesInefficient()) {
|
|
30417
|
+
if (this.optimizationInProgress || !shouldOptimize(
|
|
30418
|
+
this.leaves.map((leaf) => leaf.value),
|
|
30419
|
+
multiplicityValue
|
|
30420
|
+
)) {
|
|
30119
30421
|
return;
|
|
30120
30422
|
}
|
|
30121
|
-
|
|
30423
|
+
const controller = new AbortController();
|
|
30424
|
+
const release = await this.leavesMutex.acquire();
|
|
30425
|
+
try {
|
|
30122
30426
|
this.optimizationInProgress = true;
|
|
30123
|
-
|
|
30124
|
-
|
|
30125
|
-
|
|
30126
|
-
|
|
30127
|
-
|
|
30128
|
-
|
|
30129
|
-
|
|
30130
|
-
|
|
30131
|
-
|
|
30132
|
-
|
|
30133
|
-
|
|
30134
|
-
|
|
30135
|
-
|
|
30136
|
-
|
|
30137
|
-
|
|
30138
|
-
|
|
30139
|
-
|
|
30140
|
-
|
|
30141
|
-
|
|
30142
|
-
|
|
30143
|
-
|
|
30144
|
-
|
|
30145
|
-
|
|
30146
|
-
|
|
30427
|
+
this.leaves = await this.getLeaves();
|
|
30428
|
+
const swaps = optimize(
|
|
30429
|
+
this.leaves.map((leaf) => leaf.value),
|
|
30430
|
+
multiplicityValue
|
|
30431
|
+
);
|
|
30432
|
+
if (swaps.length === 0) {
|
|
30433
|
+
return;
|
|
30434
|
+
}
|
|
30435
|
+
yield {
|
|
30436
|
+
step: 0,
|
|
30437
|
+
total: swaps.length,
|
|
30438
|
+
controller
|
|
30439
|
+
};
|
|
30440
|
+
const valueToNodes = /* @__PURE__ */ new Map();
|
|
30441
|
+
this.leaves.forEach((leaf) => {
|
|
30442
|
+
if (!valueToNodes.has(leaf.value)) {
|
|
30443
|
+
valueToNodes.set(leaf.value, []);
|
|
30444
|
+
}
|
|
30445
|
+
valueToNodes.get(leaf.value).push(leaf);
|
|
30446
|
+
});
|
|
30447
|
+
for (const swap of swaps) {
|
|
30448
|
+
if (controller.signal.aborted) {
|
|
30449
|
+
break;
|
|
30450
|
+
}
|
|
30451
|
+
const leavesToSend = [];
|
|
30452
|
+
for (const leafValue of swap.inLeaves) {
|
|
30453
|
+
const nodes = valueToNodes.get(leafValue);
|
|
30454
|
+
if (nodes && nodes.length > 0) {
|
|
30455
|
+
const node = nodes.shift();
|
|
30456
|
+
leavesToSend.push(node);
|
|
30457
|
+
} else {
|
|
30458
|
+
throw new InternalValidationError(
|
|
30459
|
+
`No unused leaf with value ${leafValue} found in leaves`
|
|
30460
|
+
);
|
|
30147
30461
|
}
|
|
30148
|
-
await this.requestLeavesSwap({
|
|
30149
|
-
leaves: leavesToSend,
|
|
30150
|
-
targetAmounts: swap.outLeaves
|
|
30151
|
-
});
|
|
30152
30462
|
}
|
|
30153
|
-
|
|
30154
|
-
|
|
30155
|
-
|
|
30463
|
+
await this.requestLeavesSwap({
|
|
30464
|
+
leaves: leavesToSend,
|
|
30465
|
+
targetAmounts: swap.outLeaves
|
|
30466
|
+
});
|
|
30467
|
+
yield {
|
|
30468
|
+
step: swaps.indexOf(swap) + 1,
|
|
30469
|
+
total: swaps.length,
|
|
30470
|
+
controller
|
|
30471
|
+
};
|
|
30156
30472
|
}
|
|
30157
|
-
|
|
30473
|
+
this.leaves = await this.getLeaves();
|
|
30474
|
+
} finally {
|
|
30475
|
+
this.optimizationInProgress = false;
|
|
30476
|
+
release();
|
|
30477
|
+
}
|
|
30158
30478
|
}
|
|
30159
30479
|
async syncWallet() {
|
|
30160
30480
|
await this.syncTokenOutputs();
|
|
30161
30481
|
let leaves = await this.getLeaves();
|
|
30162
30482
|
leaves = await this.checkRenewLeaves(leaves);
|
|
30163
30483
|
this.leaves = leaves;
|
|
30164
|
-
this.
|
|
30165
|
-
|
|
30166
|
-
|
|
30484
|
+
if (this.config.getOptimizationOptions().auto) {
|
|
30485
|
+
for await (const _ of this.optimizeLeaves()) {
|
|
30486
|
+
}
|
|
30487
|
+
}
|
|
30167
30488
|
}
|
|
30168
30489
|
async withLeaves(operation) {
|
|
30169
30490
|
const release = await this.leavesMutex.acquire();
|
|
@@ -30746,8 +31067,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
30746
31067
|
}
|
|
30747
31068
|
return await this.claimTransfer({
|
|
30748
31069
|
transfer: incomingTransfer,
|
|
30749
|
-
emit: false
|
|
30750
|
-
optimize: false
|
|
31070
|
+
emit: false
|
|
30751
31071
|
});
|
|
30752
31072
|
} catch (e) {
|
|
30753
31073
|
console.error("[processSwapBatch] Error details:", {
|
|
@@ -31776,7 +32096,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
31776
32096
|
transfer.id
|
|
31777
32097
|
);
|
|
31778
32098
|
if (pending) {
|
|
31779
|
-
await this.claimTransfer({ transfer: pending
|
|
32099
|
+
await this.claimTransfer({ transfer: pending });
|
|
31780
32100
|
}
|
|
31781
32101
|
}
|
|
31782
32102
|
return {
|
|
@@ -31949,13 +32269,14 @@ var SparkWallet = class extends EventEmitter {
|
|
|
31949
32269
|
return response.nodes;
|
|
31950
32270
|
});
|
|
31951
32271
|
}
|
|
31952
|
-
async processClaimedTransferResults(result, transfer, emit
|
|
32272
|
+
async processClaimedTransferResults(result, transfer, emit) {
|
|
31953
32273
|
result = await this.checkRenewLeaves(result);
|
|
31954
32274
|
const existingIds = new Set(this.leaves.map((leaf) => leaf.id));
|
|
31955
32275
|
const uniqueResults = result.filter((node) => !existingIds.has(node.id));
|
|
31956
32276
|
this.leaves.push(...uniqueResults);
|
|
31957
|
-
if (
|
|
31958
|
-
await this.optimizeLeaves()
|
|
32277
|
+
if (this.config.getOptimizationOptions().auto && transfer.type !== 40 /* COUNTER_SWAP */) {
|
|
32278
|
+
for await (const _ of this.optimizeLeaves()) {
|
|
32279
|
+
}
|
|
31959
32280
|
}
|
|
31960
32281
|
if (emit) {
|
|
31961
32282
|
this.emit(
|
|
@@ -31974,8 +32295,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
31974
32295
|
*/
|
|
31975
32296
|
async claimTransfer({
|
|
31976
32297
|
transfer,
|
|
31977
|
-
emit
|
|
31978
|
-
optimize
|
|
32298
|
+
emit
|
|
31979
32299
|
}) {
|
|
31980
32300
|
const onError = async (context) => {
|
|
31981
32301
|
const error = context.error;
|
|
@@ -32020,12 +32340,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
32020
32340
|
if (result.length === 0) {
|
|
32021
32341
|
return [];
|
|
32022
32342
|
}
|
|
32023
|
-
return await this.processClaimedTransferResults(
|
|
32024
|
-
result,
|
|
32025
|
-
transfer,
|
|
32026
|
-
emit,
|
|
32027
|
-
optimize
|
|
32028
|
-
);
|
|
32343
|
+
return await this.processClaimedTransferResults(result, transfer, emit);
|
|
32029
32344
|
} catch (error) {
|
|
32030
32345
|
console.warn(
|
|
32031
32346
|
`Failed to claim transfer after all retries. Please try reinitializing your wallet in a few minutes. Transfer ID: ${transfer.id}`,
|
|
@@ -32058,7 +32373,7 @@ var SparkWallet = class extends EventEmitter {
|
|
|
32058
32373
|
continue;
|
|
32059
32374
|
}
|
|
32060
32375
|
promises.push(
|
|
32061
|
-
this.claimTransfer({ transfer, emit
|
|
32376
|
+
this.claimTransfer({ transfer, emit }).then(() => transfer.id).catch((error) => {
|
|
32062
32377
|
console.warn(`Failed to claim transfer ${transfer.id}:`, error);
|
|
32063
32378
|
return null;
|
|
32064
32379
|
})
|
|
@@ -34406,12 +34721,14 @@ export {
|
|
|
34406
34721
|
NotImplementedError,
|
|
34407
34722
|
RPCError,
|
|
34408
34723
|
ReactNativeSparkSigner,
|
|
34724
|
+
ReactNativeTaprootSparkSigner,
|
|
34409
34725
|
SparkSDKError,
|
|
34410
34726
|
SparkSdkLogger,
|
|
34411
34727
|
SparkWalletReactNative as SparkWallet,
|
|
34412
34728
|
SparkWalletEvent,
|
|
34413
34729
|
TEST_UNILATERAL_DIRECT_SEQUENCE,
|
|
34414
34730
|
TEST_UNILATERAL_SEQUENCE,
|
|
34731
|
+
ReactNativeTaprootSparkSigner as TaprootSparkSigner,
|
|
34415
34732
|
TokenTransactionService,
|
|
34416
34733
|
ValidationError,
|
|
34417
34734
|
WalletConfig,
|
|
@@ -34485,6 +34802,7 @@ export {
|
|
|
34485
34802
|
getTxFromRawTxHex,
|
|
34486
34803
|
getTxId,
|
|
34487
34804
|
getTxIdNoReverse,
|
|
34805
|
+
hash160,
|
|
34488
34806
|
isEphemeralAnchorOutput,
|
|
34489
34807
|
isLegacySparkAddress,
|
|
34490
34808
|
isSafeForNumber,
|