@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,44 @@
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.printResult = printResult;
7
+ exports.txExplorer = txExplorer;
8
+ exports.addressExplorer = addressExplorer;
9
+ exports.failWithMessage = failWithMessage;
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ function printResult(output, payload, title) {
12
+ if (output.json) {
13
+ console.log(JSON.stringify(payload, null, 2));
14
+ return;
15
+ }
16
+ if (title) {
17
+ console.log(chalk_1.default.cyan(title));
18
+ }
19
+ if (Array.isArray(payload)) {
20
+ if (payload.length === 0) {
21
+ console.log(chalk_1.default.yellow("No records."));
22
+ return;
23
+ }
24
+ console.table(payload);
25
+ return;
26
+ }
27
+ if (typeof payload === "object" && payload !== null) {
28
+ console.table([payload]);
29
+ return;
30
+ }
31
+ console.log(payload);
32
+ }
33
+ function txExplorer(signature) {
34
+ return `https://explorer.solana.com/tx/${signature}?cluster=devnet`;
35
+ }
36
+ function addressExplorer(address) {
37
+ return `https://explorer.solana.com/address/${address}?cluster=devnet`;
38
+ }
39
+ function failWithMessage(error) {
40
+ if (error instanceof Error) {
41
+ throw new Error(error.message);
42
+ }
43
+ throw new Error("Unknown CLI error");
44
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDefaultPolicyConfig = createDefaultPolicyConfig;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const programs_1 = require("../solana/programs");
6
+ const env_1 = require("./env");
7
+ function createDefaultPolicyConfig(input) {
8
+ const ttlMinutes = (0, env_1.getPolicySessionTtlMinutes)();
9
+ return {
10
+ agentId: input.agentId,
11
+ approvalMode: input.approvalMode ?? "sandbox",
12
+ sessionExpiresAtIso8601: new Date(Date.now() + ttlMinutes * 60_000).toISOString(),
13
+ limits: {
14
+ maxSolPerTxLamports: input.maxSolPerTxLamports ?? 1_000_000_000,
15
+ maxSplPerTxRawAmount: input.maxSplPerTxRawAmount ?? 1000000000n,
16
+ maxTransactionsPerSession: input.maxTransactionsPerSession ?? 50,
17
+ maxTransactionsPerDay: input.maxTransactionsPerDay ?? 500
18
+ },
19
+ rules: {
20
+ allowOpaqueProgramIds: input.allowOpaqueProgramIds ?? [],
21
+ allowedCloseAccountDestinations: input.allowedCloseAccountDestinations,
22
+ allowedProgramIds: [
23
+ web3_js_1.SystemProgram.programId.toBase58(),
24
+ programs_1.TOKEN_PROGRAM_ID.toBase58(),
25
+ programs_1.ASSOCIATED_TOKEN_PROGRAM_ID.toBase58(),
26
+ programs_1.MEMO_PROGRAM_ID.toBase58(),
27
+ ...(input.extraAllowedProgramIds ?? []),
28
+ ...(0, env_1.getExtraWhitelistedPrograms)()
29
+ ],
30
+ allowedMintAddresses: input.allowedMints ?? [],
31
+ allowedTransferDestinations: input.allowedTransferDestinations,
32
+ denyUnknownInstructionsByDefault: true,
33
+ requireSimulationSuccess: true,
34
+ rejectSuspiciousBalanceDeltas: true
35
+ }
36
+ };
37
+ }
@@ -0,0 +1,249 @@
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.EnvConfigError = void 0;
7
+ exports.getOptionalSecretKey = getOptionalSecretKey;
8
+ exports.getOptionalDevnetTreasurySecretKey = getOptionalDevnetTreasurySecretKey;
9
+ exports.getRpcUrl = getRpcUrl;
10
+ exports.getRpcFallbackUrl = getRpcFallbackUrl;
11
+ exports.getKoraRpcUrl = getKoraRpcUrl;
12
+ exports.isKoraMockMode = isKoraMockMode;
13
+ exports.getJupiterApiBaseUrl = getJupiterApiBaseUrl;
14
+ exports.getRaydiumLpConfigPath = getRaydiumLpConfigPath;
15
+ exports.getKaminoLiveConfigPath = getKaminoLiveConfigPath;
16
+ exports.isLiveSwapPathEnabled = isLiveSwapPathEnabled;
17
+ exports.isLiveRaydiumLpEnabled = isLiveRaydiumLpEnabled;
18
+ exports.isLiveKaminoEnabled = isLiveKaminoEnabled;
19
+ exports.isLiveMarinadeEnabled = isLiveMarinadeEnabled;
20
+ exports.isUniversalDeFiLiveFirstEnabled = isUniversalDeFiLiveFirstEnabled;
21
+ exports.getUsdcMintAddress = getUsdcMintAddress;
22
+ exports.getExtraWhitelistedPrograms = getExtraWhitelistedPrograms;
23
+ exports.getPolicySessionTtlMinutes = getPolicySessionTtlMinutes;
24
+ exports.getRemoteSignerConfig = getRemoteSignerConfig;
25
+ exports.detectClusterFromRpcUrl = detectClusterFromRpcUrl;
26
+ exports.assertMintMatchesRpcCluster = assertMintMatchesRpcCluster;
27
+ exports.redactSecretForLogs = redactSecretForLogs;
28
+ const dotenv_1 = __importDefault(require("dotenv"));
29
+ const web3_js_1 = require("@solana/web3.js");
30
+ dotenv_1.default.config();
31
+ const PRIVATE_KEY_ENV = "AGENT_PRIVATE_KEY";
32
+ const RPC_ENV = "SOLANA_RPC_URL";
33
+ const RPC_FALLBACK_ENV = "SOLANA_RPC_FALLBACK_URL";
34
+ const KORA_RPC_ENV = "KORA_RPC_URL";
35
+ const KORA_MOCK_MODE_ENV = "KORA_MOCK_MODE";
36
+ const JUPITER_API_BASE_URL_ENV = "JUPITER_API_BASE_URL";
37
+ const ENABLE_LIVE_SWAP_PATH_ENV = "ENABLE_LIVE_SWAP_PATH";
38
+ const ENABLE_LIVE_RAYDIUM_LP_ENV = "ENABLE_LIVE_RAYDIUM_LP";
39
+ const ENABLE_LIVE_KAMINO_ENV = "ENABLE_LIVE_KAMINO";
40
+ const ENABLE_LIVE_MARINADE_ENV = "ENABLE_LIVE_MARINADE";
41
+ const RAYDIUM_LP_CONFIG_PATH_ENV = "RAYDIUM_LP_CONFIG_PATH";
42
+ const KAMINO_LIVE_CONFIG_PATH_ENV = "KAMINO_LIVE_CONFIG_PATH";
43
+ const UNIVERSAL_DEFI_LIVE_FIRST_ENV = "UNIVERSAL_DEFI_LIVE_FIRST";
44
+ const USDC_MINT_ENV = "USDC_MINT";
45
+ const EXTRA_WHITELISTED_PROGRAMS_ENV = "EXTRA_WHITELISTED_PROGRAMS";
46
+ const POLICY_SESSION_TTL_MINUTES_ENV = "POLICY_SESSION_TTL_MINUTES";
47
+ const DEVNET_TREASURY_PRIVATE_KEY_ENV = "DEVNET_TREASURY_PRIVATE_KEY";
48
+ const REMOTE_SIGNER_URL_ENV = "REMOTE_SIGNER_URL";
49
+ const REMOTE_SIGNER_BEARER_TOKEN_ENV = "REMOTE_SIGNER_BEARER_TOKEN";
50
+ const REMOTE_SIGNER_PUBKEY_ENV = "REMOTE_SIGNER_PUBKEY";
51
+ const MAINNET_USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
52
+ const DEVNET_USDC_MINT = "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU";
53
+ class EnvConfigError extends Error {
54
+ constructor(message) {
55
+ super(message);
56
+ this.name = "EnvConfigError";
57
+ }
58
+ }
59
+ exports.EnvConfigError = EnvConfigError;
60
+ function parseSecretKey(rawValue) {
61
+ let parsed;
62
+ try {
63
+ parsed = JSON.parse(rawValue);
64
+ }
65
+ catch {
66
+ throw new EnvConfigError(`${PRIVATE_KEY_ENV} must be valid JSON.`);
67
+ }
68
+ if (!Array.isArray(parsed) || !parsed.every((value) => Number.isInteger(value))) {
69
+ throw new EnvConfigError(`${PRIVATE_KEY_ENV} must be a JSON array of integers.`);
70
+ }
71
+ if (parsed.length !== 64) {
72
+ throw new EnvConfigError(`${PRIVATE_KEY_ENV} must contain exactly 64 integers.`);
73
+ }
74
+ const byteValues = parsed;
75
+ if (byteValues.some((value) => value < 0 || value > 255)) {
76
+ throw new EnvConfigError(`${PRIVATE_KEY_ENV} values must be between 0 and 255.`);
77
+ }
78
+ return Uint8Array.from(byteValues);
79
+ }
80
+ function getOptionalSecretKeyFromEnv(envName) {
81
+ const rawValue = process.env[envName];
82
+ if (!rawValue) {
83
+ return null;
84
+ }
85
+ const trimmed = rawValue.trim();
86
+ if (trimmed.length === 0 || trimmed === "[]") {
87
+ return null;
88
+ }
89
+ return parseSecretKey(trimmed);
90
+ }
91
+ function getOptionalSecretKey() {
92
+ return getOptionalSecretKeyFromEnv(PRIVATE_KEY_ENV);
93
+ }
94
+ function getOptionalDevnetTreasurySecretKey() {
95
+ return getOptionalSecretKeyFromEnv(DEVNET_TREASURY_PRIVATE_KEY_ENV);
96
+ }
97
+ function getRpcUrl() {
98
+ const rpcUrl = process.env[RPC_ENV]?.trim();
99
+ return rpcUrl && rpcUrl.length > 0 ? rpcUrl : "https://api.devnet.solana.com";
100
+ }
101
+ function getRpcFallbackUrl() {
102
+ const fallbackUrl = process.env[RPC_FALLBACK_ENV]?.trim();
103
+ return fallbackUrl && fallbackUrl.length > 0 ? fallbackUrl : null;
104
+ }
105
+ function getKoraRpcUrl() {
106
+ const koraRpcUrl = process.env[KORA_RPC_ENV]?.trim();
107
+ return koraRpcUrl && koraRpcUrl.length > 0
108
+ ? koraRpcUrl
109
+ : "https://kora.devnet.lazorkit.com";
110
+ }
111
+ function isKoraMockMode() {
112
+ const rawValue = process.env[KORA_MOCK_MODE_ENV]?.trim().toLowerCase();
113
+ if (!rawValue) {
114
+ return true;
115
+ }
116
+ return rawValue !== "false" && rawValue !== "0";
117
+ }
118
+ function getJupiterApiBaseUrl() {
119
+ const value = process.env[JUPITER_API_BASE_URL_ENV]?.trim();
120
+ return value && value.length > 0 ? value : "https://lite-api.jup.ag";
121
+ }
122
+ function getRaydiumLpConfigPath() {
123
+ const value = process.env[RAYDIUM_LP_CONFIG_PATH_ENV]?.trim();
124
+ return value && value.length > 0 ? value : "raydium_lp.devnet.json";
125
+ }
126
+ function getKaminoLiveConfigPath() {
127
+ const value = process.env[KAMINO_LIVE_CONFIG_PATH_ENV]?.trim();
128
+ return value && value.length > 0 ? value : "kamino_live.json";
129
+ }
130
+ function isLiveSwapPathEnabled() {
131
+ const rawValue = process.env[ENABLE_LIVE_SWAP_PATH_ENV]?.trim().toLowerCase();
132
+ if (!rawValue) {
133
+ return false;
134
+ }
135
+ return rawValue === "true" || rawValue === "1";
136
+ }
137
+ function isLiveRaydiumLpEnabled() {
138
+ const rawValue = process.env[ENABLE_LIVE_RAYDIUM_LP_ENV]?.trim().toLowerCase();
139
+ if (!rawValue) {
140
+ return false;
141
+ }
142
+ return rawValue === "true" || rawValue === "1";
143
+ }
144
+ function isLiveKaminoEnabled() {
145
+ const rawValue = process.env[ENABLE_LIVE_KAMINO_ENV]?.trim().toLowerCase();
146
+ if (!rawValue) {
147
+ return false;
148
+ }
149
+ return rawValue === "true" || rawValue === "1";
150
+ }
151
+ function isLiveMarinadeEnabled() {
152
+ const rawValue = process.env[ENABLE_LIVE_MARINADE_ENV]?.trim().toLowerCase();
153
+ if (!rawValue) {
154
+ return false;
155
+ }
156
+ return rawValue === "true" || rawValue === "1";
157
+ }
158
+ function isUniversalDeFiLiveFirstEnabled() {
159
+ const rawValue = process.env[UNIVERSAL_DEFI_LIVE_FIRST_ENV]?.trim().toLowerCase();
160
+ if (!rawValue) {
161
+ return true;
162
+ }
163
+ return rawValue !== "false" && rawValue !== "0";
164
+ }
165
+ function getUsdcMintAddress() {
166
+ const value = process.env[USDC_MINT_ENV]?.trim();
167
+ return value && value.length > 0
168
+ ? value
169
+ : DEVNET_USDC_MINT;
170
+ }
171
+ function getExtraWhitelistedPrograms() {
172
+ const value = process.env[EXTRA_WHITELISTED_PROGRAMS_ENV]?.trim();
173
+ if (!value) {
174
+ return [];
175
+ }
176
+ return value
177
+ .split(",")
178
+ .map((entry) => entry.trim())
179
+ .filter((entry) => entry.length > 0);
180
+ }
181
+ function getPolicySessionTtlMinutes() {
182
+ const rawValue = process.env[POLICY_SESSION_TTL_MINUTES_ENV]?.trim();
183
+ if (!rawValue) {
184
+ return 60;
185
+ }
186
+ const ttl = Number(rawValue);
187
+ if (!Number.isInteger(ttl) || ttl <= 0 || ttl > 24 * 60) {
188
+ throw new EnvConfigError(`${POLICY_SESSION_TTL_MINUTES_ENV} must be a positive integer between 1 and 1440.`);
189
+ }
190
+ return ttl;
191
+ }
192
+ function getRemoteSignerConfig() {
193
+ const url = process.env[REMOTE_SIGNER_URL_ENV]?.trim();
194
+ const bearerToken = process.env[REMOTE_SIGNER_BEARER_TOKEN_ENV]?.trim();
195
+ const publicKeyValue = process.env[REMOTE_SIGNER_PUBKEY_ENV]?.trim();
196
+ const configuredCount = [url, bearerToken, publicKeyValue].filter((value) => value && value.length > 0).length;
197
+ if (configuredCount === 0) {
198
+ return null;
199
+ }
200
+ if (configuredCount !== 3 || !url || !bearerToken || !publicKeyValue) {
201
+ throw new EnvConfigError(`${REMOTE_SIGNER_URL_ENV}, ${REMOTE_SIGNER_BEARER_TOKEN_ENV}, and ${REMOTE_SIGNER_PUBKEY_ENV} must all be configured together.`);
202
+ }
203
+ let publicKey;
204
+ try {
205
+ publicKey = new web3_js_1.PublicKey(publicKeyValue);
206
+ }
207
+ catch {
208
+ throw new EnvConfigError(`${REMOTE_SIGNER_PUBKEY_ENV} must be a valid Solana public key.`);
209
+ }
210
+ return {
211
+ bearerToken,
212
+ publicKey,
213
+ url
214
+ };
215
+ }
216
+ function detectClusterFromRpcUrl(rpcUrl) {
217
+ const normalized = rpcUrl.trim().toLowerCase();
218
+ if (normalized.includes("localhost") ||
219
+ normalized.includes("127.0.0.1") ||
220
+ normalized.includes("0.0.0.0")) {
221
+ return "localnet";
222
+ }
223
+ if (normalized.includes("devnet")) {
224
+ return "devnet";
225
+ }
226
+ if (normalized.includes("testnet")) {
227
+ return "testnet";
228
+ }
229
+ if (normalized.includes("mainnet")) {
230
+ return "mainnet-beta";
231
+ }
232
+ return "unknown";
233
+ }
234
+ function assertMintMatchesRpcCluster(input) {
235
+ const cluster = detectClusterFromRpcUrl(input.rpcUrl);
236
+ if (cluster === "unknown" || cluster === "localnet" || cluster === "testnet") {
237
+ return;
238
+ }
239
+ const mint = input.mintAddress.trim();
240
+ if (cluster === "devnet" && mint === MAINNET_USDC_MINT) {
241
+ throw new EnvConfigError(`${input.mintName} is set to the mainnet mint (${MAINNET_USDC_MINT}) while RPC is devnet (${input.rpcUrl}). Set USDC_MINT to a devnet mint such as ${DEVNET_USDC_MINT}.`);
242
+ }
243
+ if (cluster === "mainnet-beta" && mint === DEVNET_USDC_MINT) {
244
+ throw new EnvConfigError(`${input.mintName} is set to the devnet mint (${DEVNET_USDC_MINT}) while RPC is mainnet (${input.rpcUrl}). Set USDC_MINT to the mainnet mint ${MAINNET_USDC_MINT}.`);
245
+ }
246
+ }
247
+ function redactSecretForLogs() {
248
+ return `[REDACTED:${PRIVATE_KEY_ENV}]`;
249
+ }
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_POLICY_PRESET = exports.POLICY_PRESETS = void 0;
4
+ exports.listPolicyPresetSummaries = listPolicyPresetSummaries;
5
+ exports.resolvePolicyConfig = resolvePolicyConfig;
6
+ const agentPolicies_1 = require("./agentPolicies");
7
+ exports.POLICY_PRESETS = {
8
+ "observe-only": {
9
+ label: "Observe Only",
10
+ description: "Blocks broadcasts while still allowing inspection and monitoring.",
11
+ build: ({ agentId }) => (0, agentPolicies_1.createDefaultPolicyConfig)({
12
+ agentId,
13
+ maxTransactionsPerDay: 0,
14
+ maxTransactionsPerSession: 0
15
+ })
16
+ },
17
+ "simulate-only": {
18
+ label: "Simulate Only",
19
+ description: "Safe simulation-first mode with conservative limits for testing.",
20
+ build: ({ agentId }) => (0, agentPolicies_1.createDefaultPolicyConfig)({
21
+ agentId,
22
+ maxSolPerTxLamports: 100_000_000,
23
+ maxSplPerTxRawAmount: 100000000n,
24
+ maxTransactionsPerDay: 25,
25
+ maxTransactionsPerSession: 5
26
+ })
27
+ },
28
+ "auto-devnet-safe": {
29
+ label: "Auto Devnet Safe",
30
+ description: "Default autonomous devnet profile with conservative per-tx and per-session limits.",
31
+ build: ({ agentId }) => (0, agentPolicies_1.createDefaultPolicyConfig)({
32
+ agentId,
33
+ maxSolPerTxLamports: 300_000_000,
34
+ maxSplPerTxRawAmount: 1000000000n,
35
+ maxTransactionsPerDay: 20,
36
+ maxTransactionsPerSession: 5
37
+ })
38
+ },
39
+ "guarded-live": {
40
+ label: "Guarded Live",
41
+ description: "Manual-approval profile for higher-risk live execution.",
42
+ build: ({ agentId }) => (0, agentPolicies_1.createDefaultPolicyConfig)({
43
+ agentId,
44
+ approvalMode: "live",
45
+ maxSolPerTxLamports: 1_000_000_000,
46
+ maxSplPerTxRawAmount: 5000000000n,
47
+ maxTransactionsPerDay: 50,
48
+ maxTransactionsPerSession: 10
49
+ })
50
+ },
51
+ custom: {
52
+ label: "Custom",
53
+ description: "Custom policy built from provider defaults plus explicit overrides.",
54
+ build: ({ agentId }) => (0, agentPolicies_1.createDefaultPolicyConfig)({ agentId })
55
+ }
56
+ };
57
+ exports.DEFAULT_POLICY_PRESET = "auto-devnet-safe";
58
+ function listPolicyPresetSummaries() {
59
+ return Object.entries(exports.POLICY_PRESETS).map(([name, preset]) => ({
60
+ description: preset.description,
61
+ label: preset.label,
62
+ name
63
+ }));
64
+ }
65
+ function resolvePolicyConfig(input) {
66
+ const base = exports.POLICY_PRESETS[input.presetName].build({
67
+ agentId: input.agentId
68
+ });
69
+ const overrides = input.overrides;
70
+ if (!overrides) {
71
+ return base;
72
+ }
73
+ const ttlMinutes = overrides.sessionTtlMinutes ?? null;
74
+ const sessionExpiresAtIso8601 = ttlMinutes === null
75
+ ? base.sessionExpiresAtIso8601
76
+ : new Date(Date.now() + ttlMinutes * 60_000).toISOString();
77
+ return {
78
+ ...base,
79
+ approvalMode: overrides.approvalMode ?? base.approvalMode,
80
+ sessionExpiresAtIso8601,
81
+ limits: {
82
+ ...base.limits,
83
+ maxSolPerTxLamports: overrides.maxSolPerTxLamports ?? base.limits.maxSolPerTxLamports,
84
+ maxSplPerTxRawAmount: overrides.maxSplPerTxRawAmount !== undefined
85
+ ? BigInt(overrides.maxSplPerTxRawAmount)
86
+ : base.limits.maxSplPerTxRawAmount,
87
+ maxTransactionsPerDay: overrides.maxTransactionsPerDay ?? base.limits.maxTransactionsPerDay,
88
+ maxTransactionsPerSession: overrides.maxTransactionsPerSession ?? base.limits.maxTransactionsPerSession
89
+ },
90
+ rules: {
91
+ ...base.rules,
92
+ allowOpaqueProgramIds: overrides.allowOpaqueProgramIds ?? base.rules.allowOpaqueProgramIds,
93
+ allowedCloseAccountDestinations: overrides.allowedCloseAccountDestinations ?? base.rules.allowedCloseAccountDestinations,
94
+ allowedMintAddresses: overrides.allowedMints ?? base.rules.allowedMintAddresses,
95
+ allowedProgramIds: [
96
+ ...base.rules.allowedProgramIds,
97
+ ...(overrides.extraAllowedProgramIds ?? [])
98
+ ],
99
+ allowedTransferDestinations: overrides.allowedTransferDestinations ?? base.rules.allowedTransferDestinations,
100
+ denyUnknownInstructionsByDefault: overrides.denyUnknownInstructionsByDefault ?? base.rules.denyUnknownInstructionsByDefault,
101
+ rejectSuspiciousBalanceDeltas: overrides.rejectSuspiciousBalanceDeltas ?? base.rules.rejectSuspiciousBalanceDeltas,
102
+ requireSimulationSuccess: overrides.requireSimulationSuccess ?? base.rules.requireSimulationSuccess
103
+ }
104
+ };
105
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BalanceService = void 0;
4
+ const LAMPORTS_PER_SOL = 1_000_000_000;
5
+ class BalanceService {
6
+ rpcClient;
7
+ tokenService;
8
+ constructor(rpcClient, tokenService) {
9
+ this.rpcClient = rpcClient;
10
+ this.tokenService = tokenService;
11
+ }
12
+ async getSolBalanceLamports(owner) {
13
+ return this.rpcClient.getBalance(owner, "confirmed");
14
+ }
15
+ async getSolBalance(owner) {
16
+ const lamports = await this.getSolBalanceLamports(owner);
17
+ return lamports / LAMPORTS_PER_SOL;
18
+ }
19
+ async getSplTokenBalance(input) {
20
+ const ata = this.tokenService.findAssociatedTokenAddress(input.owner, input.mint);
21
+ const account = await this.rpcClient.getAccountInfo(ata, "confirmed");
22
+ if (!account) {
23
+ return 0;
24
+ }
25
+ const tokenBalance = await this.rpcClient.getTokenAccountBalance(ata, "confirmed");
26
+ if (tokenBalance.value.uiAmount !== null && tokenBalance.value.uiAmount !== undefined) {
27
+ return tokenBalance.value.uiAmount;
28
+ }
29
+ const decimals = tokenBalance.value.decimals;
30
+ const raw = Number(tokenBalance.value.amount);
31
+ return raw / 10 ** decimals;
32
+ }
33
+ }
34
+ exports.BalanceService = BalanceService;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DevnetFundingService = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const env_1 = require("../../config/env");
6
+ const WalletManager_1 = require("../wallet/WalletManager");
7
+ class DevnetFundingService {
8
+ rpcClient;
9
+ transactionService;
10
+ treasuryWallet;
11
+ constructor(rpcClient, transactionService, treasuryWallet = loadTreasuryWalletFromEnv()) {
12
+ this.rpcClient = rpcClient;
13
+ this.transactionService = transactionService;
14
+ this.treasuryWallet = treasuryWallet;
15
+ }
16
+ hasTreasuryWallet() {
17
+ return this.treasuryWallet !== null;
18
+ }
19
+ getTreasuryPublicKey() {
20
+ return this.treasuryWallet?.publicKey ?? null;
21
+ }
22
+ async ensureMinimumSol(input) {
23
+ const currentBalance = await input.balanceService.getSolBalance(input.recipient);
24
+ if (currentBalance >= input.minimumSol) {
25
+ return null;
26
+ }
27
+ const amountSol = roundSolAmount(input.minimumSol - currentBalance);
28
+ if (this.canUseTreasury(input.recipient)) {
29
+ return this.fundFromTreasury({
30
+ amountSol,
31
+ recipient: input.recipient
32
+ });
33
+ }
34
+ return this.requestAirdrop({
35
+ amountSol: input.airdropAmountSol ?? Math.max(amountSol, 1),
36
+ recipient: input.recipient
37
+ });
38
+ }
39
+ async fundExactSol(input) {
40
+ if (this.canUseTreasury(input.recipient)) {
41
+ return this.fundFromTreasury(input);
42
+ }
43
+ return this.requestAirdrop(input);
44
+ }
45
+ async waitForMinimumBalance(input) {
46
+ const attempts = input.attempts ?? 10;
47
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
48
+ const updatedBalance = await input.balanceService.getSolBalance(input.recipient);
49
+ if (updatedBalance >= input.minimumSol) {
50
+ return updatedBalance;
51
+ }
52
+ await delay(1_000);
53
+ }
54
+ return input.balanceService.getSolBalance(input.recipient);
55
+ }
56
+ canUseTreasury(recipient) {
57
+ return (this.treasuryWallet !== null &&
58
+ !this.treasuryWallet.publicKey.equals(recipient));
59
+ }
60
+ async fundFromTreasury(input) {
61
+ if (!this.treasuryWallet) {
62
+ throw new Error("Treasury wallet is not configured.");
63
+ }
64
+ const built = await this.transactionService.buildTransaction({
65
+ feePayer: this.treasuryWallet.publicKey,
66
+ instructions: [
67
+ this.transactionService.buildSolTransferInstructionInSol({
68
+ amountSol: input.amountSol,
69
+ from: this.treasuryWallet.publicKey,
70
+ to: input.recipient
71
+ })
72
+ ],
73
+ signer: this.treasuryWallet
74
+ });
75
+ const send = await this.transactionService.sendAndConfirm(built);
76
+ return {
77
+ signature: send.signature,
78
+ source: "treasury-transfer"
79
+ };
80
+ }
81
+ async requestAirdrop(input) {
82
+ const signature = await this.rpcClient.requestAirdrop(input.recipient, Math.round(input.amountSol * web3_js_1.LAMPORTS_PER_SOL));
83
+ await this.rpcClient.confirmTransaction(signature, "confirmed");
84
+ return {
85
+ signature,
86
+ source: "airdrop"
87
+ };
88
+ }
89
+ }
90
+ exports.DevnetFundingService = DevnetFundingService;
91
+ function loadTreasuryWalletFromEnv() {
92
+ const secretKey = (0, env_1.getOptionalDevnetTreasurySecretKey)();
93
+ if (!secretKey) {
94
+ return null;
95
+ }
96
+ return WalletManager_1.WalletManager.fromSecretKey(secretKey, "env");
97
+ }
98
+ function roundSolAmount(amountSol) {
99
+ return Math.max(0, Math.round(amountSol * web3_js_1.LAMPORTS_PER_SOL) / web3_js_1.LAMPORTS_PER_SOL);
100
+ }
101
+ function delay(ms) {
102
+ return new Promise((resolve) => {
103
+ setTimeout(resolve, ms);
104
+ });
105
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExecutionIdempotencyGuard = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const DEFAULT_MAX_ENTRIES = 1000;
6
+ const DEFAULT_TTL_MS = 10 * 60 * 1000; // 10 minutes
7
+ /**
8
+ * Prevents duplicate execution of the same intent by tracking unique execution IDs.
9
+ * Uses a bounded in-memory set with TTL-based expiry.
10
+ */
11
+ class ExecutionIdempotencyGuard {
12
+ entries = new Map();
13
+ maxEntries;
14
+ ttlMs;
15
+ cleanupCounter = 0;
16
+ cleanupInterval = 50;
17
+ constructor(options) {
18
+ this.maxEntries = options?.maxEntries ?? DEFAULT_MAX_ENTRIES;
19
+ this.ttlMs = options?.ttlMs ?? DEFAULT_TTL_MS;
20
+ }
21
+ /**
22
+ * Generate a new unique execution ID.
23
+ */
24
+ generateId() {
25
+ return (0, crypto_1.randomUUID)();
26
+ }
27
+ /**
28
+ * Attempt to acquire a lock for the given execution ID.
29
+ * Returns `true` on the first call for a given ID (execution allowed).
30
+ * Returns `false` if the ID has already been acquired (duplicate blocked).
31
+ */
32
+ acquire(executionId) {
33
+ this.maybeCleanup();
34
+ const existing = this.entries.get(executionId);
35
+ if (existing && existing.expiresAt > Date.now()) {
36
+ return false;
37
+ }
38
+ if (this.entries.size >= this.maxEntries) {
39
+ this.evictOldest();
40
+ }
41
+ this.entries.set(executionId, {
42
+ id: executionId,
43
+ expiresAt: Date.now() + this.ttlMs
44
+ });
45
+ return true;
46
+ }
47
+ /**
48
+ * Check whether an execution ID has already been acquired (without acquiring it).
49
+ */
50
+ has(executionId) {
51
+ const existing = this.entries.get(executionId);
52
+ if (!existing) {
53
+ return false;
54
+ }
55
+ if (existing.expiresAt <= Date.now()) {
56
+ this.entries.delete(executionId);
57
+ return false;
58
+ }
59
+ return true;
60
+ }
61
+ /**
62
+ * Returns the number of active (non-expired) tracked entries.
63
+ */
64
+ get size() {
65
+ return this.entries.size;
66
+ }
67
+ /**
68
+ * Remove all tracked entries.
69
+ */
70
+ clear() {
71
+ this.entries.clear();
72
+ }
73
+ maybeCleanup() {
74
+ this.cleanupCounter += 1;
75
+ if (this.cleanupCounter < this.cleanupInterval) {
76
+ return;
77
+ }
78
+ this.cleanupCounter = 0;
79
+ const now = Date.now();
80
+ for (const [id, entry] of this.entries) {
81
+ if (entry.expiresAt <= now) {
82
+ this.entries.delete(id);
83
+ }
84
+ }
85
+ }
86
+ evictOldest() {
87
+ let oldestId = null;
88
+ let oldestExpiry = Infinity;
89
+ for (const [id, entry] of this.entries) {
90
+ if (entry.expiresAt < oldestExpiry) {
91
+ oldestExpiry = entry.expiresAt;
92
+ oldestId = id;
93
+ }
94
+ }
95
+ if (oldestId) {
96
+ this.entries.delete(oldestId);
97
+ }
98
+ }
99
+ }
100
+ exports.ExecutionIdempotencyGuard = ExecutionIdempotencyGuard;