@hardkas/accounts 0.12.0-rc.2 → 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.
@@ -2,7 +2,7 @@ import {
2
2
  LazyAccountAuthorizer,
3
3
  PrivateKeyAuthorizer,
4
4
  StaticSignatureScriptAuthorizer
5
- } from "./chunk-YJL7P33W.js";
5
+ } from "./chunk-E73SSWAX.js";
6
6
  export {
7
7
  LazyAccountAuthorizer,
8
8
  PrivateKeyAuthorizer,
@@ -219,7 +219,7 @@ function resolveHardkasAccount(options) {
219
219
  let alias = nameOrAddress;
220
220
  if (alias === "0") alias = "alice";
221
221
  if (alias === "1") alias = "bob";
222
- const accounts = listHardkasAccounts(config);
222
+ const accounts = listHardkasAccounts(config, options.executionTarget);
223
223
  const found = accounts.find((a) => a.name === alias);
224
224
  if (found) {
225
225
  return found;
@@ -229,17 +229,63 @@ function resolveHardkasAccount(options) {
229
229
  `Unknown HardKAS account '${nameOrAddress}'. Available accounts: ${available}`
230
230
  );
231
231
  }
232
- function listHardkasAccounts(config) {
232
+ function assertAccountCompatible(account, target) {
233
+ if (account.kind === "synthetic" && target.mode !== "simulator") {
234
+ throw new AccountNetworkMismatchError({
235
+ expected: `Execution mode 'simulator'`,
236
+ actual: `Execution mode '${target.mode}'`,
237
+ detail: `Account '${account.name}' is a synthetic simulator account and cannot be used with mode '${target.mode}'.`
238
+ });
239
+ }
240
+ if ("network" in account && account.network && target.network && account.network !== target.network) {
241
+ throw new AccountNetworkMismatchError({
242
+ expected: target.network,
243
+ actual: account.network,
244
+ detail: `Account '${account.name}' is bound to network '${account.network}' but execution target is '${target.network}'.`
245
+ });
246
+ }
247
+ }
248
+ function listHardkasAccounts(config, executionTarget) {
233
249
  const accounts = /* @__PURE__ */ new Map();
250
+ let targetMode = "localnet";
251
+ if (executionTarget) {
252
+ targetMode = executionTarget.mode;
253
+ } else {
254
+ const execConfig = config?.execution;
255
+ if (execConfig) {
256
+ if (execConfig.mode) {
257
+ targetMode = execConfig.mode;
258
+ } else if (execConfig.default) {
259
+ const targetName = execConfig.default;
260
+ const target = execConfig.targets?.[targetName];
261
+ if (target?.mode) {
262
+ targetMode = target.mode;
263
+ } else if (targetName === "simulator") {
264
+ targetMode = "simulator";
265
+ }
266
+ }
267
+ } else if (config?.defaultNetwork === "simulated") {
268
+ targetMode = "simulator";
269
+ }
270
+ }
234
271
  const detAccounts = createDeterministicAccounts();
235
272
  for (const det of detAccounts) {
236
- accounts.set(det.name, {
237
- name: det.name,
238
- kind: "synthetic",
239
- executionMode: "simulator",
240
- address: det.address,
241
- evmAddress: det.evmAddress
242
- });
273
+ if (targetMode === "simulator") {
274
+ accounts.set(det.name, {
275
+ name: det.name,
276
+ kind: "synthetic",
277
+ executionMode: "simulator",
278
+ address: `kaspa:sim_${det.name}`,
279
+ evmAddress: det.evmAddress
280
+ });
281
+ } else {
282
+ accounts.set(det.name, {
283
+ name: det.name,
284
+ kind: "kaspa",
285
+ network: "simnet",
286
+ address: det.address
287
+ });
288
+ }
243
289
  }
244
290
  const workspaceRoot = config?.cwd || process.cwd();
245
291
  const devAccountsDir = path2.join(workspaceRoot, ".hardkas", "dev-accounts");
@@ -255,13 +301,23 @@ function listHardkasAccounts(config) {
255
301
  if (!keystore.metadata?.network) {
256
302
  throw new AccountNetworkMismatchError({ expected: "known network", actual: "undefined", detail: `at ${path2.join(devAccountsDir, file)}` });
257
303
  }
258
- accounts.set(name, {
259
- name,
260
- kind: "kaspa",
261
- network: keystore.metadata.network,
262
- address: keystore.payload?.address || keystore.metadata?.address,
263
- keystorePath: path2.join(devAccountsDir, file)
264
- });
304
+ if (targetMode === "simulator") {
305
+ accounts.set(name, {
306
+ name,
307
+ kind: "synthetic",
308
+ executionMode: "simulator",
309
+ address: `kaspa:sim_${name}`,
310
+ keystorePath: path2.join(devAccountsDir, file)
311
+ });
312
+ } else {
313
+ accounts.set(name, {
314
+ name,
315
+ kind: "kaspa",
316
+ network: keystore.metadata.network,
317
+ address: keystore.payload?.address || keystore.metadata?.address,
318
+ keystorePath: path2.join(devAccountsDir, file)
319
+ });
320
+ }
265
321
  }
266
322
  } catch (e) {
267
323
  if (e instanceof AccountNetworkMismatchError) throw e;
@@ -275,19 +331,15 @@ function listHardkasAccounts(config) {
275
331
  const data = fs2.readFileSync(keystoreJsonPath, "utf-8");
276
332
  const ks = JSON.parse(data);
277
333
  for (const [name, acc] of Object.entries(ks)) {
278
- const existing = accounts.get(name);
279
- const configKind = acc.type === "simulated" ? "synthetic" : "kaspa";
280
- if (existing && existing.kind !== configKind) {
281
- console.error(`COLLISION DETECTED for ${name}. existing:`, existing, `configKind:`, configKind, `workspaceRoot:`, workspaceRoot, `keystoreJsonPath:`, keystoreJsonPath);
282
- throw new CrossWorldAccountCollisionError({ accountId: name, worlds: [existing.kind, configKind] });
283
- }
284
334
  if (acc.type === "simulated") {
285
- accounts.set(name, {
286
- name,
287
- kind: "synthetic",
288
- executionMode: "simulator",
289
- address: acc.address
290
- });
335
+ if (targetMode === "simulator") {
336
+ accounts.set(name, {
337
+ name,
338
+ kind: "synthetic",
339
+ executionMode: "simulator",
340
+ address: acc.address
341
+ });
342
+ }
291
343
  } else {
292
344
  if (!acc.network) {
293
345
  throw new AccountNetworkMismatchError({ expected: "known network", actual: "undefined", detail: "in keystore.json" });
@@ -373,7 +425,8 @@ async function resolveHardkasAccountAddress(accountOrAddress, config, context =
373
425
  }
374
426
  if (!accountOrAddress.startsWith("kaspa:sim_")) {
375
427
  try {
376
- const kaspa = await import("kaspa-wasm");
428
+ const { loadKaspaWasm } = await import("./signer-backend-LHWY7ULI.js");
429
+ const kaspa = await loadKaspaWasm();
377
430
  try {
378
431
  if (typeof kaspa.Address === "function" || kaspa.Address) {
379
432
  new kaspa.Address(accountOrAddress);
@@ -387,6 +440,7 @@ async function resolveHardkasAccountAddress(accountOrAddress, config, context =
387
440
  }
388
441
  } catch (e) {
389
442
  if (e instanceof Error && e.code === "HARDKAS_INVALID_ADDRESS") throw e;
443
+ if (e instanceof Error && e.code === "WASM_TOOLCHAIN_INTEGRITY_FAILED") throw e;
390
444
  if (e instanceof Error && (e.code === "ERR_MODULE_NOT_FOUND" || (e instanceof Error ? e instanceof Error ? e.message : String(e) : String(e)).includes("Cannot find module") || (e instanceof Error ? e instanceof Error ? e.message : String(e) : String(e)).includes("kaspa-wasm"))) {
391
445
  const err = new Error(
392
446
  "ADDRESS_VALIDATOR_UNAVAILABLE: The Kaspa address validator backend is not available."
@@ -450,6 +504,7 @@ export {
450
504
  listRealDevAccounts,
451
505
  resolveRealAccountOrAddress,
452
506
  resolveHardkasAccount,
507
+ assertAccountCompatible,
453
508
  listHardkasAccounts,
454
509
  resolveHardkasAccountAddress,
455
510
  describeAccount
@@ -2,18 +2,14 @@
2
2
  import path from "path";
3
3
  import fs from "fs";
4
4
  import { pathToFileURL } from "url";
5
+ import { loadManagedKaspaWasmSync } from "@hardkas/core";
6
+ function loadKaspaWasmSync() {
7
+ return loadManagedKaspaWasmSync();
8
+ }
5
9
  async function loadKaspaWasm(config) {
6
- const provider = config?.provider || "npm";
7
- if (provider === "npm") {
8
- try {
9
- return await import("kaspa-wasm");
10
- } catch (error) {
11
- const err = new Error(
12
- "SIGNER_BACKEND_UNAVAILABLE: Official Kaspa WASM backend is required to sign transactions.\nInstall it via: npm install kaspa-wasm"
13
- );
14
- err.code = "SIGNER_BACKEND_UNAVAILABLE";
15
- throw err;
16
- }
10
+ const provider = config?.provider || "managed";
11
+ if (provider === "managed") {
12
+ return loadKaspaWasmSync();
17
13
  }
18
14
  if (provider === "local" || provider === "release-asset") {
19
15
  if (!config?.path) {
@@ -52,13 +48,7 @@ async function loadKaspaWasm(config) {
52
48
  }
53
49
  }
54
50
  function detectCapabilities(sdk) {
55
- let v1 = false;
56
- if (sdk.createTransaction && sdk.createTransaction.length >= 8) {
57
- v1 = true;
58
- }
59
- if (sdk.createV1Transaction || sdk.Transaction && sdk.Transaction.prototype && !!Object.getOwnPropertyDescriptor(sdk.Transaction.prototype, "storageMass")) {
60
- v1 = true;
61
- }
51
+ const v1 = !!(sdk?.Transaction?.prototype && Object.getOwnPropertyDescriptor(sdk.Transaction.prototype, "storageMass"));
62
52
  return { transactionV1Signing: v1 };
63
53
  }
64
54
  async function getKaspaSigningBackendStatus(config) {
@@ -67,11 +57,11 @@ async function getKaspaSigningBackendStatus(config) {
67
57
  return {
68
58
  available: true,
69
59
  name: "Kaspa WASM SDK",
70
- version: sdk.version || "unknown",
60
+ version: typeof sdk.version === "function" ? String(sdk.version()) : "unknown",
71
61
  capabilities: detectCapabilities(sdk)
72
62
  };
73
63
  } catch (error) {
74
- if (error.code === "WASM_RELEASE_ASSET_NOT_FOUND") {
64
+ if (error.code === "WASM_RELEASE_ASSET_NOT_FOUND" || error.code === "WASM_TOOLCHAIN_INTEGRITY_FAILED") {
75
65
  throw error;
76
66
  }
77
67
  return {
@@ -84,6 +74,7 @@ async function getKaspaSigningBackendStatus(config) {
84
74
  }
85
75
 
86
76
  export {
77
+ loadKaspaWasmSync,
87
78
  loadKaspaWasm,
88
79
  detectCapabilities,
89
80
  getKaspaSigningBackendStatus
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  parseWasmTxToRpc
3
- } from "./chunk-R5P3WIWR.js";
4
- import {
5
- resolveHardkasAccount
6
- } from "./chunk-TRVIQTIO.js";
3
+ } from "./chunk-GM2BY4VS.js";
7
4
  import {
8
5
  loadKaspaWasm
9
- } from "./chunk-6DPO5V3N.js";
6
+ } from "./chunk-BNF566PS.js";
7
+ import {
8
+ resolveHardkasAccount
9
+ } from "./chunk-7KKJXU73.js";
10
10
  import {
11
11
  KeystoreManager
12
12
  } from "./chunk-YLG2NIAU.js";
@@ -15,10 +15,87 @@ import {
15
15
  import fs from "fs";
16
16
  import path from "path";
17
17
  import crypto from "crypto";
18
- import { deterministicCompare } from "@hardkas/core";
18
+ import { deterministicCompare, getNetworkPrefix as getNetworkPrefix2 } from "@hardkas/core";
19
19
 
20
20
  // src/kaspa-wasm-signer.ts
21
21
  import { calculateContentHash } from "@hardkas/artifacts";
22
+ import { getNetworkPrefix } from "@hardkas/core";
23
+
24
+ // src/wasm-transaction.ts
25
+ function assertValueConservation(input) {
26
+ const inputs = input.inputAmounts.reduce((a, b) => a + b, 0n);
27
+ const outputs = input.outputAmounts.reduce((a, b) => a + b, 0n);
28
+ if (input.feeSompi < 0n || inputs - outputs !== input.feeSompi) {
29
+ const err = new Error(
30
+ `TX_VALUE_NOT_CONSERVED: inputs ${inputs} - outputs ${outputs} = ${inputs - outputs} sompi, but the plan's fee is ${input.feeSompi}. Refusing to build a transaction whose difference would be paid as fee.`
31
+ );
32
+ err.code = "TX_VALUE_NOT_CONSERVED";
33
+ throw err;
34
+ }
35
+ }
36
+ function createBalancedTransaction(sdk, input) {
37
+ assertValueConservation({
38
+ inputAmounts: input.utxos.map((u) => u.utxoEntry.amount),
39
+ outputAmounts: input.outputs.map((o) => o.amountSompi),
40
+ feeSompi: input.feeSompi
41
+ });
42
+ return sdk.createTransaction(
43
+ [...input.utxos],
44
+ input.outputs.map((o) => o.output),
45
+ input.feeSompi
46
+ );
47
+ }
48
+ function createScriptTransaction(sdk, input) {
49
+ assertValueConservation({
50
+ inputAmounts: input.utxos.map((u) => u.utxoEntry.amount),
51
+ outputAmounts: input.outputs.map((o) => o.value),
52
+ feeSompi: input.feeSompi
53
+ });
54
+ return new sdk.Transaction({
55
+ version: 0,
56
+ inputs: input.utxos.map((u) => ({
57
+ previousOutpoint: { transactionId: u.outpoint.transactionId, index: u.outpoint.index },
58
+ signatureScript: "",
59
+ sequence: 0n,
60
+ sigOpCount: 1,
61
+ utxo: {
62
+ address: u.address,
63
+ outpoint: { transactionId: u.outpoint.transactionId, index: u.outpoint.index },
64
+ amount: u.utxoEntry.amount,
65
+ scriptPublicKey: u.utxoEntry.scriptPublicKey,
66
+ blockDaaScore: u.utxoEntry.blockDaaScore,
67
+ isCoinbase: u.utxoEntry.isCoinbase
68
+ }
69
+ })),
70
+ outputs: [...input.outputs],
71
+ lockTime: 0n,
72
+ subnetworkId: "0000000000000000000000000000000000000000",
73
+ gas: 0n,
74
+ payload: ""
75
+ });
76
+ }
77
+ function toWasmScriptPublicKey(sdk, spk) {
78
+ if (spk && typeof spk === "object") {
79
+ const o = spk;
80
+ return new sdk.ScriptPublicKey(Number(o.version ?? 0), String(o.scriptPublicKey || o.script || ""));
81
+ }
82
+ const hex = String(spk ?? "");
83
+ if (/^[0-9a-fA-F]{72}$/.test(hex) && hex.startsWith("0000")) {
84
+ return new sdk.ScriptPublicKey(0, hex.slice(4));
85
+ }
86
+ return new sdk.ScriptPublicKey(0, hex);
87
+ }
88
+ function planOutputsWithChange(plan) {
89
+ const all = [...plan.outputs];
90
+ if (plan.change && BigInt(plan.change.amountSompi) > 0n) all.push(plan.change);
91
+ return all.map((o) => {
92
+ if (!o.address) throw new Error("Output is missing address.");
93
+ const amount = BigInt(o.amountSompi);
94
+ return { amountSompi: amount, output: { address: o.address, amount } };
95
+ });
96
+ }
97
+
98
+ // src/kaspa-wasm-signer.ts
22
99
  var KaspaWasmPrivateKeySigner = class {
23
100
  constructor(options) {
24
101
  this.options = options;
@@ -28,7 +105,7 @@ var KaspaWasmPrivateKeySigner = class {
28
105
  async signTxPlan(input) {
29
106
  const plan = input.planArtifact;
30
107
  const sdk = await loadKaspaWasm(this.options.wasmConfig);
31
- const { detectCapabilities } = await import("./signer-backend-W3LNCQA3.js");
108
+ const { detectCapabilities } = await import("./signer-backend-LHWY7ULI.js");
32
109
  const capabilities = detectCapabilities(sdk);
33
110
  if (plan.computeBudget !== void 0 || plan.outputs.some((o) => o.covenant)) {
34
111
  if (!capabilities.transactionV1Signing) {
@@ -56,7 +133,7 @@ var KaspaWasmPrivateKeySigner = class {
56
133
  if (!pkValue && account.keystorePath) {
57
134
  try {
58
135
  const KeystoreManager2 = (await import("./keystore-CMWEKGBF.js")).KeystoreManager;
59
- const DEV_ACCOUNTS_PASSWORD2 = (await import("./dev-accounts-B6ZVTPCW.js")).DEV_ACCOUNTS_PASSWORD;
136
+ const DEV_ACCOUNTS_PASSWORD2 = (await import("./dev-accounts-BSWPKAAE.js")).DEV_ACCOUNTS_PASSWORD;
60
137
  const keystore = await KeystoreManager2.loadEncryptedKeystore(account.keystorePath);
61
138
  const unlock = await KeystoreManager2.decryptEncryptedKeystore(keystore, DEV_ACCOUNTS_PASSWORD2);
62
139
  if (unlock.success && unlock.payload) {
@@ -75,8 +152,8 @@ var KaspaWasmPrivateKeySigner = class {
75
152
  err.code = "INVALID_PRIVATE_KEY_MATERIAL";
76
153
  throw err;
77
154
  }
78
- const expectedAddress = new sdk.PrivateKey(pkValue).toKeypair().toAddress(plan.networkId || "simnet").toString();
79
- const { PrivateKeyAuthorizer } = await import("./authorizers-OVWWAL5J.js");
155
+ const expectedAddress = new sdk.PrivateKey(pkValue).toKeypair().toAddress(getNetworkPrefix(plan.networkId || "simnet")).toString();
156
+ const { PrivateKeyAuthorizer } = await import("./authorizers-CP222OTW.js");
80
157
  const sourceInputs = plan.inputs || plan.selectedUtxos || [];
81
158
  for (let i = 0; i < numInputs; i++) {
82
159
  if (!authorizers[i]) {
@@ -93,7 +170,6 @@ var KaspaWasmPrivateKeySigner = class {
93
170
  }
94
171
  }
95
172
  try {
96
- console.log("DEBUG PLAN INPUTS:", JSON.stringify(plan.inputs || plan.selectedUtxos, null, 2));
97
173
  const sourceInputs = plan.inputs || plan.selectedUtxos || [];
98
174
  const utxos = sourceInputs.map((u) => {
99
175
  if (!u.outpoint.transactionId || u.outpoint.index === void 0) {
@@ -105,15 +181,27 @@ var KaspaWasmPrivateKeySigner = class {
105
181
  "UTXO is missing scriptPublicKey. Real signing flows must never fabricate cryptographic state."
106
182
  );
107
183
  }
184
+ let spkHex = "";
185
+ let spkVersion = 0;
186
+ if (typeof spk === "object" && spk !== null) {
187
+ spkVersion = Number(spk.version ?? 0);
188
+ spkHex = String(spk.scriptPublicKey || spk.script || "");
189
+ } else {
190
+ spkHex = String(spk);
191
+ if (/^[0-9a-fA-F]{72}$/.test(spkHex) && spkHex.startsWith("0000")) {
192
+ spkVersion = parseInt(spkHex.slice(0, 4), 16) || 0;
193
+ spkHex = spkHex.slice(4);
194
+ }
195
+ }
108
196
  return {
109
- address: plan.from.address,
197
+ address: u.address || plan.from.address,
110
198
  outpoint: {
111
199
  transactionId: u.outpoint.transactionId,
112
200
  index: u.outpoint.index
113
201
  },
114
202
  utxoEntry: {
115
203
  amount: BigInt(u.amountSompi),
116
- scriptPublicKey: new sdk.ScriptPublicKey(parseInt(spk.substring(0, 4), 16) || 0, spk.substring(4)),
204
+ scriptPublicKey: new sdk.ScriptPublicKey(spkVersion, spkHex),
117
205
  blockDaaScore: BigInt(u.blockDaaScore || "0"),
118
206
  isCoinbase: !!u.isCoinbase
119
207
  }
@@ -121,35 +209,28 @@ var KaspaWasmPrivateKeySigner = class {
121
209
  });
122
210
  const priorityFee = BigInt(plan.estimatedFeeSompi);
123
211
  const createFreshTx = () => {
124
- let unsignedTx;
125
- if (plan.txVersion === 1) {
126
- if (!capabilities.transactionV1Signing) {
127
- throw new Error("Transaction V1 signing is not supported by the installed kaspa-wasm version");
128
- }
129
- const allOutputs = [...plan.outputs];
130
- if (plan.change) {
131
- allOutputs.push({
132
- address: plan.change.address,
133
- amountSompi: plan.change.amountSompi
134
- });
135
- }
136
- const wasmOutputs = allOutputs.map((o, idx) => {
137
- if (!o.address) throw new Error("Output is missing address.");
138
- if (o.covenant && o.covenant.covenantId) {
139
- const hash = new sdk.Hash(o.covenant.covenantId);
140
- const binding = new sdk.CovenantBinding(o.covenant.authorizingInput, hash);
141
- return sdk.PaymentOutput.withCovenant(new sdk.Address(o.address), BigInt(o.amountSompi), binding);
142
- }
143
- return new sdk.PaymentOutput(new sdk.Address(o.address), BigInt(o.amountSompi));
212
+ const isV1 = plan.txVersion === 1;
213
+ if (isV1 && !capabilities.transactionV1Signing) {
214
+ throw new Error("Transaction V1 signing is not supported by the installed kaspa-wasm version");
215
+ }
216
+ const allOutputs = [...plan.outputs];
217
+ if (plan.change && BigInt(plan.change.amountSompi) > 0n) {
218
+ allOutputs.push({
219
+ address: plan.change.address,
220
+ amountSompi: plan.change.amountSompi
144
221
  });
145
- console.log("DEBUG: Calling V1 createTransaction with:", { utxos: utxos.length, wasmOutputs: wasmOutputs.length, priorityFee });
146
- console.log("DEBUG KASPA-WASM PATH:", import.meta.resolve("kaspa-wasm"));
147
- console.log("DEBUG CREATE TRANSACTION FN:", sdk.createTransaction.toString());
148
- unsignedTx = sdk.createTransaction(
149
- utxos,
150
- wasmOutputs,
151
- priorityFee
152
- );
222
+ }
223
+ const outputs = allOutputs.map((o) => {
224
+ if (!o.address) throw new Error("Output is missing address.");
225
+ const amount = BigInt(o.amountSompi);
226
+ if (isV1 && o.covenant && o.covenant.covenantId) {
227
+ const binding = new sdk.CovenantBinding(o.covenant.authorizingInput, new sdk.Hash(o.covenant.covenantId));
228
+ return { amountSompi: amount, output: sdk.PaymentOutput.withCovenant(new sdk.Address(o.address), amount, binding) };
229
+ }
230
+ return { amountSompi: amount, output: new sdk.PaymentOutput(new sdk.Address(o.address), amount) };
231
+ });
232
+ const unsignedTx = createBalancedTransaction(sdk, { utxos, outputs, feeSompi: priorityFee });
233
+ if (isV1) {
153
234
  const genesisGroups = /* @__PURE__ */ new Map();
154
235
  allOutputs.forEach((o, idx) => {
155
236
  if (o.covenant && !o.covenant.covenantId) {
@@ -168,29 +249,6 @@ var KaspaWasmPrivateKeySigner = class {
168
249
  if (plan.storageMass !== void 0) {
169
250
  unsignedTx.storageMass = BigInt(plan.storageMass);
170
251
  }
171
- } else {
172
- const allOutputs = [...plan.outputs];
173
- if (plan.change) {
174
- allOutputs.push({
175
- address: plan.change.address,
176
- amountSompi: plan.change.amountSompi
177
- });
178
- }
179
- const wasmOutputs = allOutputs.map((o) => {
180
- if (!o.address) throw new Error("Output is missing address.");
181
- return {
182
- address: o.address,
183
- amount: BigInt(o.amountSompi)
184
- };
185
- });
186
- console.log("DEBUG: Calling V0 createTransaction with:", { utxos: utxos.length, wasmOutputs: wasmOutputs.length, priorityFee });
187
- const dummyChange = plan.change?.address || plan.from.address;
188
- unsignedTx = sdk.createTransaction(
189
- utxos,
190
- wasmOutputs,
191
- dummyChange,
192
- priorityFee
193
- );
194
252
  }
195
253
  const inputs = unsignedTx.inputs;
196
254
  for (let i = 0; i < inputs.length; i++) {
@@ -202,7 +260,6 @@ var KaspaWasmPrivateKeySigner = class {
202
260
  inputs[i].sigOpCount = 0;
203
261
  }
204
262
  }
205
- console.log("DEBUG createFreshTx RETURNING:", unsignedTx?.constructor?.name);
206
263
  return unsignedTx;
207
264
  };
208
265
  const inputOverrides = {};
@@ -244,10 +301,7 @@ var KaspaWasmPrivateKeySigner = class {
244
301
  }
245
302
  const finalTx = createFreshTx();
246
303
  const signedTx = finalTx;
247
- const wasmTxStr = typeof signedTx.serializeToJSON === "function" ? signedTx.serializeToJSON() : signedTx.toString();
248
- console.log("DEBUG wasmTxStr:", wasmTxStr);
249
- console.log("DEBUG: about to parseWasmTxToRpc");
250
- const rpcTx = parseWasmTxToRpc(wasmTxStr, signedTx, inputOverrides, plan);
304
+ const rpcTx = parseWasmTxToRpc(signedTx.serializeToObject(), signedTx, inputOverrides, plan);
251
305
  const rawTx = JSON.stringify(rpcTx);
252
306
  return {
253
307
  signatureKind: "kaspa",
@@ -263,8 +317,6 @@ var KaspaWasmPrivateKeySigner = class {
263
317
  }
264
318
  };
265
319
  } catch (error) {
266
- console.error("DEBUG SIGNING ERROR:", error);
267
- console.error("DEBUG STACK:", error?.stack || "NO STACK (raw panic)");
268
320
  throw new Error(
269
321
  `Kaspa WASM signing failed: ${error instanceof Error ? error.stack || error.message : JSON.stringify(error, Object.getOwnPropertyNames(error))}`
270
322
  );
@@ -290,6 +342,8 @@ async function ensureDevAccounts(workspaceDir) {
290
342
  }
291
343
  await getOrCreateDevAccount(workspaceDir, 0, "alice");
292
344
  await getOrCreateDevAccount(workspaceDir, 1, "bob");
345
+ await getOrCreateDevAccount(workspaceDir, 2, "carol");
346
+ await getOrCreateDevAccount(workspaceDir, 3, "dave");
293
347
  }
294
348
  async function getOrCreateDevAccount(workspaceDir, index, alias) {
295
349
  const devAccountsDir = path.join(workspaceDir, ".hardkas", "dev-accounts");
@@ -314,70 +368,12 @@ async function getOrCreateDevAccount(workspaceDir, index, alias) {
314
368
  const seedString = `${SIMNET_DETERMINISTIC_SEED}-${index}`;
315
369
  const privateKeyHex = crypto.createHash("sha256").update(seedString).digest("hex");
316
370
  const network = "simnet";
317
- const isSimnet = ["simnet", "kaspasim", "local"].includes(network);
318
- let address = "";
319
- let privateKey = "";
320
- let publicKey = "";
321
- try {
322
- if (isSimnet) {
323
- let kaspaWasm;
324
- try {
325
- kaspaWasm = await import(
326
- /* @vite-ignore */
327
- "kaspa-wasm"
328
- );
329
- } catch (e) {
330
- console.warn(`
331
- [Warning] kaspa-wasm is not installed. Required for simnet.`);
332
- return { address: "", privateKey: "", publicKey: "" };
333
- }
334
- const privKey = new kaspaWasm.PrivateKey(privateKeyHex);
335
- const kp = privKey.toKeypair();
336
- address = kp.toAddress(network).toString();
337
- publicKey = kp.publicKey;
338
- privateKey = privateKeyHex;
339
- } else {
340
- let sdkModule;
341
- try {
342
- sdkModule = await import(
343
- /* @vite-ignore */
344
- "@kaspa/core-lib"
345
- );
346
- } catch (e) {
347
- console.warn(`
348
- [Warning] @kaspa/core-lib is not installed.`);
349
- return { address: "", privateKey: "", publicKey: "" };
350
- }
351
- const sdk = sdkModule.default || sdkModule;
352
- if (typeof sdk.initRuntime === "function") {
353
- await sdk.initRuntime();
354
- }
355
- const privKey = new sdk.PrivateKey(privateKeyHex);
356
- const pubKey = privKey.toPublicKey();
357
- try {
358
- address = pubKey.toAddress(network).toString();
359
- } catch (e) {
360
- const msg = e instanceof Error ? e instanceof Error ? e instanceof Error ? e.message : String(e) : String(e) : String(e);
361
- if (msg.includes("Second argument must be") || msg.includes("Unsupported")) {
362
- const err = new Error("DEV_ACCOUNT_BACKEND_UNSUPPORTED_NETWORK");
363
- err.code = "DEV_ACCOUNT_BACKEND_UNSUPPORTED_NETWORK";
364
- throw err;
365
- }
366
- throw e;
367
- }
368
- publicKey = pubKey.toString();
369
- privateKey = privKey.toString();
370
- }
371
- } catch (e) {
372
- const msg = e instanceof Error ? e instanceof Error ? e instanceof Error ? e.message : String(e) : String(e) : String(e);
373
- if (msg === "DEV_ACCOUNT_BACKEND_UNSUPPORTED_NETWORK") {
374
- throw e;
375
- }
376
- console.warn(`
377
- [Warning] Could not generate dev account '${alias}'.
378
- ${msg}`);
379
- return { address: "", privateKey: "", publicKey: "" };
380
- }
371
+ const { loadKaspaWasm: loadKaspaWasm2 } = await import("./signer-backend-LHWY7ULI.js");
372
+ const kaspaWasm = await loadKaspaWasm2();
373
+ const kp = new kaspaWasm.PrivateKey(privateKeyHex).toKeypair();
374
+ const address = kp.toAddress(getNetworkPrefix2(network)).toString();
375
+ const publicKey = kp.publicKey;
376
+ const privateKey = privateKeyHex;
381
377
  const accountData = {
382
378
  address,
383
379
  privateKey,
@@ -446,6 +442,11 @@ async function createDevSigner(workspaceDir, accountNameOrAddress) {
446
442
  }
447
443
 
448
444
  export {
445
+ assertValueConservation,
446
+ createBalancedTransaction,
447
+ createScriptTransaction,
448
+ toWasmScriptPublicKey,
449
+ planOutputsWithChange,
449
450
  DEV_ACCOUNTS_PASSWORD,
450
451
  ensureDevAccounts,
451
452
  getOrCreateDevAccount,
@@ -1,4 +1,5 @@
1
1
  // src/authorizers.ts
2
+ import { getNetworkPrefix } from "@hardkas/core";
2
3
  var StaticSignatureScriptAuthorizer = class {
3
4
  constructor(signatureScript) {
4
5
  this.signatureScript = signatureScript;
@@ -30,7 +31,7 @@ var PrivateKeyAuthorizer = class {
30
31
  const { wasm, wasmTransaction, inputIndex } = ctx;
31
32
  const privateKey = new wasm.PrivateKey(this.privateKeyHex);
32
33
  const networkId = context.plan.networkId || "simnet";
33
- const expectedAddress = privateKey.toKeypair().toAddress(networkId).toString();
34
+ const expectedAddress = privateKey.toKeypair().toAddress(getNetworkPrefix(networkId)).toString();
34
35
  if (planInput.address && expectedAddress !== planInput.address) {
35
36
  throw new Error(
36
37
  `PRIVATE_KEY_DOES_NOT_CONTROL_INPUT: The provided private key for account '${this.accountName}' derives to address '${expectedAddress}', but input ${context.inputIndex} is controlled by '${planInput.address}'.`
@@ -38,9 +39,7 @@ var PrivateKeyAuthorizer = class {
38
39
  }
39
40
  const tx = wasmTransaction;
40
41
  try {
41
- console.log("DEBUG: Calling signTransaction");
42
42
  const signedTx = wasm.signTransaction(tx, [privateKey], false);
43
- console.log("DEBUG: signTransaction OK");
44
43
  const sigScript = signedTx.inputs[inputIndex].signatureScript;
45
44
  if (!sigScript || sigScript.length === 0) {
46
45
  throw new Error(`UNAUTHORIZED_TRANSACTION_INPUT: Kaspa WASM failed to generate a signature script for input ${inputIndex} using account '${this.accountName}'.`);
@@ -63,7 +62,7 @@ var LazyAccountAuthorizer = class {
63
62
  accountName;
64
63
  workspaceRoot;
65
64
  async authorize(context) {
66
- const { resolveHardkasAccount } = await import("./resolve-GHZEED5L.js");
65
+ const { resolveHardkasAccount } = await import("./resolve-KMMTZWC3.js");
67
66
  const account = await resolveHardkasAccount({
68
67
  nameOrAddress: this.accountName,
69
68
  config: { cwd: this.workspaceRoot }
@@ -75,7 +74,7 @@ var LazyAccountAuthorizer = class {
75
74
  if (!pkValue && account.keystorePath) {
76
75
  try {
77
76
  const { KeystoreManager } = await import("./keystore-CMWEKGBF.js");
78
- const { DEV_ACCOUNTS_PASSWORD } = await import("./dev-accounts-B6ZVTPCW.js");
77
+ const { DEV_ACCOUNTS_PASSWORD } = await import("./dev-accounts-BSWPKAAE.js");
79
78
  const keystore = await KeystoreManager.loadEncryptedKeystore(account.keystorePath);
80
79
  const unlock = await KeystoreManager.decryptEncryptedKeystore(keystore, DEV_ACCOUNTS_PASSWORD);
81
80
  if (unlock.success && unlock.payload) {