@cogcoin/client 1.1.6 → 1.1.8
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/README.md +2 -2
- package/dist/bitcoind/indexer-daemon.js +29 -79
- package/dist/bitcoind/managed-runtime/bitcoind-runtime.d.ts +20 -0
- package/dist/bitcoind/managed-runtime/bitcoind-runtime.js +74 -0
- package/dist/bitcoind/managed-runtime/bitcoind-status.d.ts +11 -0
- package/dist/bitcoind/managed-runtime/bitcoind-status.js +44 -0
- package/dist/bitcoind/managed-runtime/indexer-runtime.d.ts +15 -0
- package/dist/bitcoind/managed-runtime/indexer-runtime.js +82 -0
- package/dist/bitcoind/managed-runtime/types.d.ts +40 -0
- package/dist/bitcoind/node.d.ts +2 -2
- package/dist/bitcoind/node.js +2 -2
- package/dist/bitcoind/rpc.d.ts +2 -1
- package/dist/bitcoind/rpc.js +53 -3
- package/dist/bitcoind/service.js +47 -127
- package/dist/cli/command-registry.d.ts +1 -1
- package/dist/cli/command-registry.js +2 -64
- package/dist/cli/commands/client-admin.js +3 -18
- package/dist/cli/commands/mining-runtime.js +4 -60
- package/dist/cli/commands/wallet-admin.js +6 -6
- package/dist/cli/context.js +1 -3
- package/dist/cli/mining-json.d.ts +1 -22
- package/dist/cli/mining-json.js +0 -23
- package/dist/cli/output.js +16 -2
- package/dist/cli/parse.js +0 -2
- package/dist/cli/preview-json.d.ts +1 -22
- package/dist/cli/preview-json.js +0 -19
- package/dist/cli/types.d.ts +1 -3
- package/dist/cli/wallet-format.js +1 -1
- package/dist/cli/workflow-hints.d.ts +1 -2
- package/dist/cli/workflow-hints.js +5 -8
- package/dist/wallet/lifecycle/context.js +0 -1
- package/dist/wallet/lifecycle/repair-mining.d.ts +1 -5
- package/dist/wallet/lifecycle/repair-mining.js +5 -39
- package/dist/wallet/lifecycle/repair.js +0 -3
- package/dist/wallet/lifecycle/setup.js +10 -8
- package/dist/wallet/lifecycle/types.d.ts +1 -4
- package/dist/wallet/managed-core-wallet.d.ts +2 -0
- package/dist/wallet/managed-core-wallet.js +27 -1
- package/dist/wallet/mining/candidate.d.ts +1 -0
- package/dist/wallet/mining/candidate.js +38 -6
- package/dist/wallet/mining/competitiveness.d.ts +1 -0
- package/dist/wallet/mining/competitiveness.js +6 -0
- package/dist/wallet/mining/cycle.d.ts +2 -0
- package/dist/wallet/mining/cycle.js +14 -4
- package/dist/wallet/mining/engine-state.js +10 -0
- package/dist/wallet/mining/engine-types.d.ts +1 -0
- package/dist/wallet/mining/index.d.ts +1 -1
- package/dist/wallet/mining/index.js +1 -1
- package/dist/wallet/mining/publish.d.ts +3 -0
- package/dist/wallet/mining/publish.js +78 -6
- package/dist/wallet/mining/runner.d.ts +0 -32
- package/dist/wallet/mining/runner.js +59 -104
- package/dist/wallet/mining/stop.d.ts +7 -0
- package/dist/wallet/mining/stop.js +23 -0
- package/dist/wallet/mining/supervisor.d.ts +2 -36
- package/dist/wallet/mining/supervisor.js +139 -246
- package/dist/wallet/mining/visualizer-sync.js +79 -15
- package/dist/wallet/read/context.d.ts +1 -5
- package/dist/wallet/read/context.js +21 -205
- package/dist/wallet/read/managed-services.d.ts +33 -0
- package/dist/wallet/read/managed-services.js +222 -0
- package/dist/wallet/reset/artifacts.d.ts +16 -0
- package/dist/wallet/reset/artifacts.js +141 -0
- package/dist/wallet/reset/execution.d.ts +38 -0
- package/dist/wallet/reset/execution.js +458 -0
- package/dist/wallet/reset/preflight.d.ts +7 -0
- package/dist/wallet/reset/preflight.js +116 -0
- package/dist/wallet/reset/preview.d.ts +2 -0
- package/dist/wallet/reset/preview.js +50 -0
- package/dist/wallet/reset/process-cleanup.d.ts +12 -0
- package/dist/wallet/reset/process-cleanup.js +179 -0
- package/dist/wallet/reset/types.d.ts +189 -0
- package/dist/wallet/reset/types.js +1 -0
- package/dist/wallet/reset.d.ts +4 -119
- package/dist/wallet/reset.js +4 -882
- package/dist/wallet/state/client-password/bootstrap.d.ts +2 -0
- package/dist/wallet/state/client-password/bootstrap.js +3 -0
- package/dist/wallet/state/client-password/context.d.ts +10 -0
- package/dist/wallet/state/client-password/context.js +46 -0
- package/dist/wallet/state/client-password/crypto.d.ts +34 -0
- package/dist/wallet/state/client-password/crypto.js +117 -0
- package/dist/wallet/state/client-password/files.d.ts +10 -0
- package/dist/wallet/state/client-password/files.js +109 -0
- package/dist/wallet/state/client-password/legacy-cleanup.d.ts +11 -0
- package/dist/wallet/state/client-password/legacy-cleanup.js +338 -0
- package/dist/wallet/state/client-password/messages.d.ts +3 -0
- package/dist/wallet/state/client-password/messages.js +9 -0
- package/dist/wallet/state/client-password/migration.d.ts +4 -0
- package/dist/wallet/state/client-password/migration.js +32 -0
- package/dist/wallet/state/client-password/prompts.d.ts +12 -0
- package/dist/wallet/state/client-password/prompts.js +79 -0
- package/dist/wallet/state/client-password/protected-secrets.d.ts +13 -0
- package/dist/wallet/state/client-password/protected-secrets.js +90 -0
- package/dist/wallet/state/client-password/readiness.d.ts +4 -0
- package/dist/wallet/state/client-password/readiness.js +48 -0
- package/dist/wallet/state/client-password/references.d.ts +1 -0
- package/dist/wallet/state/client-password/references.js +56 -0
- package/dist/wallet/state/client-password/rotation.d.ts +6 -0
- package/dist/wallet/state/client-password/rotation.js +98 -0
- package/dist/wallet/state/client-password/session-policy.d.ts +6 -0
- package/dist/wallet/state/client-password/session-policy.js +28 -0
- package/dist/wallet/state/client-password/session.d.ts +19 -0
- package/dist/wallet/state/client-password/session.js +170 -0
- package/dist/wallet/state/client-password/setup.d.ts +8 -0
- package/dist/wallet/state/client-password/setup.js +49 -0
- package/dist/wallet/state/client-password/types.d.ts +82 -0
- package/dist/wallet/state/client-password/types.js +5 -0
- package/dist/wallet/state/client-password.d.ts +7 -38
- package/dist/wallet/state/client-password.js +52 -937
- package/dist/wallet/tx/anchor.js +123 -216
- package/dist/wallet/tx/cog.js +294 -489
- package/dist/wallet/tx/common.d.ts +2 -0
- package/dist/wallet/tx/common.js +2 -0
- package/dist/wallet/tx/domain-admin.js +111 -220
- package/dist/wallet/tx/domain-market.js +401 -681
- package/dist/wallet/tx/executor.d.ts +176 -0
- package/dist/wallet/tx/executor.js +302 -0
- package/dist/wallet/tx/field.js +109 -215
- package/dist/wallet/tx/register.js +158 -269
- package/dist/wallet/tx/reputation.js +120 -227
- package/package.json +1 -1
- package/dist/wallet/mining/worker-main.d.ts +0 -1
- package/dist/wallet/mining/worker-main.js +0 -17
- package/dist/wallet/state/client-password-agent.d.ts +0 -1
- package/dist/wallet/state/client-password-agent.js +0 -211
|
@@ -3,15 +3,15 @@ import { encodeSentence } from "@cogcoin/scoring";
|
|
|
3
3
|
import { getBalance, lookupDomain, } from "@cogcoin/indexer/queries";
|
|
4
4
|
import { attachOrStartManagedBitcoindService } from "../../bitcoind/service.js";
|
|
5
5
|
import { createRpcClient } from "../../bitcoind/node.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { createDefaultWalletSecretProvider, } from "../state/provider.js";
|
|
6
|
+
import {} from "../runtime.js";
|
|
7
|
+
import {} from "../state/provider.js";
|
|
9
8
|
import { serializeRepCommit, serializeRepRevoke, validateDomainName, } from "../cogop/index.js";
|
|
10
9
|
import { openWalletReadContext } from "../read/index.js";
|
|
11
|
-
import { assertFixedInputPrefixMatches, assertFundingInputsAfterFixedPrefix, assertWalletMutationContextReady, buildWalletMutationTransactionWithReserveFallback,
|
|
10
|
+
import { assertFixedInputPrefixMatches, assertFundingInputsAfterFixedPrefix, assertWalletMutationContextReady, buildWalletMutationTransactionWithReserveFallback, createFundingMutationSender, createWalletMutationFeeMetadata, formatCogAmount, getDecodedInputScriptPubKeyHex, isLocalWalletScript, mergeFixedWalletInputs, outpointKey, unlockTemporaryBuilderLocks, updateMutationRecord, } from "./common.js";
|
|
12
11
|
import { confirmTypedAcknowledgement as confirmSharedTypedAcknowledgement, confirmYesNo as confirmSharedYesNo, } from "./confirm.js";
|
|
12
|
+
import { executeWalletMutationOperation, persistWalletMutationState, publishWalletMutation, resolveExistingWalletMutation, } from "./executor.js";
|
|
13
13
|
import { getCanonicalIdentitySelector } from "./identity-selector.js";
|
|
14
|
-
import {
|
|
14
|
+
import { upsertPendingMutation } from "./journal.js";
|
|
15
15
|
function normalizeDomainName(domainName, errorCode) {
|
|
16
16
|
const normalized = domainName.trim().toLowerCase();
|
|
17
17
|
if (normalized.length === 0) {
|
|
@@ -215,18 +215,7 @@ function createDraftMutation(options) {
|
|
|
215
215
|
};
|
|
216
216
|
}
|
|
217
217
|
async function saveUpdatedMutationState(options) {
|
|
218
|
-
|
|
219
|
-
...options.state,
|
|
220
|
-
stateRevision: options.state.stateRevision + 1,
|
|
221
|
-
lastWrittenAtUnixMs: options.nowUnixMs,
|
|
222
|
-
};
|
|
223
|
-
await saveWalletStatePreservingUnlock({
|
|
224
|
-
state: nextState,
|
|
225
|
-
provider: options.provider,
|
|
226
|
-
nowUnixMs: options.nowUnixMs,
|
|
227
|
-
paths: options.paths,
|
|
228
|
-
});
|
|
229
|
-
return nextState;
|
|
218
|
+
return persistWalletMutationState(options);
|
|
230
219
|
}
|
|
231
220
|
function mutationNeedsRepair(mutation, context) {
|
|
232
221
|
if (context.snapshot === null || mutation.recipientDomainName == null) {
|
|
@@ -381,75 +370,6 @@ async function encodeReviewText(reviewText, errorPrefix) {
|
|
|
381
370
|
throw new Error(error instanceof Error ? `${errorPrefix}_invalid_review_${error.message}` : `${errorPrefix}_invalid_review`);
|
|
382
371
|
});
|
|
383
372
|
}
|
|
384
|
-
async function sendBuiltTransaction(options) {
|
|
385
|
-
let nextState = options.state;
|
|
386
|
-
const broadcasting = updateMutationRecord(options.mutation, "broadcasting", options.nowUnixMs, {
|
|
387
|
-
attemptedTxid: options.built.txid,
|
|
388
|
-
attemptedWtxid: options.built.wtxid,
|
|
389
|
-
temporaryBuilderLockedOutpoints: options.built.temporaryBuilderLockedOutpoints,
|
|
390
|
-
});
|
|
391
|
-
nextState = upsertPendingMutation(nextState, broadcasting);
|
|
392
|
-
nextState = await saveUpdatedMutationState({
|
|
393
|
-
state: nextState,
|
|
394
|
-
provider: options.provider,
|
|
395
|
-
nowUnixMs: options.nowUnixMs,
|
|
396
|
-
paths: options.paths,
|
|
397
|
-
});
|
|
398
|
-
if (options.snapshotHeight !== null && options.snapshotHeight !== (await options.rpc.getBlockchainInfo()).blocks) {
|
|
399
|
-
await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.built.temporaryBuilderLockedOutpoints);
|
|
400
|
-
throw new Error(`${options.errorPrefix}_tip_mismatch`);
|
|
401
|
-
}
|
|
402
|
-
try {
|
|
403
|
-
await options.rpc.sendRawTransaction(options.built.rawHex);
|
|
404
|
-
}
|
|
405
|
-
catch (error) {
|
|
406
|
-
if (!isAlreadyAcceptedError(error)) {
|
|
407
|
-
if (isBroadcastUnknownError(error)) {
|
|
408
|
-
const unknown = updateMutationRecord(broadcasting, "broadcast-unknown", options.nowUnixMs, {
|
|
409
|
-
attemptedTxid: options.built.txid,
|
|
410
|
-
attemptedWtxid: options.built.wtxid,
|
|
411
|
-
temporaryBuilderLockedOutpoints: options.built.temporaryBuilderLockedOutpoints,
|
|
412
|
-
});
|
|
413
|
-
nextState = upsertPendingMutation(nextState, unknown);
|
|
414
|
-
nextState = await saveUpdatedMutationState({
|
|
415
|
-
state: nextState,
|
|
416
|
-
provider: options.provider,
|
|
417
|
-
nowUnixMs: options.nowUnixMs,
|
|
418
|
-
paths: options.paths,
|
|
419
|
-
});
|
|
420
|
-
throw new Error(`${options.errorPrefix}_broadcast_unknown`);
|
|
421
|
-
}
|
|
422
|
-
await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.built.temporaryBuilderLockedOutpoints);
|
|
423
|
-
const canceled = updateMutationRecord(broadcasting, "canceled", options.nowUnixMs, {
|
|
424
|
-
attemptedTxid: options.built.txid,
|
|
425
|
-
attemptedWtxid: options.built.wtxid,
|
|
426
|
-
temporaryBuilderLockedOutpoints: [],
|
|
427
|
-
});
|
|
428
|
-
nextState = upsertPendingMutation(nextState, canceled);
|
|
429
|
-
nextState = await saveUpdatedMutationState({
|
|
430
|
-
state: nextState,
|
|
431
|
-
provider: options.provider,
|
|
432
|
-
nowUnixMs: options.nowUnixMs,
|
|
433
|
-
paths: options.paths,
|
|
434
|
-
});
|
|
435
|
-
throw error;
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.built.temporaryBuilderLockedOutpoints);
|
|
439
|
-
const live = updateMutationRecord(broadcasting, "live", options.nowUnixMs, {
|
|
440
|
-
attemptedTxid: options.built.txid,
|
|
441
|
-
attemptedWtxid: options.built.wtxid,
|
|
442
|
-
temporaryBuilderLockedOutpoints: [],
|
|
443
|
-
});
|
|
444
|
-
nextState = upsertPendingMutation(nextState, live);
|
|
445
|
-
nextState = await saveUpdatedMutationState({
|
|
446
|
-
state: nextState,
|
|
447
|
-
provider: options.provider,
|
|
448
|
-
nowUnixMs: options.nowUnixMs,
|
|
449
|
-
paths: options.paths,
|
|
450
|
-
});
|
|
451
|
-
return { state: nextState, mutation: live };
|
|
452
|
-
}
|
|
453
373
|
async function submitReputationMutation(options) {
|
|
454
374
|
if (!options.prompter.isInteractive && options.assumeYes !== true) {
|
|
455
375
|
throw new Error(`${options.errorPrefix}_requires_tty`);
|
|
@@ -457,26 +377,11 @@ async function submitReputationMutation(options) {
|
|
|
457
377
|
if (options.amountCogtoshi <= 0n) {
|
|
458
378
|
throw new Error(`${options.errorPrefix}_invalid_amount`);
|
|
459
379
|
}
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
walletRootId: null,
|
|
466
|
-
});
|
|
467
|
-
try {
|
|
468
|
-
const miningPreemption = await pauseMiningForWalletMutation({
|
|
469
|
-
paths,
|
|
470
|
-
reason: options.errorPrefix,
|
|
471
|
-
});
|
|
472
|
-
const readContext = await (options.openReadContext ?? openWalletReadContext)({
|
|
473
|
-
dataDir: options.dataDir,
|
|
474
|
-
databasePath: options.databasePath,
|
|
475
|
-
secretProvider: provider,
|
|
476
|
-
walletControlLockHeld: true,
|
|
477
|
-
paths,
|
|
478
|
-
});
|
|
479
|
-
try {
|
|
380
|
+
const execution = await executeWalletMutationOperation({
|
|
381
|
+
...options,
|
|
382
|
+
controlLockPurpose: options.errorPrefix,
|
|
383
|
+
preemptionReason: options.errorPrefix,
|
|
384
|
+
async resolveOperation(readContext) {
|
|
480
385
|
const normalizedSourceDomainName = normalizeDomainName(options.sourceDomainName, `${options.errorPrefix}_missing_source_domain`);
|
|
481
386
|
const normalizedTargetDomainName = normalizeDomainName(options.targetDomainName, `${options.errorPrefix}_missing_target_domain`);
|
|
482
387
|
const operation = resolveReputationOperation(readContext, normalizedSourceDomainName, normalizedTargetDomainName, options.errorPrefix);
|
|
@@ -493,159 +398,147 @@ async function submitReputationMutation(options) {
|
|
|
493
398
|
}
|
|
494
399
|
const review = await encodeReviewText(options.reviewText, options.errorPrefix);
|
|
495
400
|
const selfStake = operation.sourceDomain.domainId === operation.targetDomain.domainId;
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
amountCogtoshi: options.amountCogtoshi,
|
|
401
|
+
return {
|
|
402
|
+
...operation,
|
|
403
|
+
normalizedSourceDomainName,
|
|
404
|
+
normalizedTargetDomainName,
|
|
501
405
|
review,
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
406
|
+
resolved: createResolvedReputationSummary({
|
|
407
|
+
kind: options.kind === "rep-give" ? "give" : "revoke",
|
|
408
|
+
sender: operation.sender,
|
|
409
|
+
senderSelector: operation.senderSelector,
|
|
410
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
411
|
+
review,
|
|
412
|
+
selfStake,
|
|
413
|
+
}),
|
|
414
|
+
};
|
|
415
|
+
},
|
|
416
|
+
createIntentFingerprint(operation) {
|
|
417
|
+
return createIntentFingerprint([
|
|
505
418
|
options.kind,
|
|
506
419
|
operation.state.walletRootId,
|
|
507
420
|
operation.sourceDomain.name,
|
|
508
421
|
operation.targetDomain.name,
|
|
509
422
|
options.amountCogtoshi,
|
|
510
|
-
review.payloadHex ?? "",
|
|
423
|
+
operation.review.payloadHex ?? "",
|
|
511
424
|
]);
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
walletRootId: operation.state.walletRootId,
|
|
517
|
-
});
|
|
518
|
-
const rpc = (options.rpcFactory ?? createRpcClient)(node.rpc);
|
|
519
|
-
const walletName = operation.state.managedCoreWallet.walletName;
|
|
520
|
-
const feeSelection = await resolveWalletMutationFeeSelection({
|
|
521
|
-
rpc,
|
|
522
|
-
feeRateSatVb: options.feeRateSatVb ?? null,
|
|
523
|
-
});
|
|
524
|
-
const existingMutation = findPendingMutationByIntent(operation.state, intentFingerprintHex);
|
|
525
|
-
let workingState = operation.state;
|
|
526
|
-
let replacementFixedInputs = null;
|
|
527
|
-
if (existingMutation !== null) {
|
|
528
|
-
const reconciled = await reconcilePendingReputationMutation({
|
|
425
|
+
},
|
|
426
|
+
async resolveExistingMutation({ operation, existingMutation, execution }) {
|
|
427
|
+
if (existingMutation === null) {
|
|
428
|
+
return {
|
|
529
429
|
state: operation.state,
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
paths,
|
|
534
|
-
rpc,
|
|
535
|
-
walletName,
|
|
536
|
-
context: readContext,
|
|
537
|
-
});
|
|
538
|
-
workingState = reconciled.state;
|
|
539
|
-
if (reconciled.resolution === "confirmed" || reconciled.resolution === "live") {
|
|
540
|
-
const reuse = await resolvePendingMutationReuseDecision({
|
|
541
|
-
rpc,
|
|
542
|
-
walletName,
|
|
543
|
-
mutation: reconciled.mutation,
|
|
544
|
-
nextFeeSelection: feeSelection,
|
|
545
|
-
});
|
|
546
|
-
if (reuse.reuseExisting) {
|
|
547
|
-
return {
|
|
548
|
-
kind: options.kind === "rep-give" ? "give" : "revoke",
|
|
549
|
-
sourceDomainName: normalizedSourceDomainName,
|
|
550
|
-
targetDomainName: normalizedTargetDomainName,
|
|
551
|
-
amountCogtoshi: options.amountCogtoshi,
|
|
552
|
-
txid: reconciled.mutation.attemptedTxid ?? "unknown",
|
|
553
|
-
status: reconciled.resolution,
|
|
554
|
-
reusedExisting: true,
|
|
555
|
-
reviewIncluded: review.payloadHex !== null,
|
|
556
|
-
resolved,
|
|
557
|
-
fees: reuse.fees,
|
|
558
|
-
};
|
|
559
|
-
}
|
|
560
|
-
replacementFixedInputs = reuse.replacementFixedInputs;
|
|
561
|
-
}
|
|
562
|
-
if (reconciled.resolution === "repair-required") {
|
|
563
|
-
throw new Error(`${options.errorPrefix}_repair_required`);
|
|
564
|
-
}
|
|
430
|
+
replacementFixedInputs: null,
|
|
431
|
+
result: null,
|
|
432
|
+
};
|
|
565
433
|
}
|
|
434
|
+
return resolveExistingWalletMutation({
|
|
435
|
+
existingMutation,
|
|
436
|
+
execution,
|
|
437
|
+
repairRequiredErrorCode: `${options.errorPrefix}_repair_required`,
|
|
438
|
+
reconcileExistingMutation: (mutation) => reconcilePendingReputationMutation({
|
|
439
|
+
state: operation.state,
|
|
440
|
+
mutation,
|
|
441
|
+
provider: execution.provider,
|
|
442
|
+
nowUnixMs: execution.nowUnixMs,
|
|
443
|
+
paths: execution.paths,
|
|
444
|
+
rpc: execution.rpc,
|
|
445
|
+
walletName: execution.walletName,
|
|
446
|
+
context: execution.readContext,
|
|
447
|
+
}),
|
|
448
|
+
createReuseResult: ({ mutation, resolution, fees }) => ({
|
|
449
|
+
kind: options.kind === "rep-give" ? "give" : "revoke",
|
|
450
|
+
sourceDomainName: operation.normalizedSourceDomainName,
|
|
451
|
+
targetDomainName: operation.normalizedTargetDomainName,
|
|
452
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
453
|
+
txid: mutation.attemptedTxid ?? "unknown",
|
|
454
|
+
status: resolution,
|
|
455
|
+
reusedExisting: true,
|
|
456
|
+
reviewIncluded: operation.review.payloadHex !== null,
|
|
457
|
+
resolved: operation.resolved,
|
|
458
|
+
fees,
|
|
459
|
+
}),
|
|
460
|
+
});
|
|
461
|
+
},
|
|
462
|
+
async confirm({ operation }) {
|
|
566
463
|
await confirmReputationMutation(options.prompter, {
|
|
567
464
|
kind: options.kind === "rep-give" ? "give" : "revoke",
|
|
568
|
-
sourceDomainName: normalizedSourceDomainName,
|
|
569
|
-
targetDomainName: normalizedTargetDomainName,
|
|
465
|
+
sourceDomainName: operation.normalizedSourceDomainName,
|
|
466
|
+
targetDomainName: operation.normalizedTargetDomainName,
|
|
570
467
|
amountCogtoshi: options.amountCogtoshi,
|
|
571
|
-
reviewText: review.text,
|
|
572
|
-
resolved,
|
|
468
|
+
reviewText: operation.review.text,
|
|
469
|
+
resolved: operation.resolved,
|
|
573
470
|
assumeYes: options.assumeYes,
|
|
574
471
|
});
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
472
|
+
},
|
|
473
|
+
createDraftMutation({ operation, existingMutation, execution, intentFingerprintHex }) {
|
|
474
|
+
return {
|
|
475
|
+
mutation: createDraftMutation({
|
|
476
|
+
kind: options.kind,
|
|
477
|
+
sourceDomainName: operation.normalizedSourceDomainName,
|
|
478
|
+
targetDomainName: operation.normalizedTargetDomainName,
|
|
479
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
480
|
+
sender: operation.sender,
|
|
481
|
+
intentFingerprintHex,
|
|
482
|
+
nowUnixMs: execution.nowUnixMs,
|
|
483
|
+
reviewPayloadHex: operation.review.payloadHex,
|
|
484
|
+
feeSelection: execution.feeSelection,
|
|
485
|
+
existing: existingMutation,
|
|
486
|
+
}),
|
|
487
|
+
prepared: null,
|
|
488
|
+
};
|
|
489
|
+
},
|
|
490
|
+
async build({ operation, state, execution, replacementFixedInputs }) {
|
|
593
491
|
const opReturnData = options.kind === "rep-give"
|
|
594
|
-
? serializeRepCommit(operation.sourceDomain.domainId, operation.targetDomain.domainId, options.amountCogtoshi, review.payload).opReturnData
|
|
595
|
-
: serializeRepRevoke(operation.sourceDomain.domainId, operation.targetDomain.domainId, options.amountCogtoshi, review.payload).opReturnData;
|
|
492
|
+
? serializeRepCommit(operation.sourceDomain.domainId, operation.targetDomain.domainId, options.amountCogtoshi, operation.review.payload).opReturnData
|
|
493
|
+
: serializeRepRevoke(operation.sourceDomain.domainId, operation.targetDomain.domainId, options.amountCogtoshi, operation.review.payload).opReturnData;
|
|
596
494
|
const reputationPlan = buildPlanForReputationOperation({
|
|
597
|
-
state
|
|
598
|
-
allUtxos: await rpc.listUnspent(walletName, 1),
|
|
495
|
+
state,
|
|
496
|
+
allUtxos: await execution.rpc.listUnspent(execution.walletName, 1),
|
|
599
497
|
sender: operation.sender,
|
|
600
498
|
opReturnData,
|
|
601
499
|
errorPrefix: options.errorPrefix,
|
|
602
500
|
});
|
|
603
|
-
|
|
604
|
-
rpc,
|
|
605
|
-
walletName,
|
|
606
|
-
state
|
|
501
|
+
return buildTransaction({
|
|
502
|
+
rpc: execution.rpc,
|
|
503
|
+
walletName: execution.walletName,
|
|
504
|
+
state,
|
|
607
505
|
plan: {
|
|
608
506
|
...reputationPlan,
|
|
609
507
|
fixedInputs: mergeFixedWalletInputs(reputationPlan.fixedInputs, replacementFixedInputs),
|
|
610
508
|
},
|
|
611
|
-
feeRateSatVb: feeSelection.feeRateSatVb,
|
|
509
|
+
feeRateSatVb: execution.feeSelection.feeRateSatVb,
|
|
612
510
|
});
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
511
|
+
},
|
|
512
|
+
publish({ state, execution, built, mutation }) {
|
|
513
|
+
return publishWalletMutation({
|
|
514
|
+
rpc: execution.rpc,
|
|
515
|
+
walletName: execution.walletName,
|
|
516
|
+
snapshotHeight: execution.readContext.snapshot?.tip?.height ?? null,
|
|
617
517
|
built,
|
|
618
|
-
mutation
|
|
619
|
-
state
|
|
620
|
-
provider,
|
|
621
|
-
nowUnixMs,
|
|
622
|
-
paths,
|
|
518
|
+
mutation,
|
|
519
|
+
state,
|
|
520
|
+
provider: execution.provider,
|
|
521
|
+
nowUnixMs: execution.nowUnixMs,
|
|
522
|
+
paths: execution.paths,
|
|
623
523
|
errorPrefix: options.errorPrefix,
|
|
624
524
|
});
|
|
525
|
+
},
|
|
526
|
+
createResult({ operation, mutation, built, status, reusedExisting, fees }) {
|
|
625
527
|
return {
|
|
626
528
|
kind: options.kind === "rep-give" ? "give" : "revoke",
|
|
627
|
-
sourceDomainName: normalizedSourceDomainName,
|
|
628
|
-
targetDomainName: normalizedTargetDomainName,
|
|
529
|
+
sourceDomainName: operation.normalizedSourceDomainName,
|
|
530
|
+
targetDomainName: operation.normalizedTargetDomainName,
|
|
629
531
|
amountCogtoshi: options.amountCogtoshi,
|
|
630
|
-
txid:
|
|
631
|
-
status:
|
|
632
|
-
reusedExisting
|
|
633
|
-
reviewIncluded: review.payloadHex !== null,
|
|
634
|
-
resolved,
|
|
635
|
-
fees
|
|
636
|
-
selection: feeSelection,
|
|
637
|
-
built,
|
|
638
|
-
}),
|
|
532
|
+
txid: mutation.attemptedTxid ?? built?.txid ?? "unknown",
|
|
533
|
+
status: status,
|
|
534
|
+
reusedExisting,
|
|
535
|
+
reviewIncluded: operation.review.payloadHex !== null,
|
|
536
|
+
resolved: operation.resolved,
|
|
537
|
+
fees,
|
|
639
538
|
};
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
await miningPreemption.release();
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
finally {
|
|
647
|
-
await controlLock.release();
|
|
648
|
-
}
|
|
539
|
+
},
|
|
540
|
+
});
|
|
541
|
+
return execution.result;
|
|
649
542
|
}
|
|
650
543
|
export async function giveReputation(options) {
|
|
651
544
|
return submitReputationMutation({
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { runBackgroundMiningWorker } from "./runner.js";
|
|
2
|
-
function readFlag(name) {
|
|
3
|
-
const prefix = `--${name}=`;
|
|
4
|
-
const match = process.argv.find((entry) => entry.startsWith(prefix));
|
|
5
|
-
return match === undefined ? null : match.slice(prefix.length);
|
|
6
|
-
}
|
|
7
|
-
const dataDir = readFlag("data-dir");
|
|
8
|
-
const databasePath = readFlag("database-path");
|
|
9
|
-
const runId = readFlag("run-id");
|
|
10
|
-
if (dataDir === null || databasePath === null || runId === null) {
|
|
11
|
-
throw new Error("mining_worker_missing_args");
|
|
12
|
-
}
|
|
13
|
-
await runBackgroundMiningWorker({
|
|
14
|
-
dataDir,
|
|
15
|
-
databasePath,
|
|
16
|
-
runId,
|
|
17
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
2
|
-
import net from "node:net";
|
|
3
|
-
import { rm } from "node:fs/promises";
|
|
4
|
-
function shouldRemoveAgentEndpointPath(endpoint) {
|
|
5
|
-
return !endpoint.startsWith("\\\\.\\pipe\\");
|
|
6
|
-
}
|
|
7
|
-
function zeroizeBuffer(buffer) {
|
|
8
|
-
if (buffer != null) {
|
|
9
|
-
buffer.fill(0);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
function createAgentError(message) {
|
|
13
|
-
return JSON.stringify({
|
|
14
|
-
ok: false,
|
|
15
|
-
error: message,
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
async function readBootstrapConfig() {
|
|
19
|
-
const endpoint = process.argv[2] ?? "";
|
|
20
|
-
const unlockUntilUnixMs = Number(process.argv[3] ?? "");
|
|
21
|
-
if (endpoint.length === 0 || !Number.isFinite(unlockUntilUnixMs)) {
|
|
22
|
-
throw new Error("wallet_client_password_agent_bootstrap_invalid");
|
|
23
|
-
}
|
|
24
|
-
const raw = await new Promise((resolve, reject) => {
|
|
25
|
-
let received = "";
|
|
26
|
-
const onData = (chunk) => {
|
|
27
|
-
received += chunk.toString("utf8");
|
|
28
|
-
const newlineIndex = received.indexOf("\n");
|
|
29
|
-
if (newlineIndex !== -1) {
|
|
30
|
-
cleanup();
|
|
31
|
-
resolve(received.slice(0, newlineIndex));
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
const onEnd = () => {
|
|
35
|
-
cleanup();
|
|
36
|
-
reject(new Error("wallet_client_password_agent_bootstrap_missing"));
|
|
37
|
-
};
|
|
38
|
-
const onError = (error) => {
|
|
39
|
-
cleanup();
|
|
40
|
-
reject(error);
|
|
41
|
-
};
|
|
42
|
-
const cleanup = () => {
|
|
43
|
-
process.stdin.off("data", onData);
|
|
44
|
-
process.stdin.off("end", onEnd);
|
|
45
|
-
process.stdin.off("error", onError);
|
|
46
|
-
};
|
|
47
|
-
process.stdin.on("data", onData);
|
|
48
|
-
process.stdin.on("end", onEnd);
|
|
49
|
-
process.stdin.on("error", onError);
|
|
50
|
-
});
|
|
51
|
-
const parsed = JSON.parse(raw);
|
|
52
|
-
if (typeof parsed.derivedKeyBase64 !== "string") {
|
|
53
|
-
throw new Error("wallet_client_password_agent_bootstrap_invalid");
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
endpoint,
|
|
57
|
-
unlockUntilUnixMs,
|
|
58
|
-
derivedKey: Buffer.from(parsed.derivedKeyBase64, "base64"),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
async function main() {
|
|
62
|
-
const bootstrap = await readBootstrapConfig();
|
|
63
|
-
let key = bootstrap.derivedKey;
|
|
64
|
-
let unlockUntilUnixMs = bootstrap.unlockUntilUnixMs;
|
|
65
|
-
let expiryTimer = null;
|
|
66
|
-
const cleanupAndExit = async () => {
|
|
67
|
-
if (expiryTimer !== null) {
|
|
68
|
-
clearTimeout(expiryTimer);
|
|
69
|
-
expiryTimer = null;
|
|
70
|
-
}
|
|
71
|
-
zeroizeBuffer(key);
|
|
72
|
-
key = Buffer.alloc(0);
|
|
73
|
-
if (shouldRemoveAgentEndpointPath(bootstrap.endpoint)) {
|
|
74
|
-
await rm(bootstrap.endpoint, { force: true }).catch(() => undefined);
|
|
75
|
-
}
|
|
76
|
-
process.exit(0);
|
|
77
|
-
};
|
|
78
|
-
const refreshExpiry = () => {
|
|
79
|
-
if (expiryTimer !== null) {
|
|
80
|
-
clearTimeout(expiryTimer);
|
|
81
|
-
}
|
|
82
|
-
const remainingMs = Math.max(0, unlockUntilUnixMs - Date.now());
|
|
83
|
-
expiryTimer = setTimeout(() => {
|
|
84
|
-
void cleanupAndExit();
|
|
85
|
-
}, remainingMs);
|
|
86
|
-
expiryTimer.unref();
|
|
87
|
-
};
|
|
88
|
-
const encryptSecret = (secretBase64) => {
|
|
89
|
-
const nonce = randomBytes(12);
|
|
90
|
-
const cipher = createCipheriv("aes-256-gcm", key, nonce);
|
|
91
|
-
const ciphertext = Buffer.concat([
|
|
92
|
-
cipher.update(Buffer.from(secretBase64, "base64")),
|
|
93
|
-
cipher.final(),
|
|
94
|
-
]);
|
|
95
|
-
const tag = cipher.getAuthTag();
|
|
96
|
-
return {
|
|
97
|
-
nonce: nonce.toString("base64"),
|
|
98
|
-
tag: tag.toString("base64"),
|
|
99
|
-
ciphertext: ciphertext.toString("base64"),
|
|
100
|
-
};
|
|
101
|
-
};
|
|
102
|
-
const decryptSecret = (options) => {
|
|
103
|
-
const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(options.nonce, "base64"));
|
|
104
|
-
decipher.setAuthTag(Buffer.from(options.tag, "base64"));
|
|
105
|
-
return Buffer.concat([
|
|
106
|
-
decipher.update(Buffer.from(options.ciphertext, "base64")),
|
|
107
|
-
decipher.final(),
|
|
108
|
-
]).toString("base64");
|
|
109
|
-
};
|
|
110
|
-
const server = net.createServer((socket) => {
|
|
111
|
-
let received = "";
|
|
112
|
-
const send = (payload) => {
|
|
113
|
-
socket.end(`${JSON.stringify(payload)}\n`);
|
|
114
|
-
};
|
|
115
|
-
socket.on("data", (chunk) => {
|
|
116
|
-
received += chunk.toString("utf8");
|
|
117
|
-
const newlineIndex = received.indexOf("\n");
|
|
118
|
-
if (newlineIndex === -1) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
let parsed;
|
|
122
|
-
try {
|
|
123
|
-
parsed = JSON.parse(received.slice(0, newlineIndex));
|
|
124
|
-
}
|
|
125
|
-
catch {
|
|
126
|
-
send({ ok: false, error: "wallet_client_password_agent_protocol_error" });
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
try {
|
|
130
|
-
switch (parsed.command) {
|
|
131
|
-
case "status":
|
|
132
|
-
send({ ok: true, unlockUntilUnixMs });
|
|
133
|
-
return;
|
|
134
|
-
case "lock":
|
|
135
|
-
send({ ok: true, unlockUntilUnixMs: null });
|
|
136
|
-
setImmediate(() => {
|
|
137
|
-
void cleanupAndExit();
|
|
138
|
-
});
|
|
139
|
-
return;
|
|
140
|
-
case "refresh":
|
|
141
|
-
if (!Number.isFinite(parsed.unlockUntilUnixMs)) {
|
|
142
|
-
send({ ok: false, error: "wallet_client_password_agent_protocol_error" });
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
unlockUntilUnixMs = Number(parsed.unlockUntilUnixMs);
|
|
146
|
-
refreshExpiry();
|
|
147
|
-
send({ ok: true, unlockUntilUnixMs });
|
|
148
|
-
return;
|
|
149
|
-
case "encrypt":
|
|
150
|
-
if (typeof parsed.secretBase64 !== "string") {
|
|
151
|
-
send({ ok: false, error: "wallet_client_password_agent_protocol_error" });
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
send({
|
|
155
|
-
ok: true,
|
|
156
|
-
unlockUntilUnixMs,
|
|
157
|
-
envelope: encryptSecret(parsed.secretBase64),
|
|
158
|
-
});
|
|
159
|
-
return;
|
|
160
|
-
case "decrypt":
|
|
161
|
-
if (typeof parsed.envelope?.nonce !== "string"
|
|
162
|
-
|| typeof parsed.envelope?.tag !== "string"
|
|
163
|
-
|| typeof parsed.envelope?.ciphertext !== "string") {
|
|
164
|
-
send({ ok: false, error: "wallet_client_password_agent_protocol_error" });
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
send({
|
|
168
|
-
ok: true,
|
|
169
|
-
unlockUntilUnixMs,
|
|
170
|
-
secretBase64: decryptSecret({
|
|
171
|
-
nonce: parsed.envelope.nonce,
|
|
172
|
-
tag: parsed.envelope.tag,
|
|
173
|
-
ciphertext: parsed.envelope.ciphertext,
|
|
174
|
-
}),
|
|
175
|
-
});
|
|
176
|
-
return;
|
|
177
|
-
default:
|
|
178
|
-
send({ ok: false, error: "wallet_client_password_agent_protocol_error" });
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
catch (error) {
|
|
182
|
-
send({
|
|
183
|
-
ok: false,
|
|
184
|
-
error: error instanceof Error ? error.message : String(error),
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
process.on("SIGTERM", () => {
|
|
190
|
-
void cleanupAndExit();
|
|
191
|
-
});
|
|
192
|
-
process.on("SIGINT", () => {
|
|
193
|
-
void cleanupAndExit();
|
|
194
|
-
});
|
|
195
|
-
process.on("exit", () => {
|
|
196
|
-
zeroizeBuffer(key);
|
|
197
|
-
});
|
|
198
|
-
refreshExpiry();
|
|
199
|
-
await new Promise((resolve, reject) => {
|
|
200
|
-
server.once("error", reject);
|
|
201
|
-
server.listen(bootstrap.endpoint, () => {
|
|
202
|
-
server.off("error", reject);
|
|
203
|
-
resolve();
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
process.stdout.write("ready\n");
|
|
207
|
-
}
|
|
208
|
-
void main().catch((error) => {
|
|
209
|
-
process.stderr.write(`${createAgentError(error instanceof Error ? error.message : String(error))}\n`);
|
|
210
|
-
process.exit(1);
|
|
211
|
-
});
|