@hardkas/accounts 0.12.0-rc.20 → 0.12.0-rc.21
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/{authorizers-S5IKSHTE.js → authorizers-CP222OTW.js} +1 -2
- package/dist/{chunk-YBNHOFVX.js → chunk-7KKJXU73.js} +3 -1
- package/dist/{chunk-6DPO5V3N.js → chunk-BNF566PS.js} +11 -20
- package/dist/{chunk-YZ6W5EBW.js → chunk-CELVD4YG.js} +118 -113
- package/dist/{chunk-5266LO4K.js → chunk-E73SSWAX.js} +3 -3
- package/dist/{chunk-R5P3WIWR.js → chunk-GM2BY4VS.js} +37 -15
- package/dist/{dev-accounts-S4WHPHJK.js → dev-accounts-BSWPKAAE.js} +4 -5
- package/dist/index.d.ts +354 -8
- package/dist/index.js +569 -35
- package/dist/internal/wasm-rpc-serialization.d.ts +5 -1
- package/dist/internal/wasm-rpc-serialization.js +1 -2
- package/dist/{keystore-2KRHVGCM.js → keystore-CMWEKGBF.js} +0 -1
- package/dist/{resolve-UTFZTVAK.js → resolve-KMMTZWC3.js} +1 -2
- package/dist/{signer-backend-X3FD3XMB.js → signer-backend-LHWY7ULI.js} +5 -4
- package/package.json +6 -7
- package/dist/chunk-MCKGQKYU.js +0 -15
- package/dist/core-lib-YKSIDZOW.js +0 -29006
package/dist/index.js
CHANGED
|
@@ -2,12 +2,25 @@ import {
|
|
|
2
2
|
DEV_ACCOUNTS_PASSWORD,
|
|
3
3
|
KaspaWasmPrivateKeySigner,
|
|
4
4
|
assertSigningNetworkAllowed,
|
|
5
|
+
assertValueConservation,
|
|
6
|
+
createBalancedTransaction,
|
|
5
7
|
createDevSigner,
|
|
8
|
+
createScriptTransaction,
|
|
6
9
|
ensureDevAccounts,
|
|
7
10
|
getOrCreateDevAccount,
|
|
8
|
-
listDevAccountsSync
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
listDevAccountsSync,
|
|
12
|
+
planOutputsWithChange,
|
|
13
|
+
toWasmScriptPublicKey
|
|
14
|
+
} from "./chunk-CELVD4YG.js";
|
|
15
|
+
import {
|
|
16
|
+
parseWasmTxToRpc
|
|
17
|
+
} from "./chunk-GM2BY4VS.js";
|
|
18
|
+
import {
|
|
19
|
+
detectCapabilities,
|
|
20
|
+
getKaspaSigningBackendStatus,
|
|
21
|
+
loadKaspaWasm,
|
|
22
|
+
loadKaspaWasmSync
|
|
23
|
+
} from "./chunk-BNF566PS.js";
|
|
11
24
|
import {
|
|
12
25
|
assertAccountCompatible,
|
|
13
26
|
createEmptyRealAccountStore,
|
|
@@ -28,12 +41,7 @@ import {
|
|
|
28
41
|
validateAccountName,
|
|
29
42
|
validateAddressNetwork,
|
|
30
43
|
validateAddressPrefix
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import {
|
|
33
|
-
detectCapabilities,
|
|
34
|
-
getKaspaSigningBackendStatus,
|
|
35
|
-
loadKaspaWasm
|
|
36
|
-
} from "./chunk-6DPO5V3N.js";
|
|
44
|
+
} from "./chunk-7KKJXU73.js";
|
|
37
45
|
import {
|
|
38
46
|
KeystoreManager
|
|
39
47
|
} from "./chunk-YLG2NIAU.js";
|
|
@@ -41,8 +49,7 @@ import {
|
|
|
41
49
|
LazyAccountAuthorizer,
|
|
42
50
|
PrivateKeyAuthorizer,
|
|
43
51
|
StaticSignatureScriptAuthorizer
|
|
44
|
-
} from "./chunk-
|
|
45
|
-
import "./chunk-MCKGQKYU.js";
|
|
52
|
+
} from "./chunk-E73SSWAX.js";
|
|
46
53
|
|
|
47
54
|
// src/simulated.ts
|
|
48
55
|
var SimulatedSigner = class {
|
|
@@ -238,6 +245,526 @@ async function signTxPlanArtifact(input) {
|
|
|
238
245
|
throw new Error(`Unsupported account kind for signing: ${accountRecord ? accountRecord.kind : "unknown"}`);
|
|
239
246
|
}
|
|
240
247
|
|
|
248
|
+
// src/silver-spend.ts
|
|
249
|
+
import {
|
|
250
|
+
encodeSilverEntryArgs,
|
|
251
|
+
getSilContract,
|
|
252
|
+
loadManagedKaspaWasmSync,
|
|
253
|
+
silContractBytecodeHex,
|
|
254
|
+
silverP2shLock,
|
|
255
|
+
silverSigFromInputSignature,
|
|
256
|
+
silverUnlockScript
|
|
257
|
+
} from "@hardkas/core";
|
|
258
|
+
import { calculateUpstreamStorageMass, measureBuiltTransactionMass } from "@hardkas/tx-builder";
|
|
259
|
+
function spendError(code, message) {
|
|
260
|
+
const err = new Error(`${code}: ${message}`);
|
|
261
|
+
err.code = code;
|
|
262
|
+
return err;
|
|
263
|
+
}
|
|
264
|
+
var PLACEHOLDER_SIG = { kind: "bytes", value: new Uint8Array(65) };
|
|
265
|
+
function buildSilverSweep(request) {
|
|
266
|
+
const k = loadManagedKaspaWasmSync();
|
|
267
|
+
const { name: contractName, contract } = getSilContract(request.artifact, request.contractName);
|
|
268
|
+
const bytecode = silContractBytecodeHex(contract);
|
|
269
|
+
const lock = silverP2shLock(bytecode);
|
|
270
|
+
const utxoSpk = request.utxo.scriptPublicKey;
|
|
271
|
+
if (Number(utxoSpk.version) !== lock.version || String(utxoSpk.script).toLowerCase() !== lock.script) {
|
|
272
|
+
throw spendError(
|
|
273
|
+
"SILVER_SPEND_LOCK_MISMATCH",
|
|
274
|
+
`output ${request.utxo.outpoint.transactionId}:${request.utxo.outpoint.index} is not locked to contract '${contractName}'`
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
if (!k.Address.validate(request.to)) throw spendError("SILVER_SPEND_INVALID_RECIPIENT", `'${request.to}' is not a Kaspa address`);
|
|
278
|
+
const sequence = request.sequence ?? 0n;
|
|
279
|
+
const sigOpCount = request.sigOpCount ?? 1;
|
|
280
|
+
const amountIn = request.utxo.amountSompi;
|
|
281
|
+
const { transactionId, index } = request.utxo.outpoint;
|
|
282
|
+
const makeTx = (amountOut2, signatureScript) => {
|
|
283
|
+
const tx = new k.Transaction({
|
|
284
|
+
version: 0,
|
|
285
|
+
inputs: [
|
|
286
|
+
{
|
|
287
|
+
previousOutpoint: { transactionId, index },
|
|
288
|
+
signatureScript,
|
|
289
|
+
sequence,
|
|
290
|
+
sigOpCount,
|
|
291
|
+
utxo: {
|
|
292
|
+
outpoint: { transactionId, index },
|
|
293
|
+
amount: amountIn,
|
|
294
|
+
scriptPublicKey: new k.ScriptPublicKey(lock.version, lock.script),
|
|
295
|
+
blockDaaScore: request.utxo.blockDaaScore,
|
|
296
|
+
isCoinbase: request.utxo.isCoinbase
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
],
|
|
300
|
+
outputs: [{ value: amountOut2, scriptPublicKey: k.payToAddressScript(new k.Address(request.to)) }],
|
|
301
|
+
lockTime: 0n,
|
|
302
|
+
subnetworkId: "0000000000000000000000000000000000000000",
|
|
303
|
+
gas: 0n,
|
|
304
|
+
payload: ""
|
|
305
|
+
});
|
|
306
|
+
tx.storageMass = calculateUpstreamStorageMass([amountIn], [amountOut2], request.networkId);
|
|
307
|
+
return tx;
|
|
308
|
+
};
|
|
309
|
+
const entryArgs = (resolveSig) => encodeSilverEntryArgs({
|
|
310
|
+
artifact: request.artifact,
|
|
311
|
+
contractName,
|
|
312
|
+
entry: request.entry,
|
|
313
|
+
args: request.args.map((a) => a.kind === "signature" ? resolveSig(a) : a)
|
|
314
|
+
});
|
|
315
|
+
const placeholderUnlock = silverUnlockScript(bytecode, entryArgs(() => PLACEHOLDER_SIG));
|
|
316
|
+
let fee = 0n;
|
|
317
|
+
let priced;
|
|
318
|
+
let converged = false;
|
|
319
|
+
for (let round = 0; round < 8 && !converged; round++) {
|
|
320
|
+
const amountOut2 = amountIn - fee;
|
|
321
|
+
if (amountOut2 <= 0n) throw spendError("SILVER_SPEND_INSUFFICIENT_VALUE", `output of ${amountIn} sompi cannot pay a fee of ${fee}`);
|
|
322
|
+
priced = measureBuiltTransactionMass(makeTx(amountOut2, placeholderUnlock), request.networkId);
|
|
323
|
+
if (!priced.standard) {
|
|
324
|
+
throw spendError("TX_MASS_ABOVE_STANDARD_LIMIT", `mass ${priced.mass} exceeds the maximum standard mass ${priced.maximumStandardMass}`);
|
|
325
|
+
}
|
|
326
|
+
const byRate = request.feeRateSompiPerGram !== void 0 ? priced.mass * request.feeRateSompiPerGram : 0n;
|
|
327
|
+
const required = priced.minimumFeeSompi > byRate ? priced.minimumFeeSompi : byRate;
|
|
328
|
+
if (required <= fee) converged = true;
|
|
329
|
+
else fee = required;
|
|
330
|
+
}
|
|
331
|
+
if (!priced || !converged) throw spendError("SILVER_SPEND_FEE_UNRESOLVED", "the fee did not converge");
|
|
332
|
+
const amountOut = amountIn - fee;
|
|
333
|
+
const unsigned = makeTx(amountOut, "");
|
|
334
|
+
const unlock = silverUnlockScript(
|
|
335
|
+
bytecode,
|
|
336
|
+
entryArgs((a) => ({
|
|
337
|
+
kind: "bytes",
|
|
338
|
+
value: silverSigFromInputSignature(String(k.createInputSignature(unsigned, 0, new k.PrivateKey(a.privateKey), k.SighashType.All)))
|
|
339
|
+
}))
|
|
340
|
+
);
|
|
341
|
+
if (unlock.length !== placeholderUnlock.length) {
|
|
342
|
+
throw spendError("SILVER_SPEND_UNLOCK_SIZE_CHANGED", "the signed unlock is not the size the fee was computed for");
|
|
343
|
+
}
|
|
344
|
+
const signed = makeTx(amountOut, unlock);
|
|
345
|
+
return {
|
|
346
|
+
transaction: signed,
|
|
347
|
+
rpcTransaction: parseWasmTxToRpc(signed.serializeToObject()),
|
|
348
|
+
txId: String(signed.id),
|
|
349
|
+
contractName,
|
|
350
|
+
entry: request.entry,
|
|
351
|
+
outputSompi: amountOut,
|
|
352
|
+
feeSompi: fee,
|
|
353
|
+
mass: priced.mass,
|
|
354
|
+
storageMass: BigInt(signed.storageMass),
|
|
355
|
+
signatureScriptHex: unlock,
|
|
356
|
+
assumptions: [...priced.assumptions, `sigOpCount ${sigOpCount}`]
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
var SILVER_SPEND_DRAFT_SCHEMA = "hardkas.silver.spendDraft.v1";
|
|
360
|
+
function draftTx(k, draft, signatureScript, networkId) {
|
|
361
|
+
const i = draft.input;
|
|
362
|
+
const tx = new k.Transaction({
|
|
363
|
+
version: 0,
|
|
364
|
+
inputs: [{
|
|
365
|
+
previousOutpoint: i.outpoint,
|
|
366
|
+
signatureScript,
|
|
367
|
+
sequence: BigInt(i.sequence),
|
|
368
|
+
sigOpCount: i.sigOpCount,
|
|
369
|
+
utxo: {
|
|
370
|
+
outpoint: i.outpoint,
|
|
371
|
+
amount: BigInt(i.amountSompi),
|
|
372
|
+
scriptPublicKey: new k.ScriptPublicKey(i.scriptPublicKey.version, i.scriptPublicKey.script),
|
|
373
|
+
blockDaaScore: BigInt(i.blockDaaScore),
|
|
374
|
+
isCoinbase: i.isCoinbase
|
|
375
|
+
}
|
|
376
|
+
}],
|
|
377
|
+
outputs: draft.outputs.map((o) => ({ value: BigInt(o.valueSompi), scriptPublicKey: new k.ScriptPublicKey(o.scriptPublicKey.version, o.scriptPublicKey.script) })),
|
|
378
|
+
lockTime: 0n,
|
|
379
|
+
subnetworkId: "0000000000000000000000000000000000000000",
|
|
380
|
+
gas: 0n,
|
|
381
|
+
payload: ""
|
|
382
|
+
});
|
|
383
|
+
tx.storageMass = calculateUpstreamStorageMass([BigInt(i.amountSompi)], draft.outputs.map((o) => BigInt(o.valueSompi)), networkId);
|
|
384
|
+
return tx;
|
|
385
|
+
}
|
|
386
|
+
function draftUnlock(artifact, contractName, entry, args, fill) {
|
|
387
|
+
const { contract } = getSilContract(artifact, contractName);
|
|
388
|
+
return silverUnlockScript(
|
|
389
|
+
silContractBytecodeHex(contract),
|
|
390
|
+
encodeSilverEntryArgs({ artifact, contractName, entry, args: args.map((a) => a.kind === "signer" ? fill(a) : a) })
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
function prepareSilverSpend(request) {
|
|
394
|
+
const k = loadManagedKaspaWasmSync();
|
|
395
|
+
const { name: contractName, contract } = getSilContract(request.artifact, request.contractName);
|
|
396
|
+
const lock = silverP2shLock(silContractBytecodeHex(contract));
|
|
397
|
+
const u = request.utxo;
|
|
398
|
+
if (Number(u.scriptPublicKey.version) !== lock.version || String(u.scriptPublicKey.script).toLowerCase() !== lock.script) {
|
|
399
|
+
throw spendError("SILVER_SPEND_LOCK_MISMATCH", `output ${u.outpoint.transactionId}:${u.outpoint.index} is not locked to contract '${contractName}'`);
|
|
400
|
+
}
|
|
401
|
+
const signers = request.args.filter((a) => a.kind === "signer").map((a) => a.signer);
|
|
402
|
+
const outputs = request.outputs.map((o, i) => {
|
|
403
|
+
let spk = o.scriptPublicKey;
|
|
404
|
+
if (!spk && o.address) {
|
|
405
|
+
if (!k.Address.validate(o.address)) throw spendError("SILVER_SPEND_INVALID_RECIPIENT", `output ${i}: '${o.address}' is not a Kaspa address`);
|
|
406
|
+
const s = k.payToAddressScript(new k.Address(o.address));
|
|
407
|
+
spk = { version: Number(s.version), script: String(s.script) };
|
|
408
|
+
}
|
|
409
|
+
if (!spk || !/^(?:[0-9a-f]{2})+$/i.test(spk.script)) throw spendError("SILVER_SPEND_INVALID_RECIPIENT", `output ${i} has no script`);
|
|
410
|
+
if (o.amountSompi <= 0n) throw spendError("SILVER_SPEND_INVALID_OUTPUT", `output ${i} has no value`);
|
|
411
|
+
return { valueSompi: o.amountSompi.toString(), scriptPublicKey: { version: Number(spk.version), script: String(spk.script).toLowerCase() } };
|
|
412
|
+
});
|
|
413
|
+
const totalOut = outputs.reduce((s, o) => s + BigInt(o.valueSompi), 0n);
|
|
414
|
+
if (totalOut > u.amountSompi) throw spendError("SILVER_SPEND_INSUFFICIENT_VALUE", `outputs ${totalOut} exceed the contract output ${u.amountSompi}`);
|
|
415
|
+
const base = {
|
|
416
|
+
networkId: request.networkId,
|
|
417
|
+
contractName,
|
|
418
|
+
entry: request.entry,
|
|
419
|
+
input: {
|
|
420
|
+
outpoint: { transactionId: u.outpoint.transactionId, index: u.outpoint.index },
|
|
421
|
+
amountSompi: u.amountSompi.toString(),
|
|
422
|
+
scriptPublicKey: { version: lock.version, script: lock.script },
|
|
423
|
+
blockDaaScore: u.blockDaaScore.toString(),
|
|
424
|
+
isCoinbase: u.isCoinbase,
|
|
425
|
+
sequence: (request.sequence ?? 0n).toString(),
|
|
426
|
+
sigOpCount: request.sigOpCount ?? Math.max(1, signers.length)
|
|
427
|
+
},
|
|
428
|
+
outputs
|
|
429
|
+
};
|
|
430
|
+
const placeholder = draftUnlock(request.artifact, contractName, request.entry, request.args, () => PLACEHOLDER_SIG);
|
|
431
|
+
const priced = measureBuiltTransactionMass(draftTx(k, base, placeholder, request.networkId), request.networkId);
|
|
432
|
+
if (!priced.standard) throw spendError("TX_MASS_ABOVE_STANDARD_LIMIT", `mass ${priced.mass} exceeds the maximum standard mass ${priced.maximumStandardMass}`);
|
|
433
|
+
const fee = u.amountSompi - totalOut;
|
|
434
|
+
if (fee < priced.minimumFeeSompi) {
|
|
435
|
+
throw spendError("FEE_BELOW_NETWORK_MINIMUM", `the outputs leave ${fee} sompi of fee; the SDK minimum for this spend is ${priced.minimumFeeSompi}`);
|
|
436
|
+
}
|
|
437
|
+
const unsigned = draftTx(k, base, "", request.networkId);
|
|
438
|
+
return {
|
|
439
|
+
schema: SILVER_SPEND_DRAFT_SCHEMA,
|
|
440
|
+
...base,
|
|
441
|
+
signers,
|
|
442
|
+
feeSompi: fee.toString(),
|
|
443
|
+
mass: priced.mass.toString(),
|
|
444
|
+
storageMass: String(unsigned.storageMass),
|
|
445
|
+
unlockHexLength: placeholder.length,
|
|
446
|
+
unsignedTxId: String(unsigned.id)
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
function signSilverSpend(draft, privateKey) {
|
|
450
|
+
if (draft?.schema !== SILVER_SPEND_DRAFT_SCHEMA) throw spendError("SILVER_SPEND_DRAFT_INVALID", "not a SilverScript spend draft");
|
|
451
|
+
const k = loadManagedKaspaWasmSync();
|
|
452
|
+
const unsigned = draftTx(k, draft, "", draft.networkId);
|
|
453
|
+
if (String(unsigned.id) !== draft.unsignedTxId) throw spendError("SILVER_SPEND_DRAFT_INVALID", "the draft does not rebuild to the transaction it describes");
|
|
454
|
+
const inputSignature = String(k.createInputSignature(unsigned, 0, new k.PrivateKey(privateKey), k.SighashType.All));
|
|
455
|
+
return Buffer.from(silverSigFromInputSignature(inputSignature)).toString("hex");
|
|
456
|
+
}
|
|
457
|
+
function finalizeSilverSpend(draft, artifact, args, signatures) {
|
|
458
|
+
if (draft?.schema !== SILVER_SPEND_DRAFT_SCHEMA) throw spendError("SILVER_SPEND_DRAFT_INVALID", "not a SilverScript spend draft");
|
|
459
|
+
const k = loadManagedKaspaWasmSync();
|
|
460
|
+
const lock = silverP2shLock(silContractBytecodeHex(getSilContract(artifact, draft.contractName).contract));
|
|
461
|
+
if (lock.script !== draft.input.scriptPublicKey.script) throw spendError("SILVER_SPEND_LOCK_MISMATCH", "the artifact is not the contract the draft spends");
|
|
462
|
+
const unlock = draftUnlock(artifact, draft.contractName, draft.entry, args, (slot) => {
|
|
463
|
+
const sig = signatures[slot.signer];
|
|
464
|
+
if (!sig) throw spendError("SILVER_SPEND_SIGNATURE_MISSING", `no signature from '${slot.signer}'`);
|
|
465
|
+
return { kind: "bytes", value: Buffer.from(sig, "hex") };
|
|
466
|
+
});
|
|
467
|
+
if (unlock.length !== draft.unlockHexLength) {
|
|
468
|
+
throw spendError("SILVER_SPEND_UNLOCK_SIZE_CHANGED", "the signed unlock is not the size the fee was checked for");
|
|
469
|
+
}
|
|
470
|
+
const tx = draftTx(k, draft, unlock, draft.networkId);
|
|
471
|
+
if (String(tx.id) !== draft.unsignedTxId) throw spendError("SILVER_SPEND_DRAFT_INVALID", "the finalized transaction differs from the draft");
|
|
472
|
+
return { rpcTransaction: parseWasmTxToRpc(tx.serializeToObject()), txId: String(tx.id), signatureScriptHex: unlock };
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// src/silver-covenant.ts
|
|
476
|
+
import {
|
|
477
|
+
encodeSilverEntryArgs as encodeSilverEntryArgs2,
|
|
478
|
+
getSilContract as getSilContract2,
|
|
479
|
+
loadManagedKaspaWasmSync as loadManagedKaspaWasmSync2,
|
|
480
|
+
silContractBytecodeHex as silContractBytecodeHex2,
|
|
481
|
+
silverP2shLock as silverP2shLock2,
|
|
482
|
+
silverUnlockScript as silverUnlockScript2
|
|
483
|
+
} from "@hardkas/core";
|
|
484
|
+
import { calculateUpstreamStorageMass as calculateUpstreamStorageMass2, measureBuiltTransactionMass as measureBuiltTransactionMass2 } from "@hardkas/tx-builder";
|
|
485
|
+
function covenantError(code, message) {
|
|
486
|
+
const err = new Error(`${code}: ${message}`);
|
|
487
|
+
err.code = code;
|
|
488
|
+
return err;
|
|
489
|
+
}
|
|
490
|
+
var ZERO_SUBNET = "0000000000000000000000000000000000000000";
|
|
491
|
+
function checkBudget(budget, where) {
|
|
492
|
+
if (!Number.isInteger(budget) || budget < 0 || budget > 65535) {
|
|
493
|
+
throw covenantError("COVENANT_COMPUTE_BUDGET_INVALID", `${where}: compute budget ${budget} is not a u16`);
|
|
494
|
+
}
|
|
495
|
+
return budget;
|
|
496
|
+
}
|
|
497
|
+
function requireExplicitFeeForBudgets(budgets, feeSompi) {
|
|
498
|
+
if (budgets.some((b) => b > 0) && feeSompi === void 0) {
|
|
499
|
+
throw covenantError(
|
|
500
|
+
"COVENANT_V1_FEE_UNPRICED",
|
|
501
|
+
"the SDK mass calculator does not count v1 compute budgets (upstream TODO); pass feeSompi explicitly for inputs with computeBudget > 0"
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
function settleFee(build, networkId, feeRate, explicitFee) {
|
|
506
|
+
if (explicitFee !== void 0) {
|
|
507
|
+
const measured = measureBuiltTransactionMass2(build(explicitFee), networkId);
|
|
508
|
+
if (!measured.standard) {
|
|
509
|
+
throw covenantError("TX_MASS_ABOVE_STANDARD_LIMIT", `mass ${measured.mass} exceeds the maximum standard mass ${measured.maximumStandardMass}`);
|
|
510
|
+
}
|
|
511
|
+
if (explicitFee < measured.minimumFeeSompi) {
|
|
512
|
+
throw covenantError("FEE_BELOW_NETWORK_MINIMUM", `fee ${explicitFee} is below the SDK minimum ${measured.minimumFeeSompi}`);
|
|
513
|
+
}
|
|
514
|
+
return { fee: explicitFee, measured };
|
|
515
|
+
}
|
|
516
|
+
let fee = 0n;
|
|
517
|
+
for (let round = 0; round < 8; round++) {
|
|
518
|
+
const measured = measureBuiltTransactionMass2(build(fee), networkId);
|
|
519
|
+
if (!measured.standard) {
|
|
520
|
+
throw covenantError("TX_MASS_ABOVE_STANDARD_LIMIT", `mass ${measured.mass} exceeds the maximum standard mass ${measured.maximumStandardMass}`);
|
|
521
|
+
}
|
|
522
|
+
const byRate = feeRate !== void 0 ? measured.mass * feeRate : 0n;
|
|
523
|
+
const required = measured.minimumFeeSompi > byRate ? measured.minimumFeeSompi : byRate;
|
|
524
|
+
if (required <= fee) return { fee, measured };
|
|
525
|
+
fee = required;
|
|
526
|
+
}
|
|
527
|
+
throw covenantError("COVENANT_FEE_UNRESOLVED", "the fee did not converge");
|
|
528
|
+
}
|
|
529
|
+
function buildCovenantGenesis(request) {
|
|
530
|
+
const k = loadManagedKaspaWasmSync2();
|
|
531
|
+
const { contract } = getSilContract2(request.artifact, request.contractName);
|
|
532
|
+
const lock = silverP2shLock2(silContractBytecodeHex2(contract));
|
|
533
|
+
if (request.funding.length === 0) throw covenantError("COVENANT_GENESIS_UNFUNDED", "a genesis needs at least one funding input");
|
|
534
|
+
if (!k.Address.validate(request.changeAddress)) throw covenantError("COVENANT_INVALID_ADDRESS", `'${request.changeAddress}' is not a Kaspa address`);
|
|
535
|
+
const inputs = request.funding.map((f, i) => {
|
|
536
|
+
const key = new k.PrivateKey(f.privateKey);
|
|
537
|
+
const expected = k.payToAddressScript(key.toKeypair().toAddress(request.networkId));
|
|
538
|
+
if (Number(f.scriptPublicKey.version) !== Number(expected.version) || String(f.scriptPublicKey.script).toLowerCase() !== String(expected.script)) {
|
|
539
|
+
throw covenantError("COVENANT_FUNDING_KEY_MISMATCH", `funding input ${i} is not a P2PK output of its key`);
|
|
540
|
+
}
|
|
541
|
+
return { ...f, computeBudget: checkBudget(f.computeBudget, `funding input ${i}`), key };
|
|
542
|
+
});
|
|
543
|
+
const totalIn = inputs.reduce((s, f) => s + f.amountSompi, 0n);
|
|
544
|
+
const make = (fee2, signatureScripts) => {
|
|
545
|
+
const change = totalIn - request.valueSompi - fee2;
|
|
546
|
+
if (change < 0n) throw covenantError("COVENANT_GENESIS_INSUFFICIENT_FUNDS", `inputs ${totalIn} cannot cover ${request.valueSompi} + fee ${fee2}`);
|
|
547
|
+
const outputs = [{ value: request.valueSompi, scriptPublicKey: new k.ScriptPublicKey(lock.version, lock.script) }];
|
|
548
|
+
if (change > 0n) outputs.push({ value: change, scriptPublicKey: k.payToAddressScript(new k.Address(request.changeAddress)) });
|
|
549
|
+
const tx = new k.Transaction({
|
|
550
|
+
version: 1,
|
|
551
|
+
inputs: inputs.map((f, i) => ({
|
|
552
|
+
previousOutpoint: f.outpoint,
|
|
553
|
+
signatureScript: signatureScripts?.[i] ?? "",
|
|
554
|
+
sequence: 0n,
|
|
555
|
+
sigOpCount: 0,
|
|
556
|
+
computeBudget: f.computeBudget,
|
|
557
|
+
utxo: {
|
|
558
|
+
outpoint: f.outpoint,
|
|
559
|
+
amount: f.amountSompi,
|
|
560
|
+
scriptPublicKey: new k.ScriptPublicKey(Number(f.scriptPublicKey.version), String(f.scriptPublicKey.script)),
|
|
561
|
+
blockDaaScore: f.blockDaaScore,
|
|
562
|
+
isCoinbase: f.isCoinbase
|
|
563
|
+
}
|
|
564
|
+
})),
|
|
565
|
+
outputs,
|
|
566
|
+
lockTime: 0n,
|
|
567
|
+
subnetworkId: ZERO_SUBNET,
|
|
568
|
+
gas: 0n,
|
|
569
|
+
payload: ""
|
|
570
|
+
});
|
|
571
|
+
tx.populateGenesisCovenants([{ authorizingInput: 0, outputs: [0] }]);
|
|
572
|
+
tx.storageMass = calculateUpstreamStorageMass2(
|
|
573
|
+
inputs.map((f) => f.amountSompi),
|
|
574
|
+
change > 0n ? [request.valueSompi, change] : [request.valueSompi],
|
|
575
|
+
request.networkId
|
|
576
|
+
);
|
|
577
|
+
return tx;
|
|
578
|
+
};
|
|
579
|
+
requireExplicitFeeForBudgets(inputs.map((f) => f.computeBudget), request.feeSompi);
|
|
580
|
+
const { fee, measured } = settleFee((f) => make(f), request.networkId, request.feeRateSompiPerGram, request.feeSompi);
|
|
581
|
+
const unsigned = make(fee);
|
|
582
|
+
const signatures = inputs.map((f, i) => String(k.createInputSignature(unsigned, i, f.key, k.SighashType.All)));
|
|
583
|
+
const signed = make(fee, signatures);
|
|
584
|
+
const binding = signed.outputs[0].covenant;
|
|
585
|
+
if (!binding) throw covenantError("COVENANT_GENESIS_UNBOUND", "the SDK did not bind the covenant output");
|
|
586
|
+
return {
|
|
587
|
+
transaction: signed,
|
|
588
|
+
rpcTransaction: parseWasmTxToRpc(signed.serializeToObject()),
|
|
589
|
+
txId: String(signed.id),
|
|
590
|
+
covenantId: String(binding.covenantId),
|
|
591
|
+
lockingScript: lock,
|
|
592
|
+
feeSompi: fee,
|
|
593
|
+
mass: measured.mass,
|
|
594
|
+
storageMass: BigInt(signed.storageMass),
|
|
595
|
+
changeSompi: totalIn - request.valueSompi - fee,
|
|
596
|
+
computeBudgets: inputs.map((f) => f.computeBudget),
|
|
597
|
+
assumptions: [
|
|
598
|
+
...measured.assumptions,
|
|
599
|
+
"compute budgets supplied by the caller; validated only by the node",
|
|
600
|
+
...request.feeSompi !== void 0 ? ["fee supplied by the caller: the SDK does not price v1 compute budgets"] : []
|
|
601
|
+
]
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
function buildCovenantTransition(request) {
|
|
605
|
+
const k = loadManagedKaspaWasmSync2();
|
|
606
|
+
const { name, contract } = getSilContract2(request.current, request.contractName);
|
|
607
|
+
const next = getSilContract2(request.successor, name).contract;
|
|
608
|
+
if (contract.delegate_entry_abi !== void 0) {
|
|
609
|
+
throw covenantError("COVENANT_BINDING_NOT_IMPLEMENTED", `contract '${name}' is a cov-bound leader contract; only auth-bound singletons are supported`);
|
|
610
|
+
}
|
|
611
|
+
const entry = contract.cov_decl_to_abi?.[request.policy];
|
|
612
|
+
if (!entry) {
|
|
613
|
+
throw covenantError(
|
|
614
|
+
"COVENANT_POLICY_NOT_FOUND",
|
|
615
|
+
`contract '${name}' declares no covenant policy '${request.policy}' (has: ${Object.keys(contract.cov_decl_to_abi ?? {}).join(", ") || "none"})`
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
if (!Buffer.from(contract.compiled.template_hash).equals(Buffer.from(next.compiled.template_hash))) {
|
|
619
|
+
throw covenantError("SILVER_SUCCESSOR_TEMPLATE_CHANGED", "the successor artifact is not the same template");
|
|
620
|
+
}
|
|
621
|
+
const bytecode = silContractBytecodeHex2(contract);
|
|
622
|
+
const lock = silverP2shLock2(bytecode);
|
|
623
|
+
const successorLock = silverP2shLock2(silContractBytecodeHex2(next));
|
|
624
|
+
const u = request.utxo;
|
|
625
|
+
if (Number(u.scriptPublicKey.version) !== lock.version || String(u.scriptPublicKey.script).toLowerCase() !== lock.script) {
|
|
626
|
+
throw covenantError("SILVER_SPEND_LOCK_MISMATCH", `output ${u.outpoint.transactionId}:${u.outpoint.index} is not locked to the current state of '${name}'`);
|
|
627
|
+
}
|
|
628
|
+
if (!/^[0-9a-f]{64}$/i.test(u.covenantId ?? "")) throw covenantError("COVENANT_ID_MISSING", "the covenant UTXO carries no covenant id");
|
|
629
|
+
const budget = checkBudget(request.computeBudget, "covenant input");
|
|
630
|
+
const unlock = silverUnlockScript2(bytecode, encodeSilverEntryArgs2({ artifact: request.current, contractName: name, entry, args: request.args }));
|
|
631
|
+
const make = (fee2) => {
|
|
632
|
+
const value = u.amountSompi - fee2;
|
|
633
|
+
if (value <= 0n) throw covenantError("COVENANT_INSUFFICIENT_VALUE", `covenant output of ${u.amountSompi} cannot pay a fee of ${fee2}`);
|
|
634
|
+
const tx2 = new k.Transaction({
|
|
635
|
+
version: 1,
|
|
636
|
+
inputs: [{
|
|
637
|
+
previousOutpoint: u.outpoint,
|
|
638
|
+
signatureScript: unlock,
|
|
639
|
+
sequence: 0n,
|
|
640
|
+
sigOpCount: 0,
|
|
641
|
+
computeBudget: budget,
|
|
642
|
+
utxo: {
|
|
643
|
+
outpoint: u.outpoint,
|
|
644
|
+
amount: u.amountSompi,
|
|
645
|
+
scriptPublicKey: new k.ScriptPublicKey(lock.version, lock.script),
|
|
646
|
+
blockDaaScore: u.blockDaaScore,
|
|
647
|
+
isCoinbase: u.isCoinbase,
|
|
648
|
+
covenantId: u.covenantId
|
|
649
|
+
}
|
|
650
|
+
}],
|
|
651
|
+
outputs: [{
|
|
652
|
+
value,
|
|
653
|
+
scriptPublicKey: new k.ScriptPublicKey(successorLock.version, successorLock.script),
|
|
654
|
+
covenant: { authorizingInput: 0, covenantId: u.covenantId }
|
|
655
|
+
}],
|
|
656
|
+
lockTime: 0n,
|
|
657
|
+
subnetworkId: ZERO_SUBNET,
|
|
658
|
+
gas: 0n,
|
|
659
|
+
payload: ""
|
|
660
|
+
});
|
|
661
|
+
tx2.storageMass = calculateUpstreamStorageMass2([u.amountSompi], [value], request.networkId);
|
|
662
|
+
return tx2;
|
|
663
|
+
};
|
|
664
|
+
requireExplicitFeeForBudgets([budget], request.feeSompi);
|
|
665
|
+
const { fee, measured } = settleFee(make, request.networkId, request.feeRateSompiPerGram, request.feeSompi);
|
|
666
|
+
const tx = make(fee);
|
|
667
|
+
return {
|
|
668
|
+
transaction: tx,
|
|
669
|
+
rpcTransaction: parseWasmTxToRpc(tx.serializeToObject()),
|
|
670
|
+
txId: String(tx.id),
|
|
671
|
+
covenantId: u.covenantId,
|
|
672
|
+
lockingScript: successorLock,
|
|
673
|
+
feeSompi: fee,
|
|
674
|
+
mass: measured.mass,
|
|
675
|
+
storageMass: BigInt(tx.storageMass),
|
|
676
|
+
successorSompi: u.amountSompi - fee,
|
|
677
|
+
computeBudgets: [budget],
|
|
678
|
+
assumptions: [
|
|
679
|
+
...measured.assumptions,
|
|
680
|
+
"compute budget supplied by the caller; validated only by the node",
|
|
681
|
+
...request.feeSompi !== void 0 ? ["fee supplied by the caller: the SDK does not price v1 compute budgets"] : []
|
|
682
|
+
]
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// src/silver-funding.ts
|
|
687
|
+
import { loadManagedKaspaWasmSync as loadManagedKaspaWasmSync3 } from "@hardkas/core";
|
|
688
|
+
import { calculateUpstreamStorageMass as calculateUpstreamStorageMass3, measureBuiltTransactionMass as measureBuiltTransactionMass3 } from "@hardkas/tx-builder";
|
|
689
|
+
function fundingError(code, message) {
|
|
690
|
+
const err = new Error(`${code}: ${message}`);
|
|
691
|
+
err.code = code;
|
|
692
|
+
return err;
|
|
693
|
+
}
|
|
694
|
+
function buildScriptFunding(request) {
|
|
695
|
+
const k = loadManagedKaspaWasmSync3();
|
|
696
|
+
const key = new k.PrivateKey(request.privateKey);
|
|
697
|
+
const address = key.toKeypair().toAddress(request.networkId);
|
|
698
|
+
const p2pk = k.payToAddressScript(address);
|
|
699
|
+
const own = { version: Number(p2pk.version), script: String(p2pk.script) };
|
|
700
|
+
const lock = request.lockingScript;
|
|
701
|
+
const make = (inputs, fee, signatureScripts) => {
|
|
702
|
+
const total = inputs.reduce((s, u) => s + u.amountSompi, 0n);
|
|
703
|
+
const change = total - request.valueSompi - fee;
|
|
704
|
+
const outputs = [{ value: request.valueSompi, scriptPublicKey: new k.ScriptPublicKey(lock.version, lock.script) }];
|
|
705
|
+
if (change > 0n) outputs.push({ value: change, scriptPublicKey: new k.ScriptPublicKey(own.version, own.script) });
|
|
706
|
+
const tx = new k.Transaction({
|
|
707
|
+
version: 0,
|
|
708
|
+
inputs: inputs.map((u, i) => ({
|
|
709
|
+
previousOutpoint: u.outpoint,
|
|
710
|
+
signatureScript: signatureScripts?.[i] ?? "",
|
|
711
|
+
sequence: 0n,
|
|
712
|
+
sigOpCount: 1,
|
|
713
|
+
utxo: {
|
|
714
|
+
outpoint: u.outpoint,
|
|
715
|
+
amount: u.amountSompi,
|
|
716
|
+
scriptPublicKey: new k.ScriptPublicKey(own.version, own.script),
|
|
717
|
+
blockDaaScore: u.blockDaaScore,
|
|
718
|
+
isCoinbase: u.isCoinbase
|
|
719
|
+
}
|
|
720
|
+
})),
|
|
721
|
+
outputs,
|
|
722
|
+
lockTime: 0n,
|
|
723
|
+
subnetworkId: "0000000000000000000000000000000000000000",
|
|
724
|
+
gas: 0n,
|
|
725
|
+
payload: ""
|
|
726
|
+
});
|
|
727
|
+
tx.storageMass = calculateUpstreamStorageMass3(
|
|
728
|
+
inputs.map((u) => u.amountSompi),
|
|
729
|
+
change > 0n ? [request.valueSompi, change] : [request.valueSompi],
|
|
730
|
+
request.networkId
|
|
731
|
+
);
|
|
732
|
+
return { tx, change };
|
|
733
|
+
};
|
|
734
|
+
for (const u of request.utxos) {
|
|
735
|
+
if (Number(u.scriptPublicKey.version) !== own.version || String(u.scriptPublicKey.script).toLowerCase() !== own.script) {
|
|
736
|
+
throw fundingError("FUNDING_KEY_MISMATCH", `${u.outpoint.transactionId}:${u.outpoint.index} is not a P2PK output of the funding key`);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
const selected = [];
|
|
740
|
+
for (const u of request.utxos) {
|
|
741
|
+
selected.push(u);
|
|
742
|
+
const total = selected.reduce((s, x) => s + x.amountSompi, 0n);
|
|
743
|
+
if (total <= request.valueSompi) continue;
|
|
744
|
+
let fee = 0n;
|
|
745
|
+
for (let round = 0; round < 8; round++) {
|
|
746
|
+
if (total < request.valueSompi + fee) break;
|
|
747
|
+
const measured = measureBuiltTransactionMass3(make(selected, fee).tx, request.networkId);
|
|
748
|
+
if (!measured.standard) throw fundingError("TX_MASS_ABOVE_STANDARD_LIMIT", `mass ${measured.mass} exceeds the maximum standard mass`);
|
|
749
|
+
if (measured.minimumFeeSompi <= fee) {
|
|
750
|
+
const unsigned = make(selected, fee).tx;
|
|
751
|
+
const signatures = selected.map((_, i) => String(k.createInputSignature(unsigned, i, key, k.SighashType.All)));
|
|
752
|
+
const { tx, change } = make(selected, fee, signatures);
|
|
753
|
+
return {
|
|
754
|
+
rpcTransaction: parseWasmTxToRpc(tx.serializeToObject()),
|
|
755
|
+
txId: String(tx.id),
|
|
756
|
+
outputIndex: 0,
|
|
757
|
+
feeSompi: fee,
|
|
758
|
+
changeSompi: change,
|
|
759
|
+
spent: selected.map((s) => s.outpoint)
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
fee = measured.minimumFeeSompi;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
throw fundingError("FUNDING_INSUFFICIENT", `the given outputs cannot cover ${request.valueSompi} sompi plus the fee`);
|
|
766
|
+
}
|
|
767
|
+
|
|
241
768
|
// src/kaspa-sdk-keygen.ts
|
|
242
769
|
import { getNetworkPrefix } from "@hardkas/core";
|
|
243
770
|
var KaspaSdkKeyGenerator = class {
|
|
@@ -246,7 +773,8 @@ var KaspaSdkKeyGenerator = class {
|
|
|
246
773
|
constructor(options) {
|
|
247
774
|
this.networkId = options?.networkId || "simnet";
|
|
248
775
|
const rawLoader = options?.sdkLoader || (async () => {
|
|
249
|
-
|
|
776
|
+
const { loadKaspaWasm: loadKaspaWasm2 } = await import("./signer-backend-LHWY7ULI.js");
|
|
777
|
+
return await loadKaspaWasm2();
|
|
250
778
|
});
|
|
251
779
|
this.sdkLoader = async () => {
|
|
252
780
|
try {
|
|
@@ -324,6 +852,7 @@ var KaspaSdkRealTxSigner = class {
|
|
|
324
852
|
try {
|
|
325
853
|
sdk = await this.sdkLoader();
|
|
326
854
|
} catch (e) {
|
|
855
|
+
if (typeof e?.code === "string" && e.code.startsWith("WASM_TOOLCHAIN_")) throw e;
|
|
327
856
|
throw new Error(
|
|
328
857
|
"Kaspa SDK real transaction signer dependency is not installed. Install/configure the supported Kaspa WASM SDK adapter."
|
|
329
858
|
);
|
|
@@ -344,12 +873,6 @@ var KaspaSdkRealTxSigner = class {
|
|
|
344
873
|
`UTXO ${u.outpoint.transactionId}:${u.outpoint.index} is missing scriptPublicKey required for signing.`
|
|
345
874
|
);
|
|
346
875
|
}
|
|
347
|
-
let spkHex = String(u.scriptPublicKey);
|
|
348
|
-
let spkVersion = 0;
|
|
349
|
-
if (spkHex.length >= 68) {
|
|
350
|
-
spkVersion = parseInt(spkHex.slice(0, 4), 16) || 0;
|
|
351
|
-
spkHex = spkHex.slice(4);
|
|
352
|
-
}
|
|
353
876
|
return {
|
|
354
877
|
address: account.address,
|
|
355
878
|
outpoint: {
|
|
@@ -358,25 +881,19 @@ var KaspaSdkRealTxSigner = class {
|
|
|
358
881
|
},
|
|
359
882
|
utxoEntry: {
|
|
360
883
|
amount: BigInt(u.amountSompi),
|
|
361
|
-
scriptPublicKey:
|
|
884
|
+
scriptPublicKey: toWasmScriptPublicKey(sdk, u.scriptPublicKey),
|
|
362
885
|
blockDaaScore: BigInt(u.blockDaaScore ?? 0),
|
|
363
886
|
isCoinbase: u.isCoinbase ?? false
|
|
364
887
|
}
|
|
365
888
|
};
|
|
366
889
|
});
|
|
367
|
-
const
|
|
368
|
-
(o) => new sdk.PaymentOutput(new sdk.Address(o.address), BigInt(o.amountSompi))
|
|
369
|
-
);
|
|
370
|
-
const changeAddress = plan.change ? plan.change.address : account.address;
|
|
371
|
-
const priorityFee = BigInt(plan.estimatedFeeSompi);
|
|
372
|
-
const unsignedTx = sdk.createTransaction(
|
|
890
|
+
const unsignedTx = createBalancedTransaction(sdk, {
|
|
373
891
|
utxos,
|
|
374
|
-
outputs,
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
);
|
|
892
|
+
outputs: planOutputsWithChange(plan),
|
|
893
|
+
feeSompi: BigInt(plan.estimatedFeeSompi)
|
|
894
|
+
});
|
|
378
895
|
const signedTx = sdk.signTransaction(unsignedTx, [privateKey], true);
|
|
379
|
-
const innerTx = signedTx
|
|
896
|
+
const innerTx = signedTx;
|
|
380
897
|
const txId = innerTx?.id;
|
|
381
898
|
const payload = JSON.stringify(
|
|
382
899
|
innerTx.toJSON(),
|
|
@@ -483,9 +1000,7 @@ async function appendToKeystoreJson(workspaceRoot, alias, accountData) {
|
|
|
483
1000
|
|
|
484
1001
|
// src/address-manager.ts
|
|
485
1002
|
import { createHash } from "crypto";
|
|
486
|
-
import { createRequire } from "module";
|
|
487
1003
|
import { getNetworkPrefix as getNetworkPrefix2 } from "@hardkas/core";
|
|
488
|
-
var require2 = createRequire(import.meta.url);
|
|
489
1004
|
function resolveChain(chain) {
|
|
490
1005
|
if (chain === "receive" || chain === 0) return 0;
|
|
491
1006
|
if (chain === "change" || chain === 1) return 1;
|
|
@@ -517,12 +1032,16 @@ var AddressManager = {
|
|
|
517
1032
|
const hash = createHash("sha256").update(payload).digest("hex");
|
|
518
1033
|
let address;
|
|
519
1034
|
try {
|
|
520
|
-
const kaspa =
|
|
1035
|
+
const kaspa = loadKaspaWasmSync();
|
|
521
1036
|
const priv = new kaspa.PrivateKey(hash);
|
|
522
1037
|
address = priv.toKeypair().toAddress(getNetworkPrefix2(network)).toString();
|
|
523
1038
|
} catch (e) {
|
|
524
|
-
|
|
525
|
-
|
|
1039
|
+
if (typeof e?.code === "string" && e.code.startsWith("WASM_TOOLCHAIN_")) throw e;
|
|
1040
|
+
const err = new Error(
|
|
1041
|
+
`ADDRESS_DERIVATION_UNAVAILABLE: the Kaspa WASM SDK could not derive an address: ${e instanceof Error ? e.message : String(e)}`
|
|
1042
|
+
);
|
|
1043
|
+
err.code = "ADDRESS_DERIVATION_UNAVAILABLE";
|
|
1044
|
+
throw err;
|
|
526
1045
|
}
|
|
527
1046
|
return {
|
|
528
1047
|
address,
|
|
@@ -712,6 +1231,7 @@ export {
|
|
|
712
1231
|
KeystoreManager,
|
|
713
1232
|
LazyAccountAuthorizer,
|
|
714
1233
|
PrivateKeyAuthorizer,
|
|
1234
|
+
SILVER_SPEND_DRAFT_SCHEMA,
|
|
715
1235
|
SimulatedSigner,
|
|
716
1236
|
StaticSignatureScriptAuthorizer,
|
|
717
1237
|
UnsupportedKaspaKeyGenerator,
|
|
@@ -723,12 +1243,20 @@ export {
|
|
|
723
1243
|
appendToKeystoreJson,
|
|
724
1244
|
assertAccountCompatible,
|
|
725
1245
|
assertSigningNetworkAllowed,
|
|
1246
|
+
assertValueConservation,
|
|
1247
|
+
buildCovenantGenesis,
|
|
1248
|
+
buildCovenantTransition,
|
|
1249
|
+
buildScriptFunding,
|
|
1250
|
+
buildSilverSweep,
|
|
1251
|
+
createBalancedTransaction,
|
|
726
1252
|
createDevSigner,
|
|
727
1253
|
createEmptyRealAccountStore,
|
|
728
1254
|
createLocalKaspaWallet,
|
|
1255
|
+
createScriptTransaction,
|
|
729
1256
|
describeAccount,
|
|
730
1257
|
detectCapabilities,
|
|
731
1258
|
ensureDevAccounts,
|
|
1259
|
+
finalizeSilverSpend,
|
|
732
1260
|
getDefaultRealAccountsPath,
|
|
733
1261
|
getKaspaSigningBackendStatus,
|
|
734
1262
|
getOrCreateDevAccount,
|
|
@@ -739,16 +1267,22 @@ export {
|
|
|
739
1267
|
listHardkasAccounts,
|
|
740
1268
|
listRealDevAccounts,
|
|
741
1269
|
loadKaspaWasm,
|
|
1270
|
+
loadKaspaWasmSync,
|
|
742
1271
|
loadOrCreateRealAccountStore,
|
|
743
1272
|
loadRealAccountStore,
|
|
744
1273
|
loadRealAccountStoreSync,
|
|
1274
|
+
parseWasmTxToRpc,
|
|
1275
|
+
planOutputsWithChange,
|
|
745
1276
|
prepareEvmAccountExport,
|
|
1277
|
+
prepareSilverSpend,
|
|
746
1278
|
removeRealDevAccount,
|
|
747
1279
|
resolveHardkasAccount,
|
|
748
1280
|
resolveHardkasAccountAddress,
|
|
749
1281
|
resolveRealAccountOrAddress,
|
|
750
1282
|
saveRealAccountStore,
|
|
1283
|
+
signSilverSpend,
|
|
751
1284
|
signTxPlanArtifact,
|
|
1285
|
+
toWasmScriptPublicKey,
|
|
752
1286
|
validateAccountName,
|
|
753
1287
|
validateAddressNetwork,
|
|
754
1288
|
validateAddressPrefix,
|