@cogcoin/client 1.1.8 → 1.1.9
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 +1 -1
- package/dist/cli/commands/mining-read.js +1 -1
- package/dist/cli/commands/wallet-mutation/anchor.d.ts +2 -0
- package/dist/cli/commands/wallet-mutation/anchor.js +33 -0
- package/dist/cli/commands/wallet-mutation/bitcoin-transfer.d.ts +2 -0
- package/dist/cli/commands/wallet-mutation/bitcoin-transfer.js +32 -0
- package/dist/cli/commands/wallet-mutation/cog.d.ts +2 -0
- package/dist/cli/commands/wallet-mutation/cog.js +131 -0
- package/dist/cli/commands/wallet-mutation/context.d.ts +3 -0
- package/dist/cli/commands/wallet-mutation/context.js +18 -0
- package/dist/cli/commands/wallet-mutation/domain-admin.d.ts +2 -0
- package/dist/cli/commands/wallet-mutation/domain-admin.js +173 -0
- package/dist/cli/commands/wallet-mutation/domain-market.d.ts +2 -0
- package/dist/cli/commands/wallet-mutation/domain-market.js +107 -0
- package/dist/cli/commands/wallet-mutation/field.d.ts +2 -0
- package/dist/cli/commands/wallet-mutation/field.js +125 -0
- package/dist/cli/commands/wallet-mutation/register.d.ts +2 -0
- package/dist/cli/commands/wallet-mutation/register.js +38 -0
- package/dist/cli/commands/wallet-mutation/registry.d.ts +3 -0
- package/dist/cli/commands/wallet-mutation/registry.js +39 -0
- package/dist/cli/commands/wallet-mutation/reputation.d.ts +2 -0
- package/dist/cli/commands/wallet-mutation/reputation.js +57 -0
- package/dist/cli/commands/wallet-mutation/types.d.ts +32 -0
- package/dist/cli/commands/wallet-mutation/types.js +1 -0
- package/dist/cli/commands/wallet-mutation.js +13 -765
- package/dist/cli/commands/wallet-read.js +4 -4
- package/dist/cli/mutation-success.d.ts +0 -2
- package/dist/cli/output/classify.d.ts +7 -0
- package/dist/cli/output/classify.js +94 -0
- package/dist/cli/output/render.d.ts +2 -0
- package/dist/cli/output/render.js +13 -0
- package/dist/cli/output/rules/cli-surface.d.ts +2 -0
- package/dist/cli/output/rules/cli-surface.js +110 -0
- package/dist/cli/output/rules/generic.d.ts +2 -0
- package/dist/cli/output/rules/generic.js +13 -0
- package/dist/cli/output/rules/index.d.ts +2 -0
- package/dist/cli/output/rules/index.js +24 -0
- package/dist/cli/output/rules/mining-update.d.ts +2 -0
- package/dist/cli/output/rules/mining-update.js +68 -0
- package/dist/cli/output/rules/services.d.ts +2 -0
- package/dist/cli/output/rules/services.js +110 -0
- package/dist/cli/output/rules/wallet-admin.d.ts +2 -0
- package/dist/cli/output/rules/wallet-admin.js +224 -0
- package/dist/cli/output/rules/wallet-mutations.d.ts +2 -0
- package/dist/cli/output/rules/wallet-mutations.js +274 -0
- package/dist/cli/output/types.d.ts +16 -0
- package/dist/cli/output/types.js +1 -0
- package/dist/cli/output.d.ts +2 -168
- package/dist/cli/output.js +6 -989
- package/dist/cli/pagination.d.ts +15 -0
- package/dist/cli/pagination.js +16 -0
- package/dist/cli/recommendations.d.ts +4 -0
- package/dist/cli/recommendations.js +108 -0
- package/dist/cli/wallet-format/availability.d.ts +5 -0
- package/dist/cli/wallet-format/availability.js +96 -0
- package/dist/cli/wallet-format/balance.d.ts +2 -0
- package/dist/cli/wallet-format/balance.js +162 -0
- package/dist/cli/wallet-format/domains.d.ts +8 -0
- package/dist/cli/wallet-format/domains.js +84 -0
- package/dist/cli/wallet-format/fields.d.ts +6 -0
- package/dist/cli/wallet-format/fields.js +61 -0
- package/dist/cli/wallet-format/identity.d.ts +5 -0
- package/dist/cli/wallet-format/identity.js +19 -0
- package/dist/cli/wallet-format/locks.d.ts +7 -0
- package/dist/cli/wallet-format/locks.js +52 -0
- package/dist/cli/wallet-format/overview.d.ts +2 -0
- package/dist/cli/wallet-format/overview.js +122 -0
- package/dist/cli/wallet-format/pending.d.ts +13 -0
- package/dist/cli/wallet-format/pending.js +101 -0
- package/dist/cli/wallet-format/shared.d.ts +7 -0
- package/dist/cli/wallet-format/shared.js +31 -0
- package/dist/cli/wallet-format/status.d.ts +3 -0
- package/dist/cli/wallet-format/status.js +27 -0
- package/dist/cli/wallet-format.d.ts +8 -30
- package/dist/cli/wallet-format.js +8 -830
- package/dist/cli/wallet-read-helpers.d.ts +6 -0
- package/dist/cli/wallet-read-helpers.js +17 -0
- package/dist/wallet/mining/candidate.d.ts +1 -1
- package/dist/wallet/mining/candidate.js +3 -3
- package/dist/wallet/mining/constants.d.ts +2 -2
- package/dist/wallet/mining/constants.js +2 -2
- package/dist/wallet/mining/sentence-protocol.d.ts +2 -2
- package/dist/wallet/mining/sentences.js +8 -8
- package/dist/wallet/tx/anchor/confirm.d.ts +15 -0
- package/dist/wallet/tx/anchor/confirm.js +60 -0
- package/dist/wallet/tx/anchor/draft.d.ts +39 -0
- package/dist/wallet/tx/anchor/draft.js +167 -0
- package/dist/wallet/tx/anchor/index.d.ts +5 -0
- package/dist/wallet/tx/anchor/index.js +148 -0
- package/dist/wallet/tx/anchor/intent.d.ts +61 -0
- package/dist/wallet/tx/anchor/intent.js +101 -0
- package/dist/wallet/tx/anchor/plan.d.ts +3 -0
- package/dist/wallet/tx/anchor/plan.js +18 -0
- package/dist/wallet/tx/anchor/result.d.ts +25 -0
- package/dist/wallet/tx/anchor/result.js +20 -0
- package/dist/wallet/tx/anchor.d.ts +1 -39
- package/dist/wallet/tx/anchor.js +1 -494
- package/dist/wallet/tx/bitcoin-transfer/confirm.d.ts +7 -0
- package/dist/wallet/tx/bitcoin-transfer/confirm.js +11 -0
- package/dist/wallet/tx/bitcoin-transfer/index.d.ts +5 -0
- package/dist/wallet/tx/bitcoin-transfer/index.js +112 -0
- package/dist/wallet/tx/bitcoin-transfer/intent.d.ts +52 -0
- package/dist/wallet/tx/bitcoin-transfer/intent.js +74 -0
- package/dist/wallet/tx/bitcoin-transfer/plan.d.ts +5 -0
- package/dist/wallet/tx/bitcoin-transfer/plan.js +21 -0
- package/dist/wallet/tx/bitcoin-transfer/result.d.ts +19 -0
- package/dist/wallet/tx/bitcoin-transfer/result.js +16 -0
- package/dist/wallet/tx/bitcoin-transfer.d.ts +1 -35
- package/dist/wallet/tx/bitcoin-transfer.js +1 -200
- package/dist/wallet/tx/cog/confirm.d.ts +13 -0
- package/dist/wallet/tx/cog/confirm.js +59 -0
- package/dist/wallet/tx/cog/draft.d.ts +20 -0
- package/dist/wallet/tx/cog/draft.js +114 -0
- package/dist/wallet/tx/cog/index.d.ts +6 -0
- package/dist/wallet/tx/cog/index.js +117 -0
- package/dist/wallet/tx/cog/intent.d.ts +30 -0
- package/dist/wallet/tx/cog/intent.js +169 -0
- package/dist/wallet/tx/cog/plan.d.ts +19 -0
- package/dist/wallet/tx/cog/plan.js +65 -0
- package/dist/wallet/tx/cog/result.d.ts +27 -0
- package/dist/wallet/tx/cog/result.js +28 -0
- package/dist/wallet/tx/cog/types.d.ts +186 -0
- package/dist/wallet/tx/cog/types.js +2 -0
- package/dist/wallet/tx/cog/variants/claim.d.ts +3 -0
- package/dist/wallet/tx/cog/variants/claim.js +92 -0
- package/dist/wallet/tx/cog/variants/lock.d.ts +2 -0
- package/dist/wallet/tx/cog/variants/lock.js +102 -0
- package/dist/wallet/tx/cog/variants/send.d.ts +2 -0
- package/dist/wallet/tx/cog/variants/send.js +77 -0
- package/dist/wallet/tx/cog.d.ts +1 -96
- package/dist/wallet/tx/cog.js +1 -824
- package/dist/wallet/tx/common.d.ts +14 -199
- package/dist/wallet/tx/common.js +10 -493
- package/dist/wallet/tx/domain-admin/confirm.d.ts +17 -0
- package/dist/wallet/tx/domain-admin/confirm.js +58 -0
- package/dist/wallet/tx/domain-admin/draft.d.ts +20 -0
- package/dist/wallet/tx/domain-admin/draft.js +161 -0
- package/dist/wallet/tx/domain-admin/index.d.ts +9 -0
- package/dist/wallet/tx/domain-admin/index.js +150 -0
- package/dist/wallet/tx/domain-admin/intent.d.ts +12 -0
- package/dist/wallet/tx/domain-admin/intent.js +61 -0
- package/dist/wallet/tx/domain-admin/plan.d.ts +19 -0
- package/dist/wallet/tx/domain-admin/plan.js +64 -0
- package/dist/wallet/tx/domain-admin/result.d.ts +19 -0
- package/dist/wallet/tx/domain-admin/result.js +33 -0
- package/dist/wallet/tx/domain-admin/types.d.ts +162 -0
- package/dist/wallet/tx/domain-admin/types.js +1 -0
- package/dist/wallet/tx/domain-admin/variants/canonical.d.ts +2 -0
- package/dist/wallet/tx/domain-admin/variants/canonical.js +22 -0
- package/dist/wallet/tx/domain-admin/variants/delegate.d.ts +3 -0
- package/dist/wallet/tx/domain-admin/variants/delegate.js +60 -0
- package/dist/wallet/tx/domain-admin/variants/endpoint.d.ts +3 -0
- package/dist/wallet/tx/domain-admin/variants/endpoint.js +102 -0
- package/dist/wallet/tx/domain-admin/variants/miner.d.ts +3 -0
- package/dist/wallet/tx/domain-admin/variants/miner.js +59 -0
- package/dist/wallet/tx/domain-admin.d.ts +1 -107
- package/dist/wallet/tx/domain-admin.js +1 -729
- package/dist/wallet/tx/domain-market/confirm.d.ts +6 -0
- package/dist/wallet/tx/domain-market/confirm.js +52 -0
- package/dist/wallet/tx/domain-market/draft.d.ts +43 -0
- package/dist/wallet/tx/domain-market/draft.js +286 -0
- package/dist/wallet/tx/domain-market/index.d.ts +6 -0
- package/dist/wallet/tx/domain-market/index.js +145 -0
- package/dist/wallet/tx/domain-market/intent.d.ts +15 -0
- package/dist/wallet/tx/domain-market/intent.js +131 -0
- package/dist/wallet/tx/domain-market/plan.d.ts +31 -0
- package/dist/wallet/tx/domain-market/plan.js +98 -0
- package/dist/wallet/tx/domain-market/result.d.ts +45 -0
- package/dist/wallet/tx/domain-market/result.js +88 -0
- package/dist/wallet/tx/domain-market/types.d.ts +221 -0
- package/dist/wallet/tx/domain-market/types.js +1 -0
- package/dist/wallet/tx/domain-market/variants/buy.d.ts +2 -0
- package/dist/wallet/tx/domain-market/variants/buy.js +103 -0
- package/dist/wallet/tx/domain-market/variants/sell.d.ts +2 -0
- package/dist/wallet/tx/domain-market/variants/sell.js +91 -0
- package/dist/wallet/tx/domain-market/variants/transfer.d.ts +2 -0
- package/dist/wallet/tx/domain-market/variants/transfer.js +105 -0
- package/dist/wallet/tx/domain-market.d.ts +1 -116
- package/dist/wallet/tx/domain-market.js +1 -1078
- package/dist/wallet/tx/draft-build.d.ts +60 -0
- package/dist/wallet/tx/draft-build.js +127 -0
- package/dist/wallet/tx/executor.d.ts +6 -40
- package/dist/wallet/tx/executor.js +6 -100
- package/dist/wallet/tx/fee.d.ts +30 -0
- package/dist/wallet/tx/fee.js +98 -0
- package/dist/wallet/tx/field/confirm.d.ts +11 -0
- package/dist/wallet/tx/field/confirm.js +19 -0
- package/dist/wallet/tx/field/draft.d.ts +23 -0
- package/dist/wallet/tx/field/draft.js +202 -0
- package/dist/wallet/tx/field/index.d.ts +5 -0
- package/dist/wallet/tx/field/index.js +140 -0
- package/dist/wallet/tx/field/intent.d.ts +5 -0
- package/dist/wallet/tx/field/intent.js +50 -0
- package/dist/wallet/tx/field/plan.d.ts +20 -0
- package/dist/wallet/tx/field/plan.js +65 -0
- package/dist/wallet/tx/field/result.d.ts +29 -0
- package/dist/wallet/tx/field/result.js +103 -0
- package/dist/wallet/tx/field/types.d.ts +163 -0
- package/dist/wallet/tx/field/types.js +1 -0
- package/dist/wallet/tx/field/variants/clear.d.ts +2 -0
- package/dist/wallet/tx/field/variants/clear.js +60 -0
- package/dist/wallet/tx/field/variants/create.d.ts +2 -0
- package/dist/wallet/tx/field/variants/create.js +67 -0
- package/dist/wallet/tx/field/variants/set.d.ts +2 -0
- package/dist/wallet/tx/field/variants/set.js +195 -0
- package/dist/wallet/tx/field.d.ts +1 -95
- package/dist/wallet/tx/field.js +1 -920
- package/dist/wallet/tx/mining-preemption.d.ts +6 -0
- package/dist/wallet/tx/mining-preemption.js +7 -0
- package/dist/wallet/tx/primitives.d.ts +13 -0
- package/dist/wallet/tx/primitives.js +42 -0
- package/dist/wallet/tx/psbt-assert.d.ts +14 -0
- package/dist/wallet/tx/psbt-assert.js +39 -0
- package/dist/wallet/tx/publish.d.ts +37 -0
- package/dist/wallet/tx/publish.js +88 -0
- package/dist/wallet/tx/readiness.d.ts +7 -0
- package/dist/wallet/tx/readiness.js +61 -0
- package/dist/wallet/tx/reconcile.d.ts +24 -0
- package/dist/wallet/tx/reconcile.js +72 -0
- package/dist/wallet/tx/register/confirm.d.ts +6 -0
- package/dist/wallet/tx/register/confirm.js +66 -0
- package/dist/wallet/tx/register/draft.d.ts +42 -0
- package/dist/wallet/tx/register/draft.js +181 -0
- package/dist/wallet/tx/register/index.d.ts +6 -0
- package/dist/wallet/tx/register/index.js +158 -0
- package/dist/wallet/tx/register/intent.d.ts +74 -0
- package/dist/wallet/tx/register/intent.js +119 -0
- package/dist/wallet/tx/register/plan.d.ts +43 -0
- package/dist/wallet/tx/register/plan.js +168 -0
- package/dist/wallet/tx/register/result.d.ts +78 -0
- package/dist/wallet/tx/register/result.js +41 -0
- package/dist/wallet/tx/register.d.ts +1 -70
- package/dist/wallet/tx/register.js +1 -681
- package/dist/wallet/tx/reputation/confirm.d.ts +11 -0
- package/dist/wallet/tx/reputation/confirm.js +51 -0
- package/dist/wallet/tx/reputation/draft.d.ts +20 -0
- package/dist/wallet/tx/reputation/draft.js +130 -0
- package/dist/wallet/tx/reputation/index.d.ts +4 -0
- package/dist/wallet/tx/reputation/index.js +162 -0
- package/dist/wallet/tx/reputation/intent.d.ts +36 -0
- package/dist/wallet/tx/reputation/intent.js +157 -0
- package/dist/wallet/tx/reputation/plan.d.ts +19 -0
- package/dist/wallet/tx/reputation/plan.js +64 -0
- package/dist/wallet/tx/reputation/result.d.ts +21 -0
- package/dist/wallet/tx/reputation/result.js +31 -0
- package/dist/wallet/tx/reputation/types.d.ts +130 -0
- package/dist/wallet/tx/reputation/types.js +1 -0
- package/dist/wallet/tx/reputation.d.ts +1 -74
- package/dist/wallet/tx/reputation.js +1 -556
- package/dist/wallet/tx/signing.d.ts +18 -0
- package/dist/wallet/tx/signing.js +31 -0
- package/dist/wallet/tx/state-persist.d.ts +27 -0
- package/dist/wallet/tx/state-persist.js +54 -0
- package/dist/wallet/tx/types.d.ts +44 -0
- package/dist/wallet/tx/types.js +1 -0
- package/package.json +1 -1
- package/dist/cli/mining-json.d.ts +0 -20
- package/dist/cli/mining-json.js +0 -46
- package/dist/cli/mutation-json.d.ts +0 -325
- package/dist/cli/mutation-json.js +0 -269
- package/dist/cli/mutation-resolved-json.d.ts +0 -117
- package/dist/cli/mutation-resolved-json.js +0 -123
- package/dist/cli/preview-json.d.ts +0 -319
- package/dist/cli/preview-json.js +0 -254
- package/dist/cli/read-json.d.ts +0 -190
- package/dist/cli/read-json.js +0 -627
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { WalletPrompter } from "../../lifecycle.js";
|
|
2
|
+
import type { ReputationResolvedSummary } from "./types.js";
|
|
3
|
+
export declare function confirmReputationMutation(prompter: WalletPrompter, options: {
|
|
4
|
+
kind: "give" | "revoke";
|
|
5
|
+
sourceDomainName: string;
|
|
6
|
+
targetDomainName: string;
|
|
7
|
+
amountCogtoshi: bigint;
|
|
8
|
+
reviewText: string | null;
|
|
9
|
+
resolved: ReputationResolvedSummary;
|
|
10
|
+
assumeYes?: boolean;
|
|
11
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { formatCogAmount } from "../common.js";
|
|
2
|
+
import { confirmTypedAcknowledgement as confirmSharedTypedAcknowledgement, confirmYesNo as confirmSharedYesNo, } from "../confirm.js";
|
|
3
|
+
import { describeReputationEffect, describeReputationReview, } from "./intent.js";
|
|
4
|
+
async function confirmYesNo(prompter, message, errorCode, options) {
|
|
5
|
+
await confirmSharedYesNo(prompter, message, {
|
|
6
|
+
assumeYes: options.assumeYes,
|
|
7
|
+
errorCode,
|
|
8
|
+
requiresTtyErrorCode: options.requiresTtyErrorCode,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
async function confirmTyped(prompter, expected, prompt, errorCode, options) {
|
|
12
|
+
await confirmSharedTypedAcknowledgement(prompter, {
|
|
13
|
+
assumeYes: options.assumeYes,
|
|
14
|
+
expected,
|
|
15
|
+
prompt,
|
|
16
|
+
errorCode,
|
|
17
|
+
requiresTtyErrorCode: options.requiresTtyErrorCode,
|
|
18
|
+
typedAckRequiredErrorCode: options.typedAckRequiredErrorCode,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export async function confirmReputationMutation(prompter, options) {
|
|
22
|
+
prompter.writeLine(`${options.kind === "give" ? "Giving" : "Revoking"} reputation from "${options.sourceDomainName}" to "${options.targetDomainName}".`);
|
|
23
|
+
prompter.writeLine(`Resolved sender: ${options.resolved.sender.selector} (${options.resolved.sender.address})`);
|
|
24
|
+
prompter.writeLine(`Burn amount: ${formatCogAmount(options.amountCogtoshi)}`);
|
|
25
|
+
prompter.writeLine(`Effect: ${describeReputationEffect(options.resolved.effect)}.`);
|
|
26
|
+
prompter.writeLine(`Review: ${describeReputationReview(options.resolved.review)}.`);
|
|
27
|
+
if (options.reviewText !== null) {
|
|
28
|
+
prompter.writeLine("Warning: review text will be encoded and published publicly in the mempool and on-chain.");
|
|
29
|
+
}
|
|
30
|
+
if (options.kind === "give" && options.resolved.selfStake) {
|
|
31
|
+
prompter.writeLine("Self-stake: yes.");
|
|
32
|
+
prompter.writeLine("Warning: this is self-stake.");
|
|
33
|
+
prompter.writeLine("Self-stake is irrevocable and cannot later be revoked.");
|
|
34
|
+
await confirmTyped(prompter, options.sourceDomainName, `Type ${options.sourceDomainName} to continue: `, "wallet_rep_give_confirmation_rejected", {
|
|
35
|
+
assumeYes: options.assumeYes,
|
|
36
|
+
requiresTtyErrorCode: "wallet_rep_give_requires_tty",
|
|
37
|
+
typedAckRequiredErrorCode: "wallet_rep_give_typed_ack_required",
|
|
38
|
+
});
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
await confirmYesNo(prompter, options.kind === "give"
|
|
42
|
+
? "This burns COG to publish a reputation commitment."
|
|
43
|
+
: "This revokes visible support but the burned COG is not refunded.", options.kind === "give"
|
|
44
|
+
? "wallet_rep_give_confirmation_rejected"
|
|
45
|
+
: "wallet_rep_revoke_confirmation_rejected", {
|
|
46
|
+
assumeYes: options.assumeYes,
|
|
47
|
+
requiresTtyErrorCode: options.kind === "give"
|
|
48
|
+
? "wallet_rep_give_requires_tty"
|
|
49
|
+
: "wallet_rep_revoke_requires_tty",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { WalletRuntimePaths } from "../../runtime.js";
|
|
2
|
+
import type { WalletSecretProvider } from "../../state/provider.js";
|
|
3
|
+
import type { PendingMutationRecord, WalletStateV1 } from "../../types.js";
|
|
4
|
+
import type { WalletReadContext } from "../../read/index.js";
|
|
5
|
+
import type { ReputationDraftMutationOptions, ReputationRpcClient } from "./types.js";
|
|
6
|
+
export declare function createReputationDraftMutation(options: ReputationDraftMutationOptions): PendingMutationRecord;
|
|
7
|
+
export declare function reconcilePendingReputationMutation(options: {
|
|
8
|
+
state: WalletStateV1;
|
|
9
|
+
mutation: PendingMutationRecord;
|
|
10
|
+
provider: WalletSecretProvider;
|
|
11
|
+
nowUnixMs: number;
|
|
12
|
+
paths: WalletRuntimePaths;
|
|
13
|
+
rpc: ReputationRpcClient;
|
|
14
|
+
walletName: string;
|
|
15
|
+
context: WalletReadContext;
|
|
16
|
+
}): Promise<{
|
|
17
|
+
state: WalletStateV1;
|
|
18
|
+
mutation: PendingMutationRecord;
|
|
19
|
+
resolution: "confirmed" | "live" | "repair-required" | "not-seen" | "continue";
|
|
20
|
+
}>;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { lookupDomain } from "@cogcoin/indexer/queries";
|
|
3
|
+
import { createWalletMutationFeeMetadata, unlockTemporaryBuilderLocks, updateMutationRecord, } from "../common.js";
|
|
4
|
+
import { persistWalletMutationState, } from "../executor.js";
|
|
5
|
+
import { upsertPendingMutation } from "../journal.js";
|
|
6
|
+
export function createReputationDraftMutation(options) {
|
|
7
|
+
if (options.existing !== null && options.existing !== undefined) {
|
|
8
|
+
return {
|
|
9
|
+
...options.existing,
|
|
10
|
+
kind: options.kind,
|
|
11
|
+
domainName: options.sourceDomainName,
|
|
12
|
+
senderScriptPubKeyHex: options.sender.scriptPubKeyHex,
|
|
13
|
+
senderLocalIndex: options.sender.localIndex,
|
|
14
|
+
recipientDomainName: options.targetDomainName,
|
|
15
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
16
|
+
reviewPayloadHex: options.reviewPayloadHex,
|
|
17
|
+
status: "draft",
|
|
18
|
+
lastUpdatedAtUnixMs: options.nowUnixMs,
|
|
19
|
+
attemptedTxid: null,
|
|
20
|
+
attemptedWtxid: null,
|
|
21
|
+
...createWalletMutationFeeMetadata(options.feeSelection),
|
|
22
|
+
temporaryBuilderLockedOutpoints: [],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
mutationId: randomBytes(12).toString("hex"),
|
|
27
|
+
kind: options.kind,
|
|
28
|
+
domainName: options.sourceDomainName,
|
|
29
|
+
parentDomainName: null,
|
|
30
|
+
senderScriptPubKeyHex: options.sender.scriptPubKeyHex,
|
|
31
|
+
senderLocalIndex: options.sender.localIndex,
|
|
32
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
33
|
+
recipientDomainName: options.targetDomainName,
|
|
34
|
+
reviewPayloadHex: options.reviewPayloadHex,
|
|
35
|
+
intentFingerprintHex: options.intentFingerprintHex,
|
|
36
|
+
status: "draft",
|
|
37
|
+
createdAtUnixMs: options.nowUnixMs,
|
|
38
|
+
lastUpdatedAtUnixMs: options.nowUnixMs,
|
|
39
|
+
attemptedTxid: null,
|
|
40
|
+
attemptedWtxid: null,
|
|
41
|
+
...createWalletMutationFeeMetadata(options.feeSelection),
|
|
42
|
+
temporaryBuilderLockedOutpoints: [],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function mutationNeedsRepair(mutation, context) {
|
|
46
|
+
if (context.snapshot === null || mutation.recipientDomainName == null) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
const sourceDomain = lookupDomain(context.snapshot.state, mutation.domainName);
|
|
50
|
+
const targetDomain = lookupDomain(context.snapshot.state, mutation.recipientDomainName);
|
|
51
|
+
if (sourceDomain === null || targetDomain === null) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return !sourceDomain.anchored
|
|
55
|
+
|| !targetDomain.anchored
|
|
56
|
+
|| Buffer.from(sourceDomain.ownerScriptPubKey).toString("hex") !== mutation.senderScriptPubKeyHex;
|
|
57
|
+
}
|
|
58
|
+
export async function reconcilePendingReputationMutation(options) {
|
|
59
|
+
if (options.mutation.status === "confirmed" || options.mutation.status === "live") {
|
|
60
|
+
return {
|
|
61
|
+
state: options.state,
|
|
62
|
+
mutation: options.mutation,
|
|
63
|
+
resolution: options.mutation.status,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (options.mutation.status === "repair-required") {
|
|
67
|
+
return {
|
|
68
|
+
state: options.state,
|
|
69
|
+
mutation: options.mutation,
|
|
70
|
+
resolution: "repair-required",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const walletTx = options.mutation.attemptedTxid === null
|
|
74
|
+
? null
|
|
75
|
+
: await options.rpc.getTransaction(options.walletName, options.mutation.attemptedTxid).catch(() => null);
|
|
76
|
+
if (walletTx !== null) {
|
|
77
|
+
await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
|
|
78
|
+
const status = walletTx.confirmations > 0 ? "confirmed" : "live";
|
|
79
|
+
const nextMutation = updateMutationRecord(options.mutation, status, options.nowUnixMs, {
|
|
80
|
+
temporaryBuilderLockedOutpoints: [],
|
|
81
|
+
});
|
|
82
|
+
let nextState = upsertPendingMutation(options.state, nextMutation);
|
|
83
|
+
nextState = await persistWalletMutationState({
|
|
84
|
+
state: nextState,
|
|
85
|
+
provider: options.provider,
|
|
86
|
+
nowUnixMs: options.nowUnixMs,
|
|
87
|
+
paths: options.paths,
|
|
88
|
+
});
|
|
89
|
+
return {
|
|
90
|
+
state: nextState,
|
|
91
|
+
mutation: nextMutation,
|
|
92
|
+
resolution: status,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (mutationNeedsRepair(options.mutation, options.context)) {
|
|
96
|
+
await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
|
|
97
|
+
const repair = updateMutationRecord(options.mutation, "repair-required", options.nowUnixMs, {
|
|
98
|
+
temporaryBuilderLockedOutpoints: [],
|
|
99
|
+
});
|
|
100
|
+
let nextState = upsertPendingMutation(options.state, repair);
|
|
101
|
+
nextState = await persistWalletMutationState({
|
|
102
|
+
state: nextState,
|
|
103
|
+
provider: options.provider,
|
|
104
|
+
nowUnixMs: options.nowUnixMs,
|
|
105
|
+
paths: options.paths,
|
|
106
|
+
});
|
|
107
|
+
return { state: nextState, mutation: repair, resolution: "repair-required" };
|
|
108
|
+
}
|
|
109
|
+
if (options.mutation.status === "broadcast-unknown"
|
|
110
|
+
|| options.mutation.status === "draft"
|
|
111
|
+
|| options.mutation.status === "broadcasting") {
|
|
112
|
+
await unlockTemporaryBuilderLocks(options.rpc, options.walletName, options.mutation.temporaryBuilderLockedOutpoints);
|
|
113
|
+
const canceled = updateMutationRecord(options.mutation, "canceled", options.nowUnixMs, {
|
|
114
|
+
temporaryBuilderLockedOutpoints: [],
|
|
115
|
+
});
|
|
116
|
+
let nextState = upsertPendingMutation(options.state, canceled);
|
|
117
|
+
nextState = await persistWalletMutationState({
|
|
118
|
+
state: nextState,
|
|
119
|
+
provider: options.provider,
|
|
120
|
+
nowUnixMs: options.nowUnixMs,
|
|
121
|
+
paths: options.paths,
|
|
122
|
+
});
|
|
123
|
+
return { state: nextState, mutation: canceled, resolution: "not-seen" };
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
state: options.state,
|
|
127
|
+
mutation: options.mutation,
|
|
128
|
+
resolution: "continue",
|
|
129
|
+
};
|
|
130
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { GiveReputationOptions, ReputationMutationResult, RevokeReputationOptions } from "./types.js";
|
|
2
|
+
export type { GiveReputationOptions, ReputationMutationResult, ReputationResolvedEffect, ReputationResolvedReviewSummary, ReputationResolvedSenderSummary, ReputationResolvedSummary, RevokeReputationOptions, } from "./types.js";
|
|
3
|
+
export declare function giveReputation(options: GiveReputationOptions): Promise<ReputationMutationResult>;
|
|
4
|
+
export declare function revokeReputation(options: RevokeReputationOptions): Promise<ReputationMutationResult>;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { mergeFixedWalletInputs, } from "../common.js";
|
|
2
|
+
import { executeWalletMutationOperation, publishWalletMutation, resolveExistingWalletMutation, } from "../executor.js";
|
|
3
|
+
import { confirmReputationMutation, } from "./confirm.js";
|
|
4
|
+
import { createReputationDraftMutation, reconcilePendingReputationMutation, } from "./draft.js";
|
|
5
|
+
import { createReputationOpReturnData, createStandaloneReputationFingerprint, resolveStandaloneReputationOperation, } from "./intent.js";
|
|
6
|
+
import { buildPlanForReputationOperation, buildReputationTransaction, } from "./plan.js";
|
|
7
|
+
import { createReputationResult, createReputationReuseResult, } from "./result.js";
|
|
8
|
+
async function submitReputationMutation(options) {
|
|
9
|
+
if (!options.prompter.isInteractive && options.assumeYes !== true) {
|
|
10
|
+
throw new Error(`${options.errorPrefix}_requires_tty`);
|
|
11
|
+
}
|
|
12
|
+
if (options.amountCogtoshi <= 0n) {
|
|
13
|
+
throw new Error(`${options.errorPrefix}_invalid_amount`);
|
|
14
|
+
}
|
|
15
|
+
const execution = await executeWalletMutationOperation({
|
|
16
|
+
...options,
|
|
17
|
+
controlLockPurpose: options.errorPrefix,
|
|
18
|
+
preemptionReason: options.errorPrefix,
|
|
19
|
+
async resolveOperation(readContext) {
|
|
20
|
+
return resolveStandaloneReputationOperation({
|
|
21
|
+
readContext: readContext,
|
|
22
|
+
sourceDomainName: options.sourceDomainName,
|
|
23
|
+
targetDomainName: options.targetDomainName,
|
|
24
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
25
|
+
reviewText: options.reviewText,
|
|
26
|
+
kind: options.kind,
|
|
27
|
+
errorPrefix: options.errorPrefix,
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
createIntentFingerprint(operation) {
|
|
31
|
+
return createStandaloneReputationFingerprint({
|
|
32
|
+
kind: options.kind,
|
|
33
|
+
operation,
|
|
34
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
async resolveExistingMutation({ operation, existingMutation, execution }) {
|
|
38
|
+
if (existingMutation === null) {
|
|
39
|
+
return {
|
|
40
|
+
state: operation.state,
|
|
41
|
+
replacementFixedInputs: null,
|
|
42
|
+
result: null,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return resolveExistingWalletMutation({
|
|
46
|
+
existingMutation,
|
|
47
|
+
execution,
|
|
48
|
+
repairRequiredErrorCode: `${options.errorPrefix}_repair_required`,
|
|
49
|
+
reconcileExistingMutation: (mutation) => reconcilePendingReputationMutation({
|
|
50
|
+
state: operation.state,
|
|
51
|
+
mutation,
|
|
52
|
+
provider: execution.provider,
|
|
53
|
+
nowUnixMs: execution.nowUnixMs,
|
|
54
|
+
paths: execution.paths,
|
|
55
|
+
rpc: execution.rpc,
|
|
56
|
+
walletName: execution.walletName,
|
|
57
|
+
context: execution.readContext,
|
|
58
|
+
}),
|
|
59
|
+
createReuseResult: ({ mutation, resolution, fees }) => createReputationReuseResult({
|
|
60
|
+
kind: options.kind,
|
|
61
|
+
operation,
|
|
62
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
63
|
+
mutation,
|
|
64
|
+
resolution,
|
|
65
|
+
fees,
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
async confirm({ operation }) {
|
|
70
|
+
await confirmReputationMutation(options.prompter, {
|
|
71
|
+
kind: options.kind === "rep-give" ? "give" : "revoke",
|
|
72
|
+
sourceDomainName: operation.normalizedSourceDomainName,
|
|
73
|
+
targetDomainName: operation.normalizedTargetDomainName,
|
|
74
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
75
|
+
reviewText: operation.review.text,
|
|
76
|
+
resolved: operation.resolved,
|
|
77
|
+
assumeYes: options.assumeYes,
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
createDraftMutation({ operation, existingMutation, execution, intentFingerprintHex }) {
|
|
81
|
+
return {
|
|
82
|
+
mutation: createReputationDraftMutation({
|
|
83
|
+
kind: options.kind,
|
|
84
|
+
sourceDomainName: operation.normalizedSourceDomainName,
|
|
85
|
+
targetDomainName: operation.normalizedTargetDomainName,
|
|
86
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
87
|
+
sender: operation.sender,
|
|
88
|
+
intentFingerprintHex,
|
|
89
|
+
nowUnixMs: execution.nowUnixMs,
|
|
90
|
+
reviewPayloadHex: operation.review.payloadHex,
|
|
91
|
+
feeSelection: execution.feeSelection,
|
|
92
|
+
existing: existingMutation,
|
|
93
|
+
}),
|
|
94
|
+
prepared: null,
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
async build({ operation, state, execution, replacementFixedInputs }) {
|
|
98
|
+
const reputationPlan = buildPlanForReputationOperation({
|
|
99
|
+
state,
|
|
100
|
+
allUtxos: await execution.rpc.listUnspent(execution.walletName, 1),
|
|
101
|
+
sender: operation.sender,
|
|
102
|
+
opReturnData: createReputationOpReturnData({
|
|
103
|
+
kind: options.kind,
|
|
104
|
+
operation,
|
|
105
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
106
|
+
}),
|
|
107
|
+
errorPrefix: options.errorPrefix,
|
|
108
|
+
});
|
|
109
|
+
return buildReputationTransaction({
|
|
110
|
+
rpc: execution.rpc,
|
|
111
|
+
walletName: execution.walletName,
|
|
112
|
+
state,
|
|
113
|
+
plan: {
|
|
114
|
+
...reputationPlan,
|
|
115
|
+
fixedInputs: mergeFixedWalletInputs(reputationPlan.fixedInputs, replacementFixedInputs),
|
|
116
|
+
},
|
|
117
|
+
feeRateSatVb: execution.feeSelection.feeRateSatVb,
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
publish({ state, execution, built, mutation }) {
|
|
121
|
+
return publishWalletMutation({
|
|
122
|
+
rpc: execution.rpc,
|
|
123
|
+
walletName: execution.walletName,
|
|
124
|
+
snapshotHeight: execution.readContext.snapshot?.tip?.height ?? null,
|
|
125
|
+
built,
|
|
126
|
+
mutation,
|
|
127
|
+
state,
|
|
128
|
+
provider: execution.provider,
|
|
129
|
+
nowUnixMs: execution.nowUnixMs,
|
|
130
|
+
paths: execution.paths,
|
|
131
|
+
errorPrefix: options.errorPrefix,
|
|
132
|
+
});
|
|
133
|
+
},
|
|
134
|
+
createResult({ operation, mutation, built, status, reusedExisting, fees }) {
|
|
135
|
+
return createReputationResult({
|
|
136
|
+
kind: options.kind,
|
|
137
|
+
operation,
|
|
138
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
139
|
+
mutation,
|
|
140
|
+
builtTxid: built?.txid ?? null,
|
|
141
|
+
status: status,
|
|
142
|
+
reusedExisting,
|
|
143
|
+
fees,
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
return execution.result;
|
|
148
|
+
}
|
|
149
|
+
export async function giveReputation(options) {
|
|
150
|
+
return submitReputationMutation({
|
|
151
|
+
...options,
|
|
152
|
+
kind: "rep-give",
|
|
153
|
+
errorPrefix: "wallet_rep_give",
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
export async function revokeReputation(options) {
|
|
157
|
+
return submitReputationMutation({
|
|
158
|
+
...options,
|
|
159
|
+
kind: "rep-revoke",
|
|
160
|
+
errorPrefix: "wallet_rep_revoke",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type MutationSender } from "../common.js";
|
|
2
|
+
import type { ReadyWalletReadContext, ReputationMutationKind, ReputationOperation, ReputationResolvedEffect, ReputationResolvedReviewSummary, ReputationResolvedSenderSummary, ReputationResolvedSummary, ReputationReview, StandaloneReputationOperation } from "./types.js";
|
|
3
|
+
export declare function normalizeReputationDomainName(domainName: string, errorCode: string): string;
|
|
4
|
+
export declare function createReputationIntentFingerprint(parts: Array<string | number | bigint>): string;
|
|
5
|
+
export declare function createResolvedReputationSenderSummary(sender: MutationSender, selector: string): ReputationResolvedSenderSummary;
|
|
6
|
+
export declare function createResolvedReputationSummary(options: {
|
|
7
|
+
kind: "give" | "revoke";
|
|
8
|
+
sender: MutationSender;
|
|
9
|
+
senderSelector: string;
|
|
10
|
+
amountCogtoshi: bigint;
|
|
11
|
+
review: ReputationReview;
|
|
12
|
+
selfStake: boolean;
|
|
13
|
+
}): ReputationResolvedSummary;
|
|
14
|
+
export declare function describeReputationEffect(effect: ReputationResolvedEffect): string;
|
|
15
|
+
export declare function describeReputationReview(review: ReputationResolvedReviewSummary): string;
|
|
16
|
+
export declare function resolveReputationOperation(context: ReadyWalletReadContext, sourceDomainName: string, targetDomainName: string, errorPrefix: string): ReputationOperation;
|
|
17
|
+
export declare function encodeReputationReviewText(reviewText: string | null | undefined, errorPrefix: string): Promise<ReputationReview>;
|
|
18
|
+
export declare function resolveStandaloneReputationOperation(options: {
|
|
19
|
+
readContext: ReadyWalletReadContext;
|
|
20
|
+
sourceDomainName: string;
|
|
21
|
+
targetDomainName: string;
|
|
22
|
+
amountCogtoshi: bigint;
|
|
23
|
+
reviewText: string | null | undefined;
|
|
24
|
+
kind: ReputationMutationKind;
|
|
25
|
+
errorPrefix: string;
|
|
26
|
+
}): Promise<StandaloneReputationOperation>;
|
|
27
|
+
export declare function createStandaloneReputationFingerprint(options: {
|
|
28
|
+
kind: ReputationMutationKind;
|
|
29
|
+
operation: StandaloneReputationOperation;
|
|
30
|
+
amountCogtoshi: bigint;
|
|
31
|
+
}): string;
|
|
32
|
+
export declare function createReputationOpReturnData(options: {
|
|
33
|
+
kind: ReputationMutationKind;
|
|
34
|
+
operation: StandaloneReputationOperation;
|
|
35
|
+
amountCogtoshi: bigint;
|
|
36
|
+
}): Uint8Array;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { encodeSentence } from "@cogcoin/scoring";
|
|
3
|
+
import { getBalance, lookupDomain, } from "@cogcoin/indexer/queries";
|
|
4
|
+
import { serializeRepCommit, serializeRepRevoke, validateDomainName, } from "../../cogop/index.js";
|
|
5
|
+
import { assertWalletMutationContextReady, createFundingMutationSender, } from "../common.js";
|
|
6
|
+
function createSupportKey(sourceDomainId, targetDomainId) {
|
|
7
|
+
return `${sourceDomainId}:${targetDomainId}`;
|
|
8
|
+
}
|
|
9
|
+
export function normalizeReputationDomainName(domainName, errorCode) {
|
|
10
|
+
const normalized = domainName.trim().toLowerCase();
|
|
11
|
+
if (normalized.length === 0) {
|
|
12
|
+
throw new Error(errorCode);
|
|
13
|
+
}
|
|
14
|
+
validateDomainName(normalized);
|
|
15
|
+
return normalized;
|
|
16
|
+
}
|
|
17
|
+
export function createReputationIntentFingerprint(parts) {
|
|
18
|
+
return createHash("sha256")
|
|
19
|
+
.update(parts.map((part) => String(part)).join("\n"))
|
|
20
|
+
.digest("hex");
|
|
21
|
+
}
|
|
22
|
+
export function createResolvedReputationSenderSummary(sender, selector) {
|
|
23
|
+
return {
|
|
24
|
+
selector,
|
|
25
|
+
localIndex: sender.localIndex,
|
|
26
|
+
scriptPubKeyHex: sender.scriptPubKeyHex,
|
|
27
|
+
address: sender.address,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function createResolvedReputationSummary(options) {
|
|
31
|
+
return {
|
|
32
|
+
sender: createResolvedReputationSenderSummary(options.sender, options.senderSelector),
|
|
33
|
+
effect: options.kind === "give"
|
|
34
|
+
? {
|
|
35
|
+
kind: "give-support",
|
|
36
|
+
burnCogtoshi: options.amountCogtoshi.toString(),
|
|
37
|
+
}
|
|
38
|
+
: {
|
|
39
|
+
kind: "revoke-support",
|
|
40
|
+
burnCogtoshi: options.amountCogtoshi.toString(),
|
|
41
|
+
},
|
|
42
|
+
review: {
|
|
43
|
+
included: options.review.payloadHex !== null,
|
|
44
|
+
byteLength: options.review.payload?.length ?? null,
|
|
45
|
+
},
|
|
46
|
+
selfStake: options.selfStake,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function describeReputationEffect(effect) {
|
|
50
|
+
if (effect.kind === "give-support") {
|
|
51
|
+
return `burn ${effect.burnCogtoshi} cogtoshi to publish support`;
|
|
52
|
+
}
|
|
53
|
+
return `revoke visible support with no refund of the previously burned ${effect.burnCogtoshi} cogtoshi`;
|
|
54
|
+
}
|
|
55
|
+
export function describeReputationReview(review) {
|
|
56
|
+
if (!review.included || review.byteLength === null) {
|
|
57
|
+
return "none";
|
|
58
|
+
}
|
|
59
|
+
return `included (${review.byteLength} bytes)`;
|
|
60
|
+
}
|
|
61
|
+
export function resolveReputationOperation(context, sourceDomainName, targetDomainName, errorPrefix) {
|
|
62
|
+
assertWalletMutationContextReady(context, errorPrefix);
|
|
63
|
+
const sourceDomain = lookupDomain(context.snapshot.state, sourceDomainName);
|
|
64
|
+
if (sourceDomain === null) {
|
|
65
|
+
throw new Error(`${errorPrefix}_source_domain_not_found`);
|
|
66
|
+
}
|
|
67
|
+
if (!sourceDomain.anchored) {
|
|
68
|
+
throw new Error(`${errorPrefix}_source_domain_not_anchored`);
|
|
69
|
+
}
|
|
70
|
+
const targetDomain = lookupDomain(context.snapshot.state, targetDomainName);
|
|
71
|
+
if (targetDomain === null) {
|
|
72
|
+
throw new Error(`${errorPrefix}_target_domain_not_found`);
|
|
73
|
+
}
|
|
74
|
+
if (!targetDomain.anchored) {
|
|
75
|
+
throw new Error(`${errorPrefix}_target_domain_not_anchored`);
|
|
76
|
+
}
|
|
77
|
+
const ownerHex = Buffer.from(sourceDomain.ownerScriptPubKey).toString("hex");
|
|
78
|
+
if (ownerHex !== context.localState.state.funding.scriptPubKeyHex || context.model.walletAddress == null) {
|
|
79
|
+
throw new Error(`${errorPrefix}_source_owner_not_locally_controlled`);
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
readContext: context,
|
|
83
|
+
state: context.localState.state,
|
|
84
|
+
sender: createFundingMutationSender(context.localState.state),
|
|
85
|
+
senderSelector: context.model.walletAddress,
|
|
86
|
+
sourceDomain,
|
|
87
|
+
targetDomain,
|
|
88
|
+
availableBalanceCogtoshi: getBalance(context.snapshot.state, sourceDomain.ownerScriptPubKey),
|
|
89
|
+
currentNetSupportCogtoshi: context.snapshot.state.consensus.supportByPair.get(createSupportKey(sourceDomain.domainId, targetDomain.domainId)) ?? 0n,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
export async function encodeReputationReviewText(reviewText, errorPrefix) {
|
|
93
|
+
const trimmed = reviewText?.trim() ?? "";
|
|
94
|
+
if (trimmed === "") {
|
|
95
|
+
return {
|
|
96
|
+
text: null,
|
|
97
|
+
payload: undefined,
|
|
98
|
+
payloadHex: null,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return encodeSentence(trimmed)
|
|
102
|
+
.then((payload) => ({
|
|
103
|
+
text: trimmed,
|
|
104
|
+
payload,
|
|
105
|
+
payloadHex: Buffer.from(payload).toString("hex"),
|
|
106
|
+
}))
|
|
107
|
+
.catch((error) => {
|
|
108
|
+
throw new Error(error instanceof Error ? `${errorPrefix}_invalid_review_${error.message}` : `${errorPrefix}_invalid_review`);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
export async function resolveStandaloneReputationOperation(options) {
|
|
112
|
+
const normalizedSourceDomainName = normalizeReputationDomainName(options.sourceDomainName, `${options.errorPrefix}_missing_source_domain`);
|
|
113
|
+
const normalizedTargetDomainName = normalizeReputationDomainName(options.targetDomainName, `${options.errorPrefix}_missing_target_domain`);
|
|
114
|
+
const operation = resolveReputationOperation(options.readContext, normalizedSourceDomainName, normalizedTargetDomainName, options.errorPrefix);
|
|
115
|
+
if (operation.availableBalanceCogtoshi < options.amountCogtoshi) {
|
|
116
|
+
throw new Error(`${options.errorPrefix}_insufficient_cog_balance`);
|
|
117
|
+
}
|
|
118
|
+
if (options.kind === "rep-revoke") {
|
|
119
|
+
if (operation.sourceDomain.domainId === operation.targetDomain.domainId) {
|
|
120
|
+
throw new Error(`${options.errorPrefix}_self_revoke_not_allowed`);
|
|
121
|
+
}
|
|
122
|
+
if (options.amountCogtoshi > operation.currentNetSupportCogtoshi) {
|
|
123
|
+
throw new Error(`${options.errorPrefix}_amount_exceeds_net_support`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const review = await encodeReputationReviewText(options.reviewText, options.errorPrefix);
|
|
127
|
+
const selfStake = operation.sourceDomain.domainId === operation.targetDomain.domainId;
|
|
128
|
+
return {
|
|
129
|
+
...operation,
|
|
130
|
+
normalizedSourceDomainName,
|
|
131
|
+
normalizedTargetDomainName,
|
|
132
|
+
review,
|
|
133
|
+
resolved: createResolvedReputationSummary({
|
|
134
|
+
kind: options.kind === "rep-give" ? "give" : "revoke",
|
|
135
|
+
sender: operation.sender,
|
|
136
|
+
senderSelector: operation.senderSelector,
|
|
137
|
+
amountCogtoshi: options.amountCogtoshi,
|
|
138
|
+
review,
|
|
139
|
+
selfStake,
|
|
140
|
+
}),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
export function createStandaloneReputationFingerprint(options) {
|
|
144
|
+
return createReputationIntentFingerprint([
|
|
145
|
+
options.kind,
|
|
146
|
+
options.operation.state.walletRootId,
|
|
147
|
+
options.operation.sourceDomain.name,
|
|
148
|
+
options.operation.targetDomain.name,
|
|
149
|
+
options.amountCogtoshi,
|
|
150
|
+
options.operation.review.payloadHex ?? "",
|
|
151
|
+
]);
|
|
152
|
+
}
|
|
153
|
+
export function createReputationOpReturnData(options) {
|
|
154
|
+
return options.kind === "rep-give"
|
|
155
|
+
? serializeRepCommit(options.operation.sourceDomain.domainId, options.operation.targetDomain.domainId, options.amountCogtoshi, options.operation.review.payload).opReturnData
|
|
156
|
+
: serializeRepRevoke(options.operation.sourceDomain.domainId, options.operation.targetDomain.domainId, options.amountCogtoshi, options.operation.review.payload).opReturnData;
|
|
157
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RpcDecodedPsbt, RpcListUnspentEntry } from "../../../bitcoind/types.js";
|
|
2
|
+
import type { BuiltReputationTransaction, ReputationPlan, ReputationRpcClient } from "./types.js";
|
|
3
|
+
import type { WalletStateV1 } from "../../types.js";
|
|
4
|
+
import type { MutationSender } from "../common.js";
|
|
5
|
+
export declare function buildPlanForReputationOperation(options: {
|
|
6
|
+
state: WalletStateV1;
|
|
7
|
+
allUtxos: RpcListUnspentEntry[];
|
|
8
|
+
sender: MutationSender;
|
|
9
|
+
opReturnData: Uint8Array;
|
|
10
|
+
errorPrefix: string;
|
|
11
|
+
}): ReputationPlan;
|
|
12
|
+
export declare function validateFundedReputationDraft(decoded: RpcDecodedPsbt, funded: BuiltReputationTransaction["funded"], plan: ReputationPlan): void;
|
|
13
|
+
export declare function buildReputationTransaction(options: {
|
|
14
|
+
rpc: ReputationRpcClient;
|
|
15
|
+
walletName: string;
|
|
16
|
+
state: WalletStateV1;
|
|
17
|
+
plan: ReputationPlan;
|
|
18
|
+
feeRateSatVb: number;
|
|
19
|
+
}): Promise<BuiltReputationTransaction>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { buildWalletMutationTransactionWithReserveFallback, outpointKey, } from "../common.js";
|
|
2
|
+
function encodeOpReturnScript(payload) {
|
|
3
|
+
if (payload.length <= 75) {
|
|
4
|
+
return Buffer.concat([
|
|
5
|
+
Buffer.from([0x6a, payload.length]),
|
|
6
|
+
Buffer.from(payload),
|
|
7
|
+
]).toString("hex");
|
|
8
|
+
}
|
|
9
|
+
return Buffer.concat([
|
|
10
|
+
Buffer.from([0x6a, 0x4c, payload.length]),
|
|
11
|
+
Buffer.from(payload),
|
|
12
|
+
]).toString("hex");
|
|
13
|
+
}
|
|
14
|
+
export function buildPlanForReputationOperation(options) {
|
|
15
|
+
const fundingUtxos = options.allUtxos.filter((entry) => entry.scriptPubKey === options.state.funding.scriptPubKeyHex
|
|
16
|
+
&& entry.confirmations >= 1
|
|
17
|
+
&& entry.spendable !== false
|
|
18
|
+
&& entry.safe !== false);
|
|
19
|
+
return {
|
|
20
|
+
sender: options.sender,
|
|
21
|
+
changeAddress: options.state.funding.address,
|
|
22
|
+
fixedInputs: [],
|
|
23
|
+
outputs: [{ data: Buffer.from(options.opReturnData).toString("hex") }],
|
|
24
|
+
changePosition: 1,
|
|
25
|
+
expectedOpReturnScriptHex: encodeOpReturnScript(options.opReturnData),
|
|
26
|
+
allowedFundingScriptPubKeyHex: options.state.funding.scriptPubKeyHex,
|
|
27
|
+
eligibleFundingOutpointKeys: new Set(fundingUtxos.map((entry) => outpointKey({ txid: entry.txid, vout: entry.vout }))),
|
|
28
|
+
errorPrefix: options.errorPrefix,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function validateFundedReputationDraft(decoded, funded, plan) {
|
|
32
|
+
const inputs = decoded.tx.vin;
|
|
33
|
+
const outputs = decoded.tx.vout;
|
|
34
|
+
if (inputs.length === 0) {
|
|
35
|
+
throw new Error(`${plan.errorPrefix}_missing_sender_input`);
|
|
36
|
+
}
|
|
37
|
+
if (outputs[0]?.scriptPubKey?.hex !== plan.expectedOpReturnScriptHex) {
|
|
38
|
+
throw new Error(`${plan.errorPrefix}_opreturn_mismatch`);
|
|
39
|
+
}
|
|
40
|
+
if (funded.changepos === -1) {
|
|
41
|
+
if (outputs.length !== 1) {
|
|
42
|
+
throw new Error(`${plan.errorPrefix}_unexpected_output_count`);
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (funded.changepos !== plan.changePosition || outputs.length !== 2) {
|
|
47
|
+
throw new Error(`${plan.errorPrefix}_change_position_mismatch`);
|
|
48
|
+
}
|
|
49
|
+
if (outputs[funded.changepos]?.scriptPubKey?.hex !== plan.allowedFundingScriptPubKeyHex) {
|
|
50
|
+
throw new Error(`${plan.errorPrefix}_change_output_mismatch`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export async function buildReputationTransaction(options) {
|
|
54
|
+
return buildWalletMutationTransactionWithReserveFallback({
|
|
55
|
+
rpc: options.rpc,
|
|
56
|
+
walletName: options.walletName,
|
|
57
|
+
state: options.state,
|
|
58
|
+
plan: options.plan,
|
|
59
|
+
validateFundedDraft: validateFundedReputationDraft,
|
|
60
|
+
finalizeErrorCode: `${options.plan.errorPrefix}_finalize_failed`,
|
|
61
|
+
mempoolRejectPrefix: `${options.plan.errorPrefix}_mempool_rejected`,
|
|
62
|
+
feeRate: options.feeRateSatVb,
|
|
63
|
+
});
|
|
64
|
+
}
|