@prktsol/prkt 1.0.0

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.
Files changed (125) hide show
  1. package/.env.devnet.all-protocols.example +18 -0
  2. package/.env.devnet.autonomous.example +16 -0
  3. package/.env.devnet.jupiter.example +16 -0
  4. package/.env.devnet.kamino.example +17 -0
  5. package/.env.devnet.marinade.example +16 -0
  6. package/.env.devnet.orca.example +16 -0
  7. package/.env.devnet.raydium.example +17 -0
  8. package/.env.example +32 -0
  9. package/ARCHITECTURE.md +159 -0
  10. package/CLI.md +509 -0
  11. package/CLI_QUICKSTART.md +108 -0
  12. package/COMPATIBILITY.md +103 -0
  13. package/DEVNET_PROTOCOL_ADDRESSES.md +72 -0
  14. package/README.md +339 -0
  15. package/dist/agent/AgentManager.js +166 -0
  16. package/dist/agent/AgentRuntime.js +92 -0
  17. package/dist/agent/DecisionEngine.js +95 -0
  18. package/dist/agent/MockPriceFeed.js +13 -0
  19. package/dist/agent/intents/types.js +2 -0
  20. package/dist/agent/new-index.js +17 -0
  21. package/dist/agent/policyFactory.js +54 -0
  22. package/dist/agent/registry/AgentRegistry.js +16 -0
  23. package/dist/agent/runner/AgentRunner.js +266 -0
  24. package/dist/agent/strategies/MemoHeartbeatStrategy.js +15 -0
  25. package/dist/agent/strategies/SimpleScriptedTransferStrategy.js +27 -0
  26. package/dist/agent/strategies/TokenRebalancerStrategy.js +35 -0
  27. package/dist/agent/strategies/TreasuryDistributorStrategy.js +29 -0
  28. package/dist/agent/strategies/UniversalDeFiStrategy.js +19 -0
  29. package/dist/agent/types/AgentContext.js +2 -0
  30. package/dist/cli/index.js +1159 -0
  31. package/dist/cli/services/activityStore.js +42 -0
  32. package/dist/cli/services/agentRegistry.js +123 -0
  33. package/dist/cli/services/agentRuntime.js +55 -0
  34. package/dist/cli/services/storagePaths.js +64 -0
  35. package/dist/cli/services/strategyFactory.js +66 -0
  36. package/dist/cli/services/walletCrypto.js +120 -0
  37. package/dist/cli/services/walletRegistry.js +145 -0
  38. package/dist/cli/types.js +2 -0
  39. package/dist/cli/utils/completion.js +62 -0
  40. package/dist/cli/utils/output.js +44 -0
  41. package/dist/config/agentPolicies.js +37 -0
  42. package/dist/config/env.js +249 -0
  43. package/dist/config/policyPresets.js +105 -0
  44. package/dist/core/balances/BalanceService.js +34 -0
  45. package/dist/core/funding/DevnetFundingService.js +105 -0
  46. package/dist/core/idempotency/ExecutionIdempotencyGuard.js +100 -0
  47. package/dist/core/index.js +19 -0
  48. package/dist/core/rpc/RpcClient.js +45 -0
  49. package/dist/core/rpc/RpcFailoverClient.js +97 -0
  50. package/dist/core/tokens/TokenService.js +75 -0
  51. package/dist/core/transactions/PostTransactionVerifier.js +103 -0
  52. package/dist/core/transactions/TransactionService.js +104 -0
  53. package/dist/core/types/services.js +2 -0
  54. package/dist/core/wallet/WalletManager.js +120 -0
  55. package/dist/defi/DeFiCoordinator.js +93 -0
  56. package/dist/defi/DeFiExecutor.js +29 -0
  57. package/dist/defi/DeFiPolicyGuard.js +31 -0
  58. package/dist/defi/adapters/JupiterAdapter.js +25 -0
  59. package/dist/defi/adapters/KaminoAdapter.js +50 -0
  60. package/dist/defi/adapters/MarinadeAdapter.js +25 -0
  61. package/dist/defi/adapters/RaydiumAdapter.js +45 -0
  62. package/dist/defi/kamino/kaminoInstructionCompat.js +24 -0
  63. package/dist/defi/kamino/kaminoLiveConfig.js +60 -0
  64. package/dist/defi/kamino/loadKaminoMarketWithFallback.js +68 -0
  65. package/dist/defi/lp/LpInstructionBuilder.js +2 -0
  66. package/dist/defi/lp/RaydiumLpInstructionBuilder.js +100 -0
  67. package/dist/defi/lp/raydiumDevnetConfig.js +62 -0
  68. package/dist/defi/protocols.js +29 -0
  69. package/dist/defi/types.js +2 -0
  70. package/dist/defi/universal/UniversalDeFiOrchestrator.js +126 -0
  71. package/dist/defi/universal/adapters.js +73 -0
  72. package/dist/defi/universal/index.js +5 -0
  73. package/dist/defi/universal/liveExecutors.js +394 -0
  74. package/dist/defi/universal/types.js +2 -0
  75. package/dist/demo/scenarios/multiAgentDevnetScenario.js +170 -0
  76. package/dist/demo/scripts/runMultiAgentDevnetDemo.js +17 -0
  77. package/dist/dex/JupiterSwapClient.js +59 -0
  78. package/dist/dex/SwapExecutor.js +52 -0
  79. package/dist/index.js +22 -0
  80. package/dist/kora/KoraRpcClient.js +60 -0
  81. package/dist/kora/KoraSigner.js +57 -0
  82. package/dist/kora/gaslessDemo.js +18 -0
  83. package/dist/policy/PolicyGuard.js +158 -0
  84. package/dist/policy/emergencyLock.js +164 -0
  85. package/dist/policy/engine/PolicyEngine.js +237 -0
  86. package/dist/policy/errors.js +10 -0
  87. package/dist/policy/index.js +7 -0
  88. package/dist/policy/sandbox/SandboxExecutor.js +77 -0
  89. package/dist/policy/types/policy.js +2 -0
  90. package/dist/scripts/devnetFunding.js +28 -0
  91. package/dist/scripts/devnetWalletPreflight.js +16 -0
  92. package/dist/scripts/localnetCheck.js +27 -0
  93. package/dist/scripts/managedAgentWallet.js +81 -0
  94. package/dist/scripts/mode.js +6 -0
  95. package/dist/scripts/releaseReadiness.js +93 -0
  96. package/dist/scripts/runAgentUniversalDeFi.js +115 -0
  97. package/dist/scripts/runAutonomousAgentWalletDevnet.js +154 -0
  98. package/dist/scripts/runAutonomousPortfolioDevnet.js +390 -0
  99. package/dist/scripts/runBorrowStrategy.js +35 -0
  100. package/dist/scripts/runDeFiSuite.js +41 -0
  101. package/dist/scripts/runDemoRehearsal.js +111 -0
  102. package/dist/scripts/runDevnetWalletDemo.js +53 -0
  103. package/dist/scripts/runGaslessMemo.js +23 -0
  104. package/dist/scripts/runGaslessWalletDemo.js +60 -0
  105. package/dist/scripts/runKaminoDevnet.js +109 -0
  106. package/dist/scripts/runLpStrategy.js +32 -0
  107. package/dist/scripts/runMarinadeDevnet.js +97 -0
  108. package/dist/scripts/runOrcaLpDevnet.js +208 -0
  109. package/dist/scripts/runRaydiumLpDevnet.js +95 -0
  110. package/dist/scripts/runReleaseReadiness.js +22 -0
  111. package/dist/scripts/runStakeStrategy.js +33 -0
  112. package/dist/scripts/runStressTest.js +41 -0
  113. package/dist/scripts/runTradeLoop.js +53 -0
  114. package/dist/scripts/runUniversalDeFiDemo.js +84 -0
  115. package/dist/scripts/runYieldStrategy.js +33 -0
  116. package/dist/scripts/runtimeFactory.js +27 -0
  117. package/dist/scripts/shared.js +24 -0
  118. package/dist/scripts/simulateAttack.js +40 -0
  119. package/dist/scripts/simulateSwarm.js +106 -0
  120. package/dist/simulation/attack.js +30 -0
  121. package/dist/solana/programs.js +9 -0
  122. package/dist/spl/TokenWallet.js +65 -0
  123. package/dist/types/policy.js +2 -0
  124. package/dist/wallet/WalletManager.js +5 -0
  125. package/package.json +99 -0
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ActivityStore = void 0;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ const storagePaths_1 = require("./storagePaths");
10
+ class ActivityStore {
11
+ append(record) {
12
+ const payload = this.read();
13
+ payload.activities.push(record);
14
+ this.write(payload);
15
+ }
16
+ list(limit = 100) {
17
+ const activities = this.read().activities;
18
+ return activities.slice(Math.max(activities.length - limit, 0));
19
+ }
20
+ listByAgent(agent, limit = 100) {
21
+ return this.list(limit).filter((entry) => entry.agent === agent);
22
+ }
23
+ read() {
24
+ const storePath = (0, storagePaths_1.resolveCliDataPath)("cli-activity.json");
25
+ if (!(0, fs_1.existsSync)(storePath)) {
26
+ return {
27
+ activities: []
28
+ };
29
+ }
30
+ const raw = (0, fs_1.readFileSync)(storePath, "utf8");
31
+ const parsed = JSON.parse(raw);
32
+ return {
33
+ activities: parsed.activities ?? []
34
+ };
35
+ }
36
+ write(payload) {
37
+ const storePath = (0, storagePaths_1.resolveCliDataPath)("cli-activity.json");
38
+ (0, fs_1.mkdirSync)(path_1.default.dirname(storePath), { recursive: true, mode: 0o700 });
39
+ (0, fs_1.writeFileSync)(storePath, JSON.stringify(payload, null, 2), { mode: 0o600 });
40
+ }
41
+ }
42
+ exports.ActivityStore = ActivityStore;
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AgentRegistryStore = void 0;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ const walletRegistry_1 = require("./walletRegistry");
10
+ const storagePaths_1 = require("./storagePaths");
11
+ const policyPresets_1 = require("../../config/policyPresets");
12
+ class AgentRegistryStore {
13
+ walletRegistry;
14
+ constructor(walletRegistry = new walletRegistry_1.WalletRegistry()) {
15
+ this.walletRegistry = walletRegistry;
16
+ }
17
+ list() {
18
+ return this.read().agents.slice().sort((a, b) => a.name.localeCompare(b.name));
19
+ }
20
+ find(name) {
21
+ return this.read().agents.find((agent) => agent.name === name);
22
+ }
23
+ ensureForWallet(walletName) {
24
+ const existing = this.find(walletName);
25
+ if (existing) {
26
+ return existing;
27
+ }
28
+ const wallet = this.walletRegistry.find(walletName);
29
+ if (!wallet) {
30
+ throw new Error(`Cannot create agent for wallet '${walletName}': wallet not found.`);
31
+ }
32
+ const record = {
33
+ createdAtIso: new Date().toISOString(),
34
+ name: walletName,
35
+ policyMode: "sandbox",
36
+ policyPreset: policyPresets_1.DEFAULT_POLICY_PRESET,
37
+ status: "active",
38
+ strategy: "memo-heartbeat",
39
+ walletName
40
+ };
41
+ this.upsert(record);
42
+ return record;
43
+ }
44
+ createAgent(input) {
45
+ const existing = this.find(input.agentId);
46
+ if (existing) {
47
+ throw new Error(`Agent '${input.agentId}' already exists.`);
48
+ }
49
+ const walletName = input.walletName ?? input.agentId;
50
+ const wallet = this.walletRegistry.find(walletName);
51
+ if (!wallet) {
52
+ throw new Error(`Cannot create agent '${input.agentId}': wallet '${walletName}' not found.`);
53
+ }
54
+ const record = {
55
+ createdAtIso: new Date().toISOString(),
56
+ name: input.agentId,
57
+ ownerId: input.ownerId,
58
+ policyMode: "sandbox",
59
+ policyPreset: policyPresets_1.DEFAULT_POLICY_PRESET,
60
+ status: "active",
61
+ strategy: "memo-heartbeat",
62
+ walletName
63
+ };
64
+ this.upsert(record);
65
+ return record;
66
+ }
67
+ upsert(record) {
68
+ const registry = this.read();
69
+ const existingIndex = registry.agents.findIndex((agent) => agent.name === record.name);
70
+ if (existingIndex >= 0) {
71
+ registry.agents[existingIndex] = record;
72
+ }
73
+ else {
74
+ registry.agents.push(record);
75
+ }
76
+ this.write(registry);
77
+ return record;
78
+ }
79
+ patch(name, update) {
80
+ const existing = this.find(name);
81
+ if (!existing) {
82
+ throw new Error(`Agent '${name}' not found.`);
83
+ }
84
+ return this.upsert({
85
+ ...existing,
86
+ ...update
87
+ });
88
+ }
89
+ synchronizeWithWallets() {
90
+ for (const wallet of this.walletRegistry.list()) {
91
+ if (!this.find(wallet.name)) {
92
+ this.ensureForWallet(wallet.name);
93
+ }
94
+ }
95
+ return this.list();
96
+ }
97
+ read() {
98
+ const registryPath = (0, storagePaths_1.resolveCliDataPath)("cli-agents.json");
99
+ if (!(0, fs_1.existsSync)(registryPath)) {
100
+ return {
101
+ agents: []
102
+ };
103
+ }
104
+ const raw = (0, fs_1.readFileSync)(registryPath, "utf8");
105
+ const parsed = JSON.parse(raw);
106
+ return {
107
+ agents: (parsed.agents ?? []).map((agent) => this.normalize(agent))
108
+ };
109
+ }
110
+ write(payload) {
111
+ const registryPath = (0, storagePaths_1.resolveCliDataPath)("cli-agents.json");
112
+ (0, fs_1.mkdirSync)(path_1.default.dirname(registryPath), { recursive: true, mode: 0o700 });
113
+ (0, fs_1.writeFileSync)(registryPath, JSON.stringify(payload, null, 2), { mode: 0o600 });
114
+ }
115
+ normalize(agent) {
116
+ return {
117
+ ...agent,
118
+ ownerId: agent.ownerId,
119
+ policyPreset: agent.policyPreset ?? policyPresets_1.DEFAULT_POLICY_PRESET
120
+ };
121
+ }
122
+ }
123
+ exports.AgentRegistryStore = AgentRegistryStore;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runAgentOnce = runAgentOnce;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const AgentRunner_1 = require("../../agent/runner/AgentRunner");
6
+ const env_1 = require("../../config/env");
7
+ const policyPresets_1 = require("../../config/policyPresets");
8
+ const BalanceService_1 = require("../../core/balances/BalanceService");
9
+ const RpcClient_1 = require("../../core/rpc/RpcClient");
10
+ const TokenService_1 = require("../../core/tokens/TokenService");
11
+ const TransactionService_1 = require("../../core/transactions/TransactionService");
12
+ const universal_1 = require("../../defi/universal");
13
+ const shared_1 = require("../../scripts/shared");
14
+ const walletRegistry_1 = require("./walletRegistry");
15
+ const strategyFactory_1 = require("./strategyFactory");
16
+ async function runAgentOnce(input) {
17
+ const walletRegistry = new walletRegistry_1.WalletRegistry();
18
+ const walletManager = walletRegistry.toWalletManager(input.agent.walletName);
19
+ const rpcClient = new RpcClient_1.RpcClient((0, env_1.getRpcUrl)(), "confirmed");
20
+ const tokenService = new TokenService_1.TokenService(rpcClient);
21
+ const transactionService = new TransactionService_1.TransactionService(rpcClient);
22
+ const balanceService = new BalanceService_1.BalanceService(rpcClient, tokenService);
23
+ const universalDeFi = new universal_1.UniversalDeFiOrchestrator({
24
+ koraSigner: (0, shared_1.createKoraSigner)(),
25
+ liveFirst: (0, env_1.isUniversalDeFiLiveFirstEnabled)(),
26
+ walletManager
27
+ });
28
+ const runner = new AgentRunner_1.AgentRunner();
29
+ const policyConfig = (0, policyPresets_1.resolvePolicyConfig)({
30
+ agentId: input.agent.name,
31
+ overrides: input.agent.policyOverrides,
32
+ presetName: input.agent.policyPreset
33
+ });
34
+ runner.registerAgent({
35
+ context: {
36
+ id: input.agent.name,
37
+ walletManager,
38
+ walletPublicKey: new web3_js_1.PublicKey(walletManager.publicKey.toBase58()),
39
+ rpcClient,
40
+ transactionService,
41
+ tokenService,
42
+ balanceService,
43
+ policyConfig: policyConfig,
44
+ logger: () => undefined,
45
+ universalDeFiExecutor: universalDeFi
46
+ },
47
+ strategy: (0, strategyFactory_1.createStrategy)({
48
+ name: input.overrideStrategy ?? input.agent.strategy,
49
+ config: input.agent.strategyConfig
50
+ }),
51
+ approvalMode: policyConfig.approvalMode
52
+ });
53
+ const [result] = await runner.runOnceParallel();
54
+ return result;
55
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getCliDataDir = getCliDataDir;
7
+ exports.resolveCliDataPath = resolveCliDataPath;
8
+ exports.getCliHomeEnvName = getCliHomeEnvName;
9
+ exports.probeCliDataDir = probeCliDataDir;
10
+ const fs_1 = require("fs");
11
+ const os_1 = __importDefault(require("os"));
12
+ const path_1 = __importDefault(require("path"));
13
+ const CLI_HOME_ENV = "PRKT_CLI_HOME";
14
+ function resolveBaseDir() {
15
+ const override = process.env[CLI_HOME_ENV]?.trim();
16
+ if (override) {
17
+ return path_1.default.resolve(override);
18
+ }
19
+ if (process.platform === "win32") {
20
+ const windowsBase = process.env.APPDATA || process.env.LOCALAPPDATA;
21
+ if (windowsBase) {
22
+ return path_1.default.join(windowsBase, "PRKT");
23
+ }
24
+ }
25
+ if (process.platform === "darwin") {
26
+ return path_1.default.join(os_1.default.homedir(), "Library", "Application Support", "PRKT");
27
+ }
28
+ const xdgBase = process.env.XDG_DATA_HOME?.trim();
29
+ if (xdgBase) {
30
+ return path_1.default.join(xdgBase, "prkt");
31
+ }
32
+ return path_1.default.join(os_1.default.homedir(), ".local", "share", "prkt");
33
+ }
34
+ function getCliDataDir() {
35
+ const baseDir = resolveBaseDir();
36
+ (0, fs_1.mkdirSync)(baseDir, { recursive: true, mode: 0o700 });
37
+ return baseDir;
38
+ }
39
+ function resolveCliDataPath(fileName) {
40
+ return path_1.default.join(getCliDataDir(), fileName);
41
+ }
42
+ function getCliHomeEnvName() {
43
+ return CLI_HOME_ENV;
44
+ }
45
+ function probeCliDataDir() {
46
+ const dataDir = getCliDataDir();
47
+ const probePath = path_1.default.join(dataDir, ".prkt-write-test");
48
+ try {
49
+ (0, fs_1.writeFileSync)(probePath, "ok", { mode: 0o600 });
50
+ (0, fs_1.rmSync)(probePath, { force: true });
51
+ return {
52
+ details: "ok",
53
+ path: dataDir,
54
+ writable: true
55
+ };
56
+ }
57
+ catch (error) {
58
+ return {
59
+ details: error instanceof Error ? error.message : "unknown write error",
60
+ path: dataDir,
61
+ writable: false
62
+ };
63
+ }
64
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createStrategy = createStrategy;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const MemoHeartbeatStrategy_1 = require("../../agent/strategies/MemoHeartbeatStrategy");
6
+ const SimpleScriptedTransferStrategy_1 = require("../../agent/strategies/SimpleScriptedTransferStrategy");
7
+ const UniversalDeFiStrategy_1 = require("../../agent/strategies/UniversalDeFiStrategy");
8
+ function createStrategy(input) {
9
+ const name = input.name.trim().toLowerCase();
10
+ if (name === "memo-heartbeat") {
11
+ return new MemoHeartbeatStrategy_1.MemoHeartbeatStrategy();
12
+ }
13
+ if (name === "simple-scripted-transfer") {
14
+ const to = typeof input.config?.to === "string" ? input.config.to : undefined;
15
+ const amountSol = typeof input.config?.amountSol === "number" ? input.config.amountSol : 0.001;
16
+ if (!to) {
17
+ throw new Error("simple-scripted-transfer requires strategy config key 'to'.");
18
+ }
19
+ return new SimpleScriptedTransferStrategy_1.SimpleScriptedTransferStrategy({
20
+ to,
21
+ lamports: Math.round(amountSol * web3_js_1.LAMPORTS_PER_SOL),
22
+ memo: typeof input.config?.memo === "string"
23
+ ? input.config.memo
24
+ : "cli simple-scripted-transfer"
25
+ });
26
+ }
27
+ if (name === "universal-defi") {
28
+ return new UniversalDeFiStrategy_1.UniversalDeFiStrategy([
29
+ {
30
+ capability: "trade",
31
+ snapshot: {
32
+ buyThresholdUsd: 100,
33
+ solPriceUsd: 95
34
+ }
35
+ },
36
+ {
37
+ capability: "staking",
38
+ snapshot: {
39
+ idleSolLamports: Math.round(1 * web3_js_1.LAMPORTS_PER_SOL)
40
+ }
41
+ },
42
+ {
43
+ capability: "lp",
44
+ snapshot: {
45
+ liquidityInRange: true
46
+ }
47
+ },
48
+ {
49
+ capability: "lending",
50
+ snapshot: {
51
+ healthFactor: 2.1,
52
+ idleUsdcAtomic: 5_000_000
53
+ }
54
+ },
55
+ {
56
+ capability: "borrowing",
57
+ snapshot: {
58
+ borrowDemandUsdcAtomic: 3_000_000,
59
+ collateralSolLamports: Math.round(1 * web3_js_1.LAMPORTS_PER_SOL),
60
+ healthFactor: 2.3
61
+ }
62
+ }
63
+ ]);
64
+ }
65
+ throw new Error(`Unknown strategy '${input.name}'. Supported: memo-heartbeat, simple-scripted-transfer, universal-defi.`);
66
+ }
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.encryptSecretKeyForPlatform = encryptSecretKeyForPlatform;
7
+ exports.decryptSecretKeyForPlatform = decryptSecretKeyForPlatform;
8
+ exports.createRecoveryPackage = createRecoveryPackage;
9
+ exports.decryptSecretKeyWithRecovery = decryptSecretKeyWithRecovery;
10
+ exports.getPlatformMasterKeySource = getPlatformMasterKeySource;
11
+ const fs_1 = require("fs");
12
+ const path_1 = __importDefault(require("path"));
13
+ const crypto_1 = require("crypto");
14
+ const storagePaths_1 = require("./storagePaths");
15
+ const MASTER_KEY_ENV = "PRKT_WALLET_MASTER_KEY";
16
+ const KEY_BYTES = 32;
17
+ function encryptSecretKeyForPlatform(secretKey) {
18
+ const { key } = resolvePlatformMasterKey({ allowCreate: true });
19
+ return encryptBytes(secretKey, key);
20
+ }
21
+ function decryptSecretKeyForPlatform(payload) {
22
+ const { key } = resolvePlatformMasterKey({ allowCreate: false });
23
+ return decryptBytes(payload, key);
24
+ }
25
+ function createRecoveryPackage(secretKey) {
26
+ const recoveryKey = encodeRecoveryKey((0, crypto_1.randomBytes)(KEY_BYTES));
27
+ const salt = (0, crypto_1.randomBytes)(16);
28
+ const key = (0, crypto_1.scryptSync)(recoveryKey, salt, KEY_BYTES);
29
+ const encrypted = encryptBytes(secretKey, key);
30
+ return {
31
+ recoveryKey,
32
+ recoveryPackage: {
33
+ algorithm: "scrypt-aes-256-gcm",
34
+ ciphertext: encrypted.ciphertext,
35
+ iv: encrypted.iv,
36
+ kdf: "scrypt",
37
+ salt: salt.toString("base64"),
38
+ tag: encrypted.tag
39
+ }
40
+ };
41
+ }
42
+ function decryptSecretKeyWithRecovery(input) {
43
+ const key = (0, crypto_1.scryptSync)(input.recoveryKey, Buffer.from(input.recoveryPackage.salt, "base64"), KEY_BYTES);
44
+ return decryptBytes({
45
+ algorithm: "aes-256-gcm",
46
+ ciphertext: input.recoveryPackage.ciphertext,
47
+ iv: input.recoveryPackage.iv,
48
+ tag: input.recoveryPackage.tag
49
+ }, key);
50
+ }
51
+ function getPlatformMasterKeySource() {
52
+ return resolvePlatformMasterKey({ allowCreate: true }).source;
53
+ }
54
+ function resolvePlatformMasterKey(input) {
55
+ const masterKeyPath = (0, storagePaths_1.resolveCliDataPath)("platform-wallet-master.key");
56
+ const envValue = process.env[MASTER_KEY_ENV]?.trim();
57
+ if (envValue) {
58
+ return {
59
+ key: parseConfiguredKey(envValue),
60
+ source: "env"
61
+ };
62
+ }
63
+ if ((0, fs_1.existsSync)(masterKeyPath)) {
64
+ return {
65
+ key: readStoredKey(masterKeyPath),
66
+ source: "local-file"
67
+ };
68
+ }
69
+ if (!input.allowCreate) {
70
+ throw new Error(`Wallet master key is not configured. Set ${MASTER_KEY_ENV} or create ${masterKeyPath}.`);
71
+ }
72
+ const generated = (0, crypto_1.randomBytes)(KEY_BYTES);
73
+ (0, fs_1.mkdirSync)(path_1.default.dirname(masterKeyPath), { recursive: true, mode: 0o700 });
74
+ (0, fs_1.writeFileSync)(masterKeyPath, generated.toString("base64"), { mode: 0o600 });
75
+ return {
76
+ key: generated,
77
+ source: "local-file"
78
+ };
79
+ }
80
+ function parseConfiguredKey(value) {
81
+ if (/^[0-9a-f]{64}$/iu.test(value)) {
82
+ return Buffer.from(value, "hex");
83
+ }
84
+ const base64 = Buffer.from(value, "base64");
85
+ if (base64.length === KEY_BYTES) {
86
+ return base64;
87
+ }
88
+ throw new Error(`${MASTER_KEY_ENV} must be a 32-byte key encoded as base64 or 64 hex characters.`);
89
+ }
90
+ function readStoredKey(filePath) {
91
+ const raw = (0, fs_1.readFileSync)(filePath, "utf8").trim();
92
+ const parsed = Buffer.from(raw, "base64");
93
+ if (parsed.length !== KEY_BYTES) {
94
+ throw new Error(`Stored wallet master key at ${filePath} is invalid.`);
95
+ }
96
+ return parsed;
97
+ }
98
+ function encryptBytes(value, key) {
99
+ const iv = (0, crypto_1.randomBytes)(12);
100
+ const cipher = (0, crypto_1.createCipheriv)("aes-256-gcm", key, iv);
101
+ const ciphertext = Buffer.concat([cipher.update(Buffer.from(value)), cipher.final()]);
102
+ return {
103
+ algorithm: "aes-256-gcm",
104
+ ciphertext: ciphertext.toString("base64"),
105
+ iv: iv.toString("base64"),
106
+ tag: cipher.getAuthTag().toString("base64")
107
+ };
108
+ }
109
+ function decryptBytes(payload, key) {
110
+ const decipher = (0, crypto_1.createDecipheriv)(payload.algorithm, key, Buffer.from(payload.iv, "base64"));
111
+ decipher.setAuthTag(Buffer.from(payload.tag, "base64"));
112
+ const plaintext = Buffer.concat([
113
+ decipher.update(Buffer.from(payload.ciphertext, "base64")),
114
+ decipher.final()
115
+ ]);
116
+ return Uint8Array.from(plaintext);
117
+ }
118
+ function encodeRecoveryKey(bytes) {
119
+ return `prkt_recovery_${bytes.toString("base64url")}`;
120
+ }
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WalletRegistry = void 0;
7
+ exports.generateTemporaryWalletName = generateTemporaryWalletName;
8
+ const fs_1 = require("fs");
9
+ const path_1 = __importDefault(require("path"));
10
+ const web3_js_1 = require("@solana/web3.js");
11
+ const WalletManager_1 = require("../../core/wallet/WalletManager");
12
+ const walletCrypto_1 = require("./walletCrypto");
13
+ const storagePaths_1 = require("./storagePaths");
14
+ class WalletRegistry {
15
+ list() {
16
+ return this.read().wallets.slice().sort((a, b) => a.name.localeCompare(b.name));
17
+ }
18
+ find(name) {
19
+ return this.read().wallets.find((wallet) => wallet.name === name);
20
+ }
21
+ create(name) {
22
+ const existing = this.find(name);
23
+ if (existing) {
24
+ throw new Error(`Wallet '${name}' already exists.`);
25
+ }
26
+ return this.provision({
27
+ name,
28
+ secretKey: web3_js_1.Keypair.generate().secretKey
29
+ });
30
+ }
31
+ toWalletManager(name) {
32
+ const record = this.requireRecord(name);
33
+ return WalletManager_1.WalletManager.fromSecretKey(this.resolveSecretKey(record), "generated");
34
+ }
35
+ ensureFromEnv(name) {
36
+ const existing = this.find(name);
37
+ if (existing) {
38
+ return {
39
+ created: false,
40
+ record: existing,
41
+ recoveryKey: null
42
+ };
43
+ }
44
+ const fromEnv = WalletManager_1.WalletManager.loadFromEnv();
45
+ return this.provision({
46
+ name,
47
+ secretKey: fromEnv.payer.secretKey
48
+ });
49
+ }
50
+ exportSecretKeyWithRecovery(input) {
51
+ const record = this.requireRecord(input.name);
52
+ if (!record.recoveryPackage) {
53
+ throw new Error(`Wallet '${input.name}' does not have a recovery package.`);
54
+ }
55
+ return (0, walletCrypto_1.decryptSecretKeyWithRecovery)({
56
+ recoveryKey: input.recoveryKey,
57
+ recoveryPackage: record.recoveryPackage
58
+ });
59
+ }
60
+ provision(input) {
61
+ const wallet = WalletManager_1.WalletManager.fromSecretKey(input.secretKey, "generated");
62
+ const recovery = (0, walletCrypto_1.createRecoveryPackage)(input.secretKey);
63
+ const record = {
64
+ createdAtIso: new Date().toISOString(),
65
+ encryptedSecretKey: (0, walletCrypto_1.encryptSecretKeyForPlatform)(input.secretKey),
66
+ name: input.name,
67
+ publicKey: wallet.publicKey.toBase58(),
68
+ recoveryPackage: recovery.recoveryPackage,
69
+ version: 2
70
+ };
71
+ const registry = this.read();
72
+ registry.wallets.push(record);
73
+ this.write(registry);
74
+ return {
75
+ created: true,
76
+ record,
77
+ recoveryKey: recovery.recoveryKey
78
+ };
79
+ }
80
+ requireRecord(name) {
81
+ const registry = this.read();
82
+ const record = registry.wallets.find((wallet) => wallet.name === name);
83
+ if (!record) {
84
+ throw new Error(`Wallet '${name}' not found.`);
85
+ }
86
+ const migrated = this.maybeMigrateLegacyRecord(registry, record);
87
+ return migrated ?? record;
88
+ }
89
+ read() {
90
+ const registryPath = (0, storagePaths_1.resolveCliDataPath)("cli-wallets.json");
91
+ if (!(0, fs_1.existsSync)(registryPath)) {
92
+ return {
93
+ wallets: []
94
+ };
95
+ }
96
+ const raw = (0, fs_1.readFileSync)(registryPath, "utf8");
97
+ const parsed = JSON.parse(raw);
98
+ return {
99
+ wallets: (parsed.wallets ?? []).map((wallet) => this.normalize(wallet))
100
+ };
101
+ }
102
+ write(payload) {
103
+ const registryPath = (0, storagePaths_1.resolveCliDataPath)("cli-wallets.json");
104
+ (0, fs_1.mkdirSync)(path_1.default.dirname(registryPath), { recursive: true, mode: 0o700 });
105
+ (0, fs_1.writeFileSync)(registryPath, JSON.stringify(payload, null, 2), { mode: 0o600 });
106
+ }
107
+ maybeMigrateLegacyRecord(registry, record) {
108
+ if (!record.secretKey || record.encryptedSecretKey) {
109
+ return null;
110
+ }
111
+ const secretKey = Uint8Array.from(record.secretKey);
112
+ const recovery = (0, walletCrypto_1.createRecoveryPackage)(secretKey);
113
+ const migrated = {
114
+ createdAtIso: record.createdAtIso,
115
+ encryptedSecretKey: (0, walletCrypto_1.encryptSecretKeyForPlatform)(secretKey),
116
+ name: record.name,
117
+ publicKey: record.publicKey,
118
+ recoveryPackage: recovery.recoveryPackage,
119
+ version: 2
120
+ };
121
+ const index = registry.wallets.findIndex((entry) => entry.name === record.name);
122
+ registry.wallets[index] = migrated;
123
+ this.write(registry);
124
+ return migrated;
125
+ }
126
+ normalize(wallet) {
127
+ return {
128
+ ...wallet,
129
+ version: wallet.version ?? (wallet.encryptedSecretKey ? 2 : 1)
130
+ };
131
+ }
132
+ resolveSecretKey(record) {
133
+ if (record.encryptedSecretKey) {
134
+ return (0, walletCrypto_1.decryptSecretKeyForPlatform)(record.encryptedSecretKey);
135
+ }
136
+ if (record.secretKey) {
137
+ return Uint8Array.from(record.secretKey);
138
+ }
139
+ throw new Error(`Wallet '${record.name}' does not contain recoverable key material.`);
140
+ }
141
+ }
142
+ exports.WalletRegistry = WalletRegistry;
143
+ function generateTemporaryWalletName() {
144
+ return `wallet-${web3_js_1.Keypair.generate().publicKey.toBase58().slice(0, 8)}`;
145
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.completionWords = completionWords;
4
+ exports.buildBashCompletion = buildBashCompletion;
5
+ exports.buildZshCompletion = buildZshCompletion;
6
+ exports.buildPowerShellCompletion = buildPowerShellCompletion;
7
+ const TOP_LEVEL_COMMANDS = [
8
+ "wallet",
9
+ "token",
10
+ "policy",
11
+ "agent",
12
+ "monitor",
13
+ "demo",
14
+ "audit",
15
+ "config",
16
+ "doctor",
17
+ "completion"
18
+ ];
19
+ function completionWords() {
20
+ return TOP_LEVEL_COMMANDS.join(" ");
21
+ }
22
+ function buildBashCompletion() {
23
+ return `# bash completion for prkt
24
+ _prkt_completion() {
25
+ local cur cword
26
+ cur="\${COMP_WORDS[COMP_CWORD]}"
27
+ cword=$COMP_CWORD
28
+ local commands="${completionWords()}"
29
+ if [[ $cword -eq 1 ]]; then
30
+ COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
31
+ return
32
+ fi
33
+ }
34
+ complete -F _prkt_completion prkt
35
+ `;
36
+ }
37
+ function buildZshCompletion() {
38
+ return `#compdef prkt
39
+ _prkt() {
40
+ local -a commands
41
+ commands=(${completionWords()})
42
+ if (( CURRENT == 2 )); then
43
+ _describe 'command' commands
44
+ return
45
+ fi
46
+ }
47
+ compdef _prkt prkt
48
+ `;
49
+ }
50
+ function buildPowerShellCompletion() {
51
+ return `Register-ArgumentCompleter -Native -CommandName prkt -ScriptBlock {
52
+ param($wordToComplete, $commandAst, $cursorPosition)
53
+ $commands = @(${completionWords()
54
+ .split(" ")
55
+ .map((word) => `'${word}'`)
56
+ .join(", ")})
57
+ $commands | Where-Object { $_ -like \"$wordToComplete*\" } | ForEach-Object {
58
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
59
+ }
60
+ }
61
+ `;
62
+ }