@hardkas/accounts 0.11.2-alpha → 0.11.4-alpha

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.
@@ -0,0 +1,452 @@
1
+ import {
2
+ parseWasmTxToRpc
3
+ } from "./chunk-WRRHW2WO.js";
4
+ import {
5
+ resolveHardkasAccount
6
+ } from "./chunk-ILASLDZU.js";
7
+ import {
8
+ loadKaspaWasm
9
+ } from "./chunk-6DPO5V3N.js";
10
+ import {
11
+ KeystoreManager
12
+ } from "./chunk-YLG2NIAU.js";
13
+
14
+ // src/dev-accounts.ts
15
+ import fs from "fs";
16
+ import path from "path";
17
+ import crypto from "crypto";
18
+ import { deterministicCompare } from "@hardkas/core";
19
+
20
+ // src/kaspa-wasm-signer.ts
21
+ import { calculateContentHash } from "@hardkas/artifacts";
22
+ var KaspaWasmPrivateKeySigner = class {
23
+ constructor(options) {
24
+ this.options = options;
25
+ }
26
+ options;
27
+ kind = "kaspa-private-key";
28
+ async signTxPlan(input) {
29
+ const plan = input.planArtifact;
30
+ const sdk = await loadKaspaWasm(this.options.wasmConfig);
31
+ const { detectCapabilities } = await import("./signer-backend-W3LNCQA3.js");
32
+ const capabilities = detectCapabilities(sdk);
33
+ if (plan.computeBudget !== void 0 || plan.outputs.some((o) => o.covenant)) {
34
+ if (!capabilities.transactionV1Signing) {
35
+ throw new Error("Transaction V1 signing is not supported by the installed kaspa-wasm version");
36
+ }
37
+ }
38
+ assertSigningNetworkAllowed({
39
+ network: plan.networkId,
40
+ mode: plan.mode,
41
+ allowMainnet: this.options.allowMainnet
42
+ });
43
+ let authorizers = input.authorizers ? { ...input.authorizers } : {};
44
+ const numInputs = plan.inputs?.length || plan.selectedUtxos?.length || 0;
45
+ if (this.options.account) {
46
+ const account = this.options.account;
47
+ let pkValue = account.privateKeyEnv ? process.env[account.privateKeyEnv] : void 0;
48
+ if (!pkValue && account.privateKey) {
49
+ if (plan.networkId === "mainnet") {
50
+ throw new Error(
51
+ `Mainnet guard: Unsafe plaintext privateKey fallback is forbidden on mainnet for account '${account.name}'. Use privateKeyEnv instead.`
52
+ );
53
+ }
54
+ pkValue = account.privateKey;
55
+ }
56
+ if (!pkValue && account.keystorePath) {
57
+ try {
58
+ const KeystoreManager2 = (await import("./keystore-CMWEKGBF.js")).KeystoreManager;
59
+ const DEV_ACCOUNTS_PASSWORD2 = (await import("./dev-accounts-FU4XTSGF.js")).DEV_ACCOUNTS_PASSWORD;
60
+ const keystore = await KeystoreManager2.loadEncryptedKeystore(account.keystorePath);
61
+ const unlock = await KeystoreManager2.decryptEncryptedKeystore(keystore, DEV_ACCOUNTS_PASSWORD2);
62
+ if (unlock.success && unlock.payload) {
63
+ pkValue = unlock.payload.privateKey;
64
+ }
65
+ } catch (e) {
66
+ }
67
+ }
68
+ if (!pkValue) {
69
+ const err = new Error(`DEV_ACCOUNT_KEY_UNAVAILABLE: Missing required private key for account '${account.name}'.`);
70
+ err.code = "DEV_ACCOUNT_KEY_UNAVAILABLE";
71
+ throw err;
72
+ }
73
+ if (typeof pkValue !== "string" || pkValue.trim() === "" || !/^[0-9a-fA-F]{64}$/.test(pkValue)) {
74
+ const err = new Error("INVALID_PRIVATE_KEY_MATERIAL: Private key must be a valid 64-character hex string.");
75
+ err.code = "INVALID_PRIVATE_KEY_MATERIAL";
76
+ throw err;
77
+ }
78
+ const expectedAddress = new sdk.PrivateKey(pkValue).toKeypair().toAddress(plan.networkId || "simnet").toString();
79
+ const { PrivateKeyAuthorizer } = await import("./authorizers-N2RUAVJV.js");
80
+ const sourceInputs = plan.inputs || plan.selectedUtxos || [];
81
+ for (let i = 0; i < numInputs; i++) {
82
+ if (!authorizers[i]) {
83
+ const inputAddress = sourceInputs[i]?.address;
84
+ if (inputAddress === expectedAddress) {
85
+ authorizers[i] = new PrivateKeyAuthorizer(account.name, pkValue);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ for (let i = 0; i < numInputs; i++) {
91
+ if (!authorizers[i]) {
92
+ throw new Error(`MISSING_INPUT_AUTHORIZER: No authorizer was provided for input index ${i}.`);
93
+ }
94
+ }
95
+ try {
96
+ console.log("DEBUG PLAN INPUTS:", JSON.stringify(plan.inputs || plan.selectedUtxos, null, 2));
97
+ const sourceInputs = plan.inputs || plan.selectedUtxos || [];
98
+ const utxos = sourceInputs.map((u) => {
99
+ if (!u.outpoint.transactionId || u.outpoint.index === void 0) {
100
+ throw new Error(`UTXO is missing transactionId or index. Re-run tx plan.`);
101
+ }
102
+ const spk = u.scriptPublicKey;
103
+ if (!spk) {
104
+ throw new Error(
105
+ "UTXO is missing scriptPublicKey. Real signing flows must never fabricate cryptographic state."
106
+ );
107
+ }
108
+ return {
109
+ address: plan.from.address,
110
+ outpoint: {
111
+ transactionId: u.outpoint.transactionId,
112
+ index: u.outpoint.index
113
+ },
114
+ utxoEntry: {
115
+ amount: BigInt(u.amountSompi),
116
+ scriptPublicKey: new sdk.ScriptPublicKey(parseInt(spk.substring(0, 4), 16) || 0, spk.substring(4)),
117
+ blockDaaScore: BigInt(u.blockDaaScore || "0"),
118
+ isCoinbase: !!u.isCoinbase
119
+ }
120
+ };
121
+ });
122
+ const priorityFee = BigInt(plan.estimatedFeeSompi);
123
+ 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));
144
+ });
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
+ );
153
+ const genesisGroups = /* @__PURE__ */ new Map();
154
+ allOutputs.forEach((o, idx) => {
155
+ if (o.covenant && !o.covenant.covenantId) {
156
+ const authIn = o.covenant.authorizingInput;
157
+ if (!genesisGroups.has(authIn)) genesisGroups.set(authIn, []);
158
+ genesisGroups.get(authIn).push(idx);
159
+ }
160
+ });
161
+ if (genesisGroups.size > 0) {
162
+ const groupsArray = Array.from(genesisGroups.entries()).map(([authIn, outIndices]) => {
163
+ return new sdk.GenesisCovenantGroup(authIn, outIndices);
164
+ });
165
+ unsignedTx.populateGenesisCovenants(groupsArray);
166
+ }
167
+ unsignedTx.version = 1;
168
+ if (plan.storageMass !== void 0) {
169
+ unsignedTx.storageMass = BigInt(plan.storageMass);
170
+ }
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
+ unsignedTx = sdk.createTransaction(
188
+ utxos,
189
+ wasmOutputs,
190
+ priorityFee
191
+ );
192
+ }
193
+ const inputs = unsignedTx.inputs;
194
+ for (let i = 0; i < inputs.length; i++) {
195
+ if (plan.computeBudget !== void 0) {
196
+ const val = Number(plan.computeBudget);
197
+ inputs[i].computeBudget = val;
198
+ }
199
+ if (unsignedTx.version === 1) {
200
+ inputs[i].sigOpCount = 0;
201
+ }
202
+ }
203
+ unsignedTx.inputs = inputs;
204
+ console.log("DEBUG createFreshTx RETURNING:", unsignedTx?.constructor?.name);
205
+ return unsignedTx;
206
+ };
207
+ const inputOverrides = {};
208
+ if (!authorizers || Object.keys(authorizers).length === 0) {
209
+ throw new Error("MISSING_INPUT_AUTHORIZER: No authorizers were provided for the transaction.");
210
+ }
211
+ const dummyTx = createFreshTx();
212
+ const numInputsWasm = dummyTx.inputs.length;
213
+ for (let i = 0; i < numInputsWasm; i++) {
214
+ const authorizer = authorizers[i];
215
+ if (!authorizer) {
216
+ throw new Error(`MISSING_INPUT_AUTHORIZER: No authorizer was provided for input index ${i}.`);
217
+ }
218
+ const txForAuth = createFreshTx();
219
+ const authorization = await authorizer.authorize({
220
+ inputIndex: i,
221
+ plan,
222
+ wasmTransaction: txForAuth,
223
+ wasm: sdk
224
+ });
225
+ let sigScript;
226
+ if (authorization.kind === "signature-script") {
227
+ sigScript = authorization.signatureScript;
228
+ } else if (authorization.kind === "wasm-signer") {
229
+ sigScript = await authorization.signer.signInput({
230
+ inputIndex: i,
231
+ plan,
232
+ wasmTransaction: txForAuth,
233
+ wasm: sdk
234
+ });
235
+ }
236
+ if (!sigScript || sigScript.trim() === "") {
237
+ throw new Error(`INVALID_SIGNATURE_SCRIPT: Authorizer for input ${i} failed to return a signatureScript.`);
238
+ }
239
+ if (!/^[0-9a-fA-F]+$/.test(sigScript)) {
240
+ throw new Error(`INVALID_SIGNATURE_SCRIPT: Authorizer for input ${i} returned a non-hex signatureScript.`);
241
+ }
242
+ inputOverrides[i] = { signatureScript: sigScript };
243
+ }
244
+ const finalTx = createFreshTx();
245
+ const signedTx = finalTx;
246
+ const wasmTxStr = typeof signedTx.serializeToJSON === "function" ? signedTx.serializeToJSON() : signedTx.toString();
247
+ const rpcTx = parseWasmTxToRpc(wasmTxStr, signedTx, inputOverrides, plan);
248
+ const rawTx = JSON.stringify(rpcTx);
249
+ return {
250
+ signatureKind: "kaspa-private-key",
251
+ signerAddress: input.accountName || plan.from.address || "authorized",
252
+ signedTransaction: {
253
+ format: "hex",
254
+ payload: rawTx
255
+ },
256
+ txId: signedTx.id,
257
+ signature: {
258
+ // We use the txid as the signature identifier in the artifact
259
+ value: signedTx.id || calculateContentHash(plan)
260
+ }
261
+ };
262
+ } catch (error) {
263
+ console.error("DEBUG SIGNING ERROR:", error);
264
+ throw new Error(
265
+ `Kaspa WASM signing failed: ${error instanceof Error ? error.stack || error.message : JSON.stringify(error, Object.getOwnPropertyNames(error))}`
266
+ );
267
+ }
268
+ }
269
+ };
270
+ function assertSigningNetworkAllowed(input) {
271
+ const isMainnet = input.network === "mainnet";
272
+ if (isMainnet && !input.allowMainnet) {
273
+ throw new Error(
274
+ "Mainnet signing is disabled by default. Use --allow-mainnet-signing only if you understand the risks."
275
+ );
276
+ }
277
+ }
278
+
279
+ // src/dev-accounts.ts
280
+ var DEV_ACCOUNTS_PASSWORD = "hardkas-local-dev";
281
+ var SIMNET_DETERMINISTIC_SEED = "hardkas-deterministic-simnet-seed-v1";
282
+ async function ensureDevAccounts(workspaceDir) {
283
+ const devAccountsDir = path.join(workspaceDir, ".hardkas", "dev-accounts");
284
+ if (!fs.existsSync(devAccountsDir)) {
285
+ await fs.promises.mkdir(devAccountsDir, { recursive: true });
286
+ }
287
+ await getOrCreateDevAccount(workspaceDir, 0, "alice");
288
+ await getOrCreateDevAccount(workspaceDir, 1, "bob");
289
+ }
290
+ async function getOrCreateDevAccount(workspaceDir, index, alias) {
291
+ const devAccountsDir = path.join(workspaceDir, ".hardkas", "dev-accounts");
292
+ const filePath = path.join(devAccountsDir, `${alias}.json`);
293
+ if (fs.existsSync(filePath)) {
294
+ const keystore2 = await KeystoreManager.loadEncryptedKeystore(filePath);
295
+ const unlock = await KeystoreManager.decryptEncryptedKeystore(
296
+ keystore2,
297
+ DEV_ACCOUNTS_PASSWORD
298
+ );
299
+ if (!unlock.success || !unlock.payload) {
300
+ throw new Error(
301
+ `Failed to decrypt dev account ${alias}. Expected password: ${DEV_ACCOUNTS_PASSWORD}`
302
+ );
303
+ }
304
+ return {
305
+ address: unlock.payload.address,
306
+ privateKey: unlock.payload.privateKey,
307
+ publicKey: unlock.payload.publicKey
308
+ };
309
+ }
310
+ const seedString = `${SIMNET_DETERMINISTIC_SEED}-${index}`;
311
+ const privateKeyHex = crypto.createHash("sha256").update(seedString).digest("hex");
312
+ const network = "simnet";
313
+ const isSimnet = ["simnet", "kaspasim", "local"].includes(network);
314
+ let address = "";
315
+ let privateKey = "";
316
+ let publicKey = "";
317
+ try {
318
+ if (isSimnet) {
319
+ let kaspaWasm;
320
+ try {
321
+ kaspaWasm = await import(
322
+ /* @vite-ignore */
323
+ "kaspa-wasm"
324
+ );
325
+ } catch (e) {
326
+ console.warn(`
327
+ [Warning] kaspa-wasm is not installed. Required for simnet.`);
328
+ return { address: "", privateKey: "", publicKey: "" };
329
+ }
330
+ const privKey = new kaspaWasm.PrivateKey(privateKeyHex);
331
+ const kp = privKey.toKeypair();
332
+ address = kp.toAddress(network).toString();
333
+ publicKey = kp.publicKey;
334
+ privateKey = privateKeyHex;
335
+ } else {
336
+ let sdkModule;
337
+ try {
338
+ sdkModule = await import(
339
+ /* @vite-ignore */
340
+ "@kaspa/core-lib"
341
+ );
342
+ } catch (e) {
343
+ console.warn(`
344
+ [Warning] @kaspa/core-lib is not installed.`);
345
+ return { address: "", privateKey: "", publicKey: "" };
346
+ }
347
+ const sdk = sdkModule.default || sdkModule;
348
+ if (typeof sdk.initRuntime === "function") {
349
+ await sdk.initRuntime();
350
+ }
351
+ const privKey = new sdk.PrivateKey(privateKeyHex);
352
+ const pubKey = privKey.toPublicKey();
353
+ try {
354
+ address = pubKey.toAddress(network).toString();
355
+ } catch (e) {
356
+ const msg = e instanceof Error ? e instanceof Error ? e instanceof Error ? e.message : String(e) : String(e) : String(e);
357
+ if (msg.includes("Second argument must be") || msg.includes("Unsupported")) {
358
+ const err = new Error("DEV_ACCOUNT_BACKEND_UNSUPPORTED_NETWORK");
359
+ err.code = "DEV_ACCOUNT_BACKEND_UNSUPPORTED_NETWORK";
360
+ throw err;
361
+ }
362
+ throw e;
363
+ }
364
+ publicKey = pubKey.toString();
365
+ privateKey = privKey.toString();
366
+ }
367
+ } catch (e) {
368
+ const msg = e instanceof Error ? e instanceof Error ? e instanceof Error ? e.message : String(e) : String(e) : String(e);
369
+ if (msg === "DEV_ACCOUNT_BACKEND_UNSUPPORTED_NETWORK") {
370
+ throw e;
371
+ }
372
+ console.warn(`
373
+ [Warning] Could not generate dev account '${alias}'.
374
+ ${msg}`);
375
+ return { address: "", privateKey: "", publicKey: "" };
376
+ }
377
+ const accountData = {
378
+ address,
379
+ privateKey,
380
+ publicKey
381
+ };
382
+ if (!fs.existsSync(devAccountsDir)) {
383
+ await fs.promises.mkdir(devAccountsDir, { recursive: true });
384
+ }
385
+ const payload = {
386
+ address: accountData.address,
387
+ privateKey: accountData.privateKey,
388
+ network: "simnet"
389
+ };
390
+ if (accountData.publicKey) {
391
+ payload.publicKey = accountData.publicKey;
392
+ }
393
+ const keystore = await KeystoreManager.createEncryptedKeystore(
394
+ payload,
395
+ DEV_ACCOUNTS_PASSWORD,
396
+ {
397
+ label: alias,
398
+ network: "simnet"
399
+ }
400
+ );
401
+ await KeystoreManager.saveEncryptedKeystore(filePath, keystore);
402
+ return accountData;
403
+ }
404
+ function listDevAccountsSync(workspaceDir) {
405
+ const devAccountsDir = path.join(workspaceDir, ".hardkas", "dev-accounts");
406
+ if (!fs.existsSync(devAccountsDir)) {
407
+ return [];
408
+ }
409
+ const accounts = [];
410
+ const files = fs.readdirSync(devAccountsDir);
411
+ for (const file of files) {
412
+ if (file.endsWith(".json")) {
413
+ const name = path.basename(file, ".json");
414
+ try {
415
+ const data = fs.readFileSync(path.join(devAccountsDir, file), "utf-8");
416
+ const keystore = JSON.parse(data);
417
+ if (keystore.type === "hardkas.encryptedKeystore.v2") {
418
+ accounts.push({
419
+ name,
420
+ address: keystore.metadata?.address || ""
421
+ });
422
+ }
423
+ } catch (e) {
424
+ }
425
+ }
426
+ }
427
+ accounts.sort((a, b) => deterministicCompare(a.name, b.name));
428
+ return accounts;
429
+ }
430
+ async function createDevSigner(workspaceDir, accountNameOrAddress) {
431
+ const account = resolveHardkasAccount({
432
+ nameOrAddress: accountNameOrAddress,
433
+ config: { cwd: workspaceDir }
434
+ });
435
+ if (account.kind !== "kaspa-private-key") {
436
+ throw new Error(`Account '${accountNameOrAddress}' is not a private key account, cannot create local dev signer.`);
437
+ }
438
+ return new KaspaWasmPrivateKeySigner({
439
+ account,
440
+ allowMainnet: false
441
+ });
442
+ }
443
+
444
+ export {
445
+ DEV_ACCOUNTS_PASSWORD,
446
+ ensureDevAccounts,
447
+ getOrCreateDevAccount,
448
+ listDevAccountsSync,
449
+ createDevSigner,
450
+ KaspaWasmPrivateKeySigner,
451
+ assertSigningNetworkAllowed
452
+ };
@@ -0,0 +1,103 @@
1
+ // src/internal/wasm-rpc-serialization.ts
2
+ function parseWasmTxToRpc(wasmTxStr, signedTx, inputOverrides, plan) {
3
+ let parsed;
4
+ try {
5
+ parsed = JSON.parse(wasmTxStr);
6
+ } catch (e) {
7
+ throw new Error("Failed to parse WASM transaction JSON: " + String(e));
8
+ }
9
+ while (typeof parsed === "string") {
10
+ parsed = JSON.parse(parsed);
11
+ }
12
+ const txInner = parsed.outputs ? parsed : parsed.tx ? parsed.tx.inner : parsed.inner;
13
+ if (!txInner) throw new Error("Could not find inner tx data");
14
+ const version = txInner.version || 0;
15
+ const numInputs = txInner.inputs ? txInner.inputs.length : 0;
16
+ if (inputOverrides) {
17
+ for (const idxStr of Object.keys(inputOverrides)) {
18
+ const idx = parseInt(idxStr, 10);
19
+ if (isNaN(idx) || idx < 0 || idx >= numInputs) {
20
+ throw new Error(`INVALID_UNLOCKER_INPUT_INDEX: Unlocker provided for non-existent input index ${idxStr}`);
21
+ }
22
+ }
23
+ }
24
+ function toHex(arr) {
25
+ if (!arr) return "";
26
+ return Buffer.from(arr).toString("hex");
27
+ }
28
+ return {
29
+ version,
30
+ inputs: (txInner.inputs || []).map((i, idx) => {
31
+ const isFlattened = !!txInner.outputs || !!i.previousOutpoint || !!i.transactionId;
32
+ const prevOut = isFlattened ? i.previousOutpoint || i : i.inner.previousOutpoint.inner;
33
+ const originalSigScript = isFlattened ? i.signatureScript || "" : toHex(i.inner.signatureScript);
34
+ const originalSigOpCount = isFlattened ? i.sigOpCount : i.inner.sigOpCount;
35
+ const computeBudget = isFlattened ? i.computeBudget : i.inner.computeBudget;
36
+ const override = inputOverrides ? inputOverrides[idx] : void 0;
37
+ const finalSigScript = override ? override.signatureScript : originalSigScript;
38
+ if (!finalSigScript || finalSigScript.length === 0 || !/^[0-9a-fA-F]+$/.test(finalSigScript)) {
39
+ throw new Error(`INVALID_SIGNATURE_SCRIPT: Missing or invalid hex signature script at input ${idx}`);
40
+ }
41
+ const sigOpCount = version === 1 ? 0 : originalSigOpCount !== void 0 ? originalSigOpCount : 1;
42
+ if (version === 1 && sigOpCount !== 0) {
43
+ throw new Error("INVALID_V1_SIG_OP_COUNT: V1 transactions must have sigOpCount = 0.");
44
+ }
45
+ const overrideBudget = plan?.computeBudget;
46
+ const finalComputeBudget = overrideBudget !== void 0 ? Number(overrideBudget) : computeBudget !== void 0 && computeBudget !== 0 ? computeBudget : 0;
47
+ return {
48
+ previousOutpoint: {
49
+ transactionId: prevOut.transactionId || prevOut.transactionId,
50
+ index: prevOut.index || prevOut.index
51
+ },
52
+ signatureScript: finalSigScript,
53
+ sequence: isFlattened ? i.sequence || 0 : i.inner.sequence || 0,
54
+ sigOpCount,
55
+ computeBudget: finalComputeBudget
56
+ };
57
+ }),
58
+ outputs: (txInner.outputs || []).map((o, idx) => {
59
+ const isFlattened = !!txInner.outputs || !!o.scriptPublicKey || !!o.value || !!o.amount;
60
+ const innerOut = isFlattened ? o : o.inner;
61
+ const scriptObj = innerOut.scriptPublicKey;
62
+ const ret = {
63
+ amount: (innerOut.value || innerOut.amount || 0).toString(),
64
+ scriptPublicKey: {
65
+ version: typeof scriptObj === "string" ? parseInt(scriptObj.substring(0, 4), 16) || 0 : scriptObj.version || 0,
66
+ scriptPublicKey: typeof scriptObj === "string" ? scriptObj.substring(4) : scriptObj.scriptPublicKey || scriptObj.script || ""
67
+ }
68
+ };
69
+ if (innerOut.covenant) {
70
+ ret.covenant = {
71
+ authorizingInput: innerOut.covenant.authorizingInput !== void 0 ? innerOut.covenant.authorizingInput : 0,
72
+ covenantId: typeof innerOut.covenant.covenantId === "string" ? innerOut.covenant.covenantId : ""
73
+ };
74
+ } else if (signedTx && typeof signedTx.outputs === "function") {
75
+ const outputs = signedTx.outputs();
76
+ if (outputs && outputs[idx] && outputs[idx].covenant) {
77
+ const cov = outputs[idx].covenant;
78
+ ret.covenant = {
79
+ authorizingInput: cov.authorizingInput !== void 0 ? cov.authorizingInput : 0,
80
+ covenantId: typeof cov.covenantId === "string" ? cov.covenantId : cov.covenantId.toString()
81
+ };
82
+ }
83
+ } else if (signedTx && signedTx.outputs && signedTx.outputs[idx] && signedTx.outputs[idx].covenant) {
84
+ const cov = signedTx.outputs[idx].covenant;
85
+ ret.covenant = {
86
+ authorizingInput: cov.authorizingInput !== void 0 ? cov.authorizingInput : 0,
87
+ covenantId: typeof cov.covenantId === "string" ? cov.covenantId : cov.covenantId.toString()
88
+ };
89
+ }
90
+ return ret;
91
+ }),
92
+ lockTime: txInner.lockTime || 0,
93
+ subnetworkId: txInner.subnetworkId || "0000000000000000000000000000000000000000",
94
+ gas: txInner.gas || 0,
95
+ mass: txInner.mass || 0,
96
+ storageMass: txInner.storageMass || 0,
97
+ payload: txInner.payload && txInner.payload.length > 0 ? typeof txInner.payload === "string" ? txInner.payload : toHex(txInner.payload) : ""
98
+ };
99
+ }
100
+
101
+ export {
102
+ parseWasmTxToRpc
103
+ };