@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,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UniversalDeFiOrchestrator = void 0;
4
+ const policyFactory_1 = require("../../agent/policyFactory");
5
+ const env_1 = require("../../config/env");
6
+ const DeFiExecutor_1 = require("../DeFiExecutor");
7
+ const adapters_1 = require("./adapters");
8
+ const liveExecutors_1 = require("./liveExecutors");
9
+ class UniversalDeFiOrchestrator {
10
+ deps;
11
+ adapters;
12
+ executor;
13
+ constructor(deps, adapters) {
14
+ this.deps = deps;
15
+ this.adapters = adapters ?? [
16
+ new adapters_1.JupiterUniversalAdapter(),
17
+ new adapters_1.MarinadeUniversalAdapter(),
18
+ new adapters_1.RaydiumUniversalAdapter(),
19
+ new adapters_1.KaminoUniversalAdapter()
20
+ ];
21
+ this.executor = new DeFiExecutor_1.DeFiExecutor(deps.policy ??
22
+ (0, policyFactory_1.createDefaultAgentPolicy)({
23
+ maxSpend: {
24
+ lamports: 2_000_000_000
25
+ }
26
+ }));
27
+ }
28
+ async execute(request, options) {
29
+ const adapter = this.resolveAdapter(request);
30
+ if (!adapter) {
31
+ this.log(`No compatible adapter for capability=${request.capability} protocol=${request.protocol ?? "auto"}`);
32
+ return {
33
+ capability: request.capability,
34
+ protocol: request.protocol ?? "raydium",
35
+ result: null
36
+ };
37
+ }
38
+ const intent = adapter.buildIntent(request);
39
+ if (!intent) {
40
+ this.log(`${adapter.protocol} returned HOLD for capability ${request.capability}`);
41
+ return {
42
+ capability: request.capability,
43
+ protocol: adapter.protocol,
44
+ result: null
45
+ };
46
+ }
47
+ const liveFirst = this.deps.liveFirst ?? (0, env_1.isUniversalDeFiLiveFirstEnabled)();
48
+ if (liveFirst) {
49
+ const preparedLive = (await (0, liveExecutors_1.prepareLiveJupiter)({
50
+ intent,
51
+ logger: this.deps.logger,
52
+ walletManager: this.deps.walletManager
53
+ })) ??
54
+ (await (0, liveExecutors_1.prepareLiveRaydiumLp)({
55
+ intent,
56
+ logger: this.deps.logger,
57
+ walletManager: this.deps.walletManager
58
+ })) ??
59
+ (await (0, liveExecutors_1.prepareLiveKamino)({
60
+ intent,
61
+ logger: this.deps.logger,
62
+ walletManager: this.deps.walletManager
63
+ })) ??
64
+ (await (0, liveExecutors_1.prepareLiveMarinade)({
65
+ intent,
66
+ logger: this.deps.logger,
67
+ walletManager: this.deps.walletManager
68
+ }));
69
+ const liveResult = await this.tryExecutePreparedLive(preparedLive, options);
70
+ if (liveResult) {
71
+ return {
72
+ capability: request.capability,
73
+ protocol: adapter.protocol,
74
+ result: liveResult
75
+ };
76
+ }
77
+ }
78
+ const result = await this.executor.executeIntent({
79
+ intent,
80
+ koraSigner: this.deps.koraSigner,
81
+ walletManager: this.deps.walletManager
82
+ });
83
+ return {
84
+ capability: request.capability,
85
+ protocol: adapter.protocol,
86
+ result
87
+ };
88
+ }
89
+ async executeBatch(requests, options) {
90
+ return Promise.all(requests.map((request) => this.execute(request, options)));
91
+ }
92
+ resolveAdapter(request) {
93
+ const scoped = request.protocol
94
+ ? this.adapters.filter((adapter) => adapter.protocol === request.protocol)
95
+ : this.adapters;
96
+ return scoped.find((adapter) => adapter.capabilities.includes(request.capability)) ?? null;
97
+ }
98
+ log(message) {
99
+ (this.deps.logger ?? (() => undefined))(message);
100
+ }
101
+ async tryExecutePreparedLive(prepared, options) {
102
+ if (!prepared) {
103
+ return null;
104
+ }
105
+ if (!options?.liveExecutor) {
106
+ this.log(`guarded live ${prepared.protocol} transaction prepared but no guarded executor was provided`);
107
+ return null;
108
+ }
109
+ const execution = await options.liveExecutor.executePreparedTransaction({
110
+ confirmationStrategy: prepared.confirmationStrategy,
111
+ inspectionContext: prepared.inspectionContext,
112
+ policyConfigPatch: prepared.policyConfigPatch,
113
+ transaction: prepared.transaction
114
+ });
115
+ if (!execution.signature) {
116
+ const reasons = execution.inspection.reasons.join("; ");
117
+ this.log(`guarded live ${prepared.protocol} execution blocked${reasons ? `: ${reasons}` : ""}`);
118
+ return null;
119
+ }
120
+ if (prepared.verifyExecution) {
121
+ await prepared.verifyExecution(execution.signature);
122
+ }
123
+ return prepared.toExecutionResult(execution.signature);
124
+ }
125
+ }
126
+ exports.UniversalDeFiOrchestrator = UniversalDeFiOrchestrator;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KaminoUniversalAdapter = exports.RaydiumUniversalAdapter = exports.MarinadeUniversalAdapter = exports.JupiterUniversalAdapter = void 0;
4
+ const JupiterAdapter_1 = require("../adapters/JupiterAdapter");
5
+ const KaminoAdapter_1 = require("../adapters/KaminoAdapter");
6
+ const MarinadeAdapter_1 = require("../adapters/MarinadeAdapter");
7
+ const RaydiumAdapter_1 = require("../adapters/RaydiumAdapter");
8
+ class JupiterUniversalAdapter {
9
+ protocol = "jupiter";
10
+ capabilities = ["trade"];
11
+ adapter = new JupiterAdapter_1.JupiterAdapter();
12
+ buildIntent(request) {
13
+ if (request.capability !== "trade") {
14
+ return null;
15
+ }
16
+ return this.adapter.buildTradeIntent(request.snapshot);
17
+ }
18
+ }
19
+ exports.JupiterUniversalAdapter = JupiterUniversalAdapter;
20
+ class MarinadeUniversalAdapter {
21
+ protocol = "marinade";
22
+ capabilities = ["staking"];
23
+ adapter = new MarinadeAdapter_1.MarinadeAdapter();
24
+ buildIntent(request) {
25
+ if (request.capability !== "staking") {
26
+ return null;
27
+ }
28
+ return this.adapter.buildStakeIntent(request.snapshot);
29
+ }
30
+ }
31
+ exports.MarinadeUniversalAdapter = MarinadeUniversalAdapter;
32
+ class RaydiumUniversalAdapter {
33
+ protocol = "raydium";
34
+ capabilities = ["lp", "yield"];
35
+ adapter = new RaydiumAdapter_1.RaydiumAdapter();
36
+ buildIntent(request) {
37
+ if (request.capability === "lp") {
38
+ return this.adapter.buildAddLiquidityIntent(request.snapshot);
39
+ }
40
+ if (request.capability === "yield") {
41
+ const rewards = request.snapshot.rewardsClaimableAtomic ?? 0;
42
+ if (rewards <= 0) {
43
+ return null;
44
+ }
45
+ const plan = this.adapter.buildAddLiquidityPlan();
46
+ return {
47
+ action: "harvest",
48
+ amountLamports: 0,
49
+ marketId: plan.poolId,
50
+ memo: `DEFI_INTENT:RAYDIUM:harvest:${rewards}`,
51
+ protocol: this.protocol,
52
+ slippageBps: plan.slippageBps
53
+ };
54
+ }
55
+ return null;
56
+ }
57
+ }
58
+ exports.RaydiumUniversalAdapter = RaydiumUniversalAdapter;
59
+ class KaminoUniversalAdapter {
60
+ protocol = "kamino";
61
+ capabilities = ["lending", "borrowing", "yield"];
62
+ adapter = new KaminoAdapter_1.KaminoAdapter();
63
+ buildIntent(request) {
64
+ if (request.capability === "borrowing") {
65
+ return this.adapter.buildBorrowIntent(request.snapshot);
66
+ }
67
+ if (request.capability !== "lending" && request.capability !== "yield") {
68
+ return null;
69
+ }
70
+ return this.adapter.buildDepositIntent(request.snapshot);
71
+ }
72
+ }
73
+ exports.KaminoUniversalAdapter = KaminoUniversalAdapter;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UniversalDeFiOrchestrator = void 0;
4
+ var UniversalDeFiOrchestrator_1 = require("./UniversalDeFiOrchestrator");
5
+ Object.defineProperty(exports, "UniversalDeFiOrchestrator", { enumerable: true, get: function () { return UniversalDeFiOrchestrator_1.UniversalDeFiOrchestrator; } });
@@ -0,0 +1,394 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.prepareLiveJupiter = prepareLiveJupiter;
4
+ exports.prepareLiveRaydiumLp = prepareLiveRaydiumLp;
5
+ exports.prepareLiveKamino = prepareLiveKamino;
6
+ exports.prepareLiveMarinade = prepareLiveMarinade;
7
+ const kit_1 = require("@solana/kit");
8
+ const marinade_ts_sdk_1 = require("@marinade.finance/marinade-ts-sdk");
9
+ const klend_sdk_1 = require("@kamino-finance/klend-sdk");
10
+ const web3_js_1 = require("@solana/web3.js");
11
+ const env_1 = require("../../config/env");
12
+ const RpcClient_1 = require("../../core/rpc/RpcClient");
13
+ const PostTransactionVerifier_1 = require("../../core/transactions/PostTransactionVerifier");
14
+ const TokenService_1 = require("../../core/tokens/TokenService");
15
+ const JupiterSwapClient_1 = require("../../dex/JupiterSwapClient");
16
+ const SwapExecutor_1 = require("../../dex/SwapExecutor");
17
+ const raydiumDevnetConfig_1 = require("../lp/raydiumDevnetConfig");
18
+ const RaydiumAdapter_1 = require("../adapters/RaydiumAdapter");
19
+ const kaminoInstructionCompat_1 = require("../kamino/kaminoInstructionCompat");
20
+ const kaminoLiveConfig_1 = require("../kamino/kaminoLiveConfig");
21
+ const loadKaminoMarketWithFallback_1 = require("../kamino/loadKaminoMarketWithFallback");
22
+ async function prepareLiveJupiter(input) {
23
+ if (input.intent.protocol !== "jupiter" || input.intent.action !== "trade") {
24
+ return null;
25
+ }
26
+ if (!(0, env_1.isLiveSwapPathEnabled)()) {
27
+ input.logger?.("live jupiter disabled via ENABLE_LIVE_SWAP_PATH");
28
+ return null;
29
+ }
30
+ const amountSol = input.intent.amountLamports / web3_js_1.LAMPORTS_PER_SOL;
31
+ const outputMint = (0, env_1.getUsdcMintAddress)();
32
+ const rpcClient = new RpcClient_1.RpcClient((0, env_1.getRpcUrl)(), "confirmed");
33
+ const tokenService = new TokenService_1.TokenService(rpcClient);
34
+ const verifier = new PostTransactionVerifier_1.PostTransactionVerifier(rpcClient, tokenService);
35
+ const outputSnapshot = await verifier.snapshotSplBalanceForOwner({
36
+ label: `Jupiter output token balance (${outputMint})`,
37
+ mint: new web3_js_1.PublicKey(outputMint),
38
+ owner: input.walletManager.publicKey
39
+ });
40
+ const swapExecutor = new SwapExecutor_1.SwapExecutor(new JupiterSwapClient_1.JupiterSwapClient((0, env_1.getJupiterApiBaseUrl)()));
41
+ const prepared = await swapExecutor.buildSolToTokenSwapTransaction({
42
+ amountSol,
43
+ outputMint,
44
+ slippageBps: input.intent.slippageBps,
45
+ walletManager: input.walletManager
46
+ });
47
+ return {
48
+ protocol: input.intent.protocol,
49
+ toExecutionResult(signature) {
50
+ return {
51
+ action: input.intent.action,
52
+ memo: `LIVE:JUPITER:${input.intent.marketId}:${input.intent.amountLamports}`,
53
+ mock: false,
54
+ protocol: input.intent.protocol,
55
+ signature
56
+ };
57
+ },
58
+ transaction: prepared.transaction,
59
+ async verifyExecution(signature) {
60
+ const [report] = await verifier.assertBalanceChanges([
61
+ {
62
+ minIncreaseRaw: 1n,
63
+ snapshot: outputSnapshot
64
+ }
65
+ ]);
66
+ input.logger?.(`verified ${signature}: ${report.label} ${report.beforeUi} -> ${report.afterUi} (${report.deltaUi})`);
67
+ }
68
+ };
69
+ }
70
+ async function prepareLiveRaydiumLp(input) {
71
+ if (input.intent.protocol !== "raydium" || input.intent.action !== "add_liquidity") {
72
+ return null;
73
+ }
74
+ if (!(0, env_1.isLiveRaydiumLpEnabled)()) {
75
+ input.logger?.("live raydium disabled via ENABLE_LIVE_RAYDIUM_LP");
76
+ return null;
77
+ }
78
+ const rpcUrl = (0, env_1.getRpcUrl)();
79
+ const cluster = (0, env_1.detectClusterFromRpcUrl)(rpcUrl);
80
+ if (cluster !== "devnet" && cluster !== "unknown") {
81
+ input.logger?.(`live raydium lp currently intended for devnet; current cluster=${cluster}`);
82
+ return null;
83
+ }
84
+ const connection = new web3_js_1.Connection(rpcUrl, "confirmed");
85
+ const rpcClient = new RpcClient_1.RpcClient(rpcUrl, "confirmed");
86
+ const tokenService = new TokenService_1.TokenService(rpcClient);
87
+ const verifier = new PostTransactionVerifier_1.PostTransactionVerifier(rpcClient, tokenService);
88
+ const config = (0, raydiumDevnetConfig_1.loadRaydiumLpDevnetConfig)();
89
+ const adapter = new RaydiumAdapter_1.RaydiumAdapter();
90
+ const requiredAccounts = [
91
+ config.poolConfig.poolId,
92
+ config.poolConfig.authority,
93
+ config.poolConfig.baseVault,
94
+ config.poolConfig.quoteVault,
95
+ config.poolConfig.openOrders,
96
+ config.poolConfig.targetOrders,
97
+ config.poolConfig.marketId,
98
+ config.poolConfig.marketEventQueue,
99
+ config.poolConfig.lpMint,
100
+ config.userTokenAccounts.baseTokenAccount,
101
+ config.userTokenAccounts.quoteTokenAccount,
102
+ config.userTokenAccounts.lpTokenAccount
103
+ ];
104
+ const accountInfos = await connection.getMultipleAccountsInfo(requiredAccounts.map((key) => new web3_js_1.PublicKey(key)), "confirmed");
105
+ const missing = requiredAccounts.filter((_, index) => accountInfos[index] === null);
106
+ if (missing.length > 0) {
107
+ input.logger?.(`live raydium config invalid on cluster; missing ${missing.length} accounts`);
108
+ return null;
109
+ }
110
+ const latestBlockhash = await connection.getLatestBlockhash("confirmed");
111
+ const lpBalanceSnapshot = await verifier.snapshotSplTokenAccount({
112
+ label: "Raydium LP token balance",
113
+ mint: new web3_js_1.PublicKey(config.poolConfig.lpMint),
114
+ tokenAccount: new web3_js_1.PublicKey(config.userTokenAccounts.lpTokenAccount)
115
+ });
116
+ const transaction = await adapter.buildAddLiquidityTransactionDraft({
117
+ baseAmountIn: config.amounts.baseAmountIn,
118
+ otherAmountMin: config.amounts.otherAmountMin,
119
+ owner: input.walletManager,
120
+ poolConfig: config.poolConfig,
121
+ quoteAmountIn: config.amounts.quoteAmountIn,
122
+ recentBlockhash: latestBlockhash.blockhash,
123
+ userTokenAccounts: config.userTokenAccounts
124
+ });
125
+ return {
126
+ confirmationStrategy: {
127
+ blockhash: latestBlockhash.blockhash,
128
+ lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
129
+ signature: ""
130
+ },
131
+ protocol: input.intent.protocol,
132
+ policyConfigPatch: {
133
+ rules: {
134
+ allowOpaqueProgramIds: [config.poolConfig.programId],
135
+ allowedProgramIds: [config.poolConfig.programId]
136
+ }
137
+ },
138
+ toExecutionResult(signature) {
139
+ return {
140
+ action: input.intent.action,
141
+ memo: `LIVE:RAYDIUM:${config.poolConfig.poolId}`,
142
+ mock: false,
143
+ protocol: input.intent.protocol,
144
+ signature
145
+ };
146
+ },
147
+ transaction,
148
+ async verifyExecution(signature) {
149
+ const [report] = await verifier.assertBalanceChanges([
150
+ {
151
+ minIncreaseRaw: 1n,
152
+ snapshot: lpBalanceSnapshot
153
+ }
154
+ ]);
155
+ input.logger?.(`verified ${signature}: ${report.label} ${report.beforeUi} -> ${report.afterUi} (${report.deltaUi})`);
156
+ }
157
+ };
158
+ }
159
+ async function prepareLiveKamino(input) {
160
+ if (input.intent.protocol !== "kamino" ||
161
+ (input.intent.action !== "deposit" && input.intent.action !== "borrow")) {
162
+ return null;
163
+ }
164
+ if (!(0, env_1.isLiveKaminoEnabled)()) {
165
+ input.logger?.("live kamino disabled via ENABLE_LIVE_KAMINO");
166
+ return null;
167
+ }
168
+ const rpcUrl = (0, env_1.getRpcUrl)();
169
+ const cluster = (0, env_1.detectClusterFromRpcUrl)(rpcUrl);
170
+ const config = (0, kaminoLiveConfig_1.loadKaminoLiveConfig)();
171
+ if (config.cluster && cluster !== "unknown" && cluster !== config.cluster) {
172
+ throw new Error(`Kamino live config cluster=${config.cluster} does not match current RPC cluster=${cluster}. Check ${(0, env_1.getKaminoLiveConfigPath)()}.`);
173
+ }
174
+ const rpcClient = new RpcClient_1.RpcClient(rpcUrl, "confirmed");
175
+ const tokenService = new TokenService_1.TokenService(rpcClient);
176
+ const verifier = new PostTransactionVerifier_1.PostTransactionVerifier(rpcClient, tokenService);
177
+ const connection = new web3_js_1.Connection(rpcUrl, "confirmed");
178
+ const latestBlockhash = await connection.getLatestBlockhash("confirmed");
179
+ const configuredMarketAddress = new web3_js_1.PublicKey(config.marketAddress);
180
+ const configuredProgramId = new web3_js_1.PublicKey(config.programId);
181
+ const marketAccount = await rpcClient.getAccountInfo(configuredMarketAddress, "confirmed");
182
+ if (!marketAccount) {
183
+ throw new Error(`Kamino market ${config.marketAddress} does not exist on ${rpcUrl}. Update ${(0, env_1.getKaminoLiveConfigPath)()} with a valid market address for this cluster.`);
184
+ }
185
+ if (!marketAccount.owner.equals(configuredProgramId)) {
186
+ throw new Error(`Kamino market ${config.marketAddress} is owned by ${marketAccount.owner.toBase58()}, not Kamino program ${config.programId}. Update ${(0, env_1.getKaminoLiveConfigPath)()} with a valid market address for this cluster.`);
187
+ }
188
+ const ownerAddress = (0, kit_1.address)(input.walletManager.publicKey.toBase58());
189
+ const ownerSigner = (0, kit_1.createNoopSigner)(ownerAddress);
190
+ const programAddress = (0, kit_1.address)(config.programId);
191
+ const marketAddress = (0, kit_1.address)(config.marketAddress);
192
+ const obligationType = new klend_sdk_1.VanillaObligation(programAddress);
193
+ const market = await (0, loadKaminoMarketWithFallback_1.loadKaminoMarketWithFallback)({
194
+ cluster,
195
+ logger: input.logger,
196
+ marketAddress,
197
+ programAddress,
198
+ rpcUrl
199
+ });
200
+ if (input.intent.action === "deposit") {
201
+ const depositMint = (0, kit_1.address)(config.depositMint);
202
+ market.getExistingReserveByMint(depositMint, "configured deposit mint");
203
+ const beforeDeposit = await market.getObligationDepositByWallet(ownerAddress, depositMint, obligationType);
204
+ const action = await klend_sdk_1.KaminoAction.buildDepositTxns(market, config.actions.depositAmountRaw.toString(), depositMint, ownerSigner, obligationType, true, undefined, 0, true, false, {
205
+ skipInitialization: false,
206
+ skipLutCreation: true
207
+ });
208
+ return {
209
+ confirmationStrategy: {
210
+ blockhash: latestBlockhash.blockhash,
211
+ lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
212
+ signature: ""
213
+ },
214
+ protocol: input.intent.protocol,
215
+ policyConfigPatch: {
216
+ rules: {
217
+ allowedCloseAccountDestinations: [input.walletManager.publicKey.toBase58()],
218
+ allowOpaqueProgramIds: [config.programId],
219
+ allowedProgramIds: [config.programId]
220
+ }
221
+ },
222
+ toExecutionResult(signature) {
223
+ return {
224
+ action: input.intent.action,
225
+ memo: `LIVE:KAMINO:deposit:${config.marketAddress}:${config.depositMint}`,
226
+ mock: false,
227
+ protocol: input.intent.protocol,
228
+ signature
229
+ };
230
+ },
231
+ transaction: await buildSignedVersionedTransaction({
232
+ instructions: buildKaminoInstructions(action, cluster, input.logger),
233
+ payer: input.walletManager.publicKey,
234
+ recentBlockhash: latestBlockhash.blockhash,
235
+ walletManager: input.walletManager
236
+ }),
237
+ async verifyExecution(signature) {
238
+ const afterDeposit = await market.getObligationDepositByWallet(ownerAddress, depositMint, obligationType);
239
+ if (!afterDeposit.greaterThan(beforeDeposit)) {
240
+ throw new Error(`Kamino deposit verification failed: obligation deposit did not increase (${beforeDeposit.toString()} -> ${afterDeposit.toString()}).`);
241
+ }
242
+ input.logger?.(`verified ${signature}: Kamino obligation deposit ${beforeDeposit.toString()} -> ${afterDeposit.toString()} (${afterDeposit.minus(beforeDeposit).toString()})`);
243
+ }
244
+ };
245
+ }
246
+ const borrowMint = (0, kit_1.address)(config.borrowMint);
247
+ market.getExistingReserveByMint(borrowMint, "configured borrow mint");
248
+ const beforeBorrow = await market.getObligationBorrowByWallet(ownerAddress, borrowMint, obligationType);
249
+ const borrowSnapshot = await verifier.snapshotSplBalanceForOwner({
250
+ label: `Kamino borrowed token balance (${config.borrowMint})`,
251
+ mint: new web3_js_1.PublicKey(config.borrowMint),
252
+ owner: input.walletManager.publicKey
253
+ });
254
+ const action = await klend_sdk_1.KaminoAction.buildBorrowTxns(market, config.actions.borrowAmountRaw.toString(), borrowMint, ownerSigner, obligationType, true, undefined, 0, true, false, {
255
+ skipInitialization: false,
256
+ skipLutCreation: true
257
+ });
258
+ return {
259
+ confirmationStrategy: {
260
+ blockhash: latestBlockhash.blockhash,
261
+ lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
262
+ signature: ""
263
+ },
264
+ protocol: input.intent.protocol,
265
+ policyConfigPatch: {
266
+ rules: {
267
+ allowedCloseAccountDestinations: [input.walletManager.publicKey.toBase58()],
268
+ allowOpaqueProgramIds: [config.programId],
269
+ allowedProgramIds: [config.programId]
270
+ }
271
+ },
272
+ toExecutionResult(signature) {
273
+ return {
274
+ action: input.intent.action,
275
+ memo: `LIVE:KAMINO:borrow:${config.marketAddress}:${config.borrowMint}`,
276
+ mock: false,
277
+ protocol: input.intent.protocol,
278
+ signature
279
+ };
280
+ },
281
+ transaction: await buildSignedVersionedTransaction({
282
+ instructions: buildKaminoInstructions(action, cluster, input.logger),
283
+ payer: input.walletManager.publicKey,
284
+ recentBlockhash: latestBlockhash.blockhash,
285
+ walletManager: input.walletManager
286
+ }),
287
+ async verifyExecution(signature) {
288
+ const afterBorrow = await market.getObligationBorrowByWallet(ownerAddress, borrowMint, obligationType);
289
+ if (!afterBorrow.greaterThan(beforeBorrow)) {
290
+ throw new Error(`Kamino borrow verification failed: obligation borrow did not increase (${beforeBorrow.toString()} -> ${afterBorrow.toString()}).`);
291
+ }
292
+ const [report] = await verifier.assertBalanceChanges([
293
+ {
294
+ minIncreaseRaw: 1n,
295
+ snapshot: borrowSnapshot
296
+ }
297
+ ]);
298
+ input.logger?.(`verified ${signature}: ${report.label} ${report.beforeUi} -> ${report.afterUi} (${report.deltaUi}); obligation borrow ${beforeBorrow.toString()} -> ${afterBorrow.toString()}`);
299
+ }
300
+ };
301
+ }
302
+ async function prepareLiveMarinade(input) {
303
+ if (input.intent.protocol !== "marinade" || input.intent.action !== "stake") {
304
+ return null;
305
+ }
306
+ if (!(0, env_1.isLiveMarinadeEnabled)()) {
307
+ input.logger?.("live marinade disabled via ENABLE_LIVE_MARINADE");
308
+ return null;
309
+ }
310
+ const rpcUrl = (0, env_1.getRpcUrl)();
311
+ const cluster = (0, env_1.detectClusterFromRpcUrl)(rpcUrl);
312
+ if (cluster !== "devnet" && cluster !== "unknown") {
313
+ input.logger?.(`live marinade staking currently intended for devnet; current cluster=${cluster}`);
314
+ return null;
315
+ }
316
+ const rpcClient = new RpcClient_1.RpcClient(rpcUrl, "confirmed");
317
+ const tokenService = new TokenService_1.TokenService(rpcClient);
318
+ const verifier = new PostTransactionVerifier_1.PostTransactionVerifier(rpcClient, tokenService);
319
+ const connection = new web3_js_1.Connection(rpcUrl, "confirmed");
320
+ const latestBlockhash = await connection.getLatestBlockhash("confirmed");
321
+ const marinade = new marinade_ts_sdk_1.Marinade(new marinade_ts_sdk_1.MarinadeConfig({
322
+ connection,
323
+ publicKey: input.walletManager.publicKey
324
+ }));
325
+ const marinadeState = await marinade.getMarinadeState();
326
+ const msolSnapshot = await verifier.snapshotSplBalanceForOwner({
327
+ label: `Marinade mSOL balance (${marinadeState.mSolMintAddress.toBase58()})`,
328
+ mint: marinadeState.mSolMintAddress,
329
+ owner: input.walletManager.publicKey
330
+ });
331
+ const prepared = await marinade.deposit(new marinade_ts_sdk_1.BN(input.intent.amountLamports));
332
+ return {
333
+ confirmationStrategy: {
334
+ blockhash: latestBlockhash.blockhash,
335
+ lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
336
+ signature: ""
337
+ },
338
+ protocol: input.intent.protocol,
339
+ policyConfigPatch: {
340
+ rules: {
341
+ allowOpaqueProgramIds: [marinade.config.marinadeFinanceProgramId.toBase58()],
342
+ allowedProgramIds: [marinade.config.marinadeFinanceProgramId.toBase58()]
343
+ }
344
+ },
345
+ toExecutionResult(signature) {
346
+ return {
347
+ action: input.intent.action,
348
+ memo: `LIVE:MARINADE:stake:${input.intent.amountLamports}`,
349
+ mock: false,
350
+ protocol: input.intent.protocol,
351
+ signature
352
+ };
353
+ },
354
+ transaction: await buildSignedVersionedTransaction({
355
+ instructions: prepared.transaction.instructions,
356
+ payer: input.walletManager.publicKey,
357
+ recentBlockhash: latestBlockhash.blockhash,
358
+ walletManager: input.walletManager
359
+ }),
360
+ async verifyExecution(signature) {
361
+ const [report] = await verifier.assertBalanceChanges([
362
+ {
363
+ minIncreaseRaw: 1n,
364
+ snapshot: msolSnapshot
365
+ }
366
+ ]);
367
+ input.logger?.(`verified ${signature}: ${report.label} ${report.beforeUi} -> ${report.afterUi} (${report.deltaUi})`);
368
+ }
369
+ };
370
+ }
371
+ function buildVersionedTransaction(input) {
372
+ const message = new web3_js_1.TransactionMessage({
373
+ instructions: input.instructions,
374
+ payerKey: input.payer,
375
+ recentBlockhash: input.recentBlockhash
376
+ }).compileToV0Message();
377
+ return new web3_js_1.VersionedTransaction(message);
378
+ }
379
+ async function buildSignedVersionedTransaction(input) {
380
+ const transaction = buildVersionedTransaction(input);
381
+ return input.walletManager.signTransaction(transaction);
382
+ }
383
+ function buildKaminoInstructions(action, cluster, logger) {
384
+ const instructions = klend_sdk_1.KaminoAction.actionToIxs(action);
385
+ const labels = klend_sdk_1.KaminoAction.actionToIxLabels(action);
386
+ if (cluster !== "devnet") {
387
+ return instructions.map(kaminoInstructionCompat_1.convertKaminoInstruction);
388
+ }
389
+ const filtered = instructions.filter((_, index) => !labels[index]?.startsWith("RefreshReserve["));
390
+ if (filtered.length !== instructions.length) {
391
+ logger?.(`kamino devnet compatibility removed ${instructions.length - filtered.length} RefreshReserve instructions`);
392
+ }
393
+ return filtered.map(kaminoInstructionCompat_1.convertKaminoInstruction);
394
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });