@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,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeFiExecutor = void 0;
4
+ const PolicyGuard_1 = require("../policy/PolicyGuard");
5
+ const DeFiPolicyGuard_1 = require("./DeFiPolicyGuard");
6
+ class DeFiExecutor {
7
+ policy;
8
+ defiPolicyGuard;
9
+ policyGuard;
10
+ constructor(policy) {
11
+ this.policy = policy;
12
+ this.defiPolicyGuard = new DeFiPolicyGuard_1.DeFiPolicyGuard(policy);
13
+ this.policyGuard = new PolicyGuard_1.PolicyGuard(policy);
14
+ }
15
+ async executeIntent(input) {
16
+ this.defiPolicyGuard.validateIntent(input.intent);
17
+ const transaction = await input.koraSigner.buildMemoTransaction(input.walletManager, input.intent.memo);
18
+ this.policyGuard.validate(transaction);
19
+ const execution = await input.koraSigner.signAndSendGasless(transaction, input.intent.memo);
20
+ return {
21
+ action: input.intent.action,
22
+ memo: input.intent.memo,
23
+ mock: execution.mock,
24
+ protocol: input.intent.protocol,
25
+ signature: execution.signature
26
+ };
27
+ }
28
+ }
29
+ exports.DeFiExecutor = DeFiExecutor;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeFiPolicyGuard = void 0;
4
+ const errors_1 = require("../policy/errors");
5
+ class DeFiPolicyGuard {
6
+ policy;
7
+ constructor(policy) {
8
+ this.policy = policy;
9
+ }
10
+ validateIntent(intent) {
11
+ const protocolPolicy = this.policy.protocolPolicies[intent.protocol];
12
+ if (!protocolPolicy || !protocolPolicy.enabled) {
13
+ throw new errors_1.SecurityViolationError(`Protocol blocked: ${intent.protocol} is disabled.`);
14
+ }
15
+ if (!protocolPolicy.allowedMarkets.includes(intent.marketId)) {
16
+ throw new errors_1.SecurityViolationError(`Protocol blocked: market ${intent.marketId} is not approved for ${intent.protocol}.`);
17
+ }
18
+ if (intent.amountLamports > protocolPolicy.maxExposureLamports) {
19
+ throw new errors_1.SecurityViolationError(`Protocol blocked: amount ${intent.amountLamports} exceeds protocol exposure ${protocolPolicy.maxExposureLamports}.`);
20
+ }
21
+ if (intent.slippageBps > protocolPolicy.maxSlippageBps) {
22
+ throw new errors_1.SecurityViolationError(`Protocol blocked: slippage ${intent.slippageBps} exceeds max ${protocolPolicy.maxSlippageBps}.`);
23
+ }
24
+ if (protocolPolicy.minHealthFactor !== undefined &&
25
+ intent.expectedHealthFactor !== undefined &&
26
+ intent.expectedHealthFactor < protocolPolicy.minHealthFactor) {
27
+ throw new errors_1.SecurityViolationError(`Protocol blocked: health factor ${intent.expectedHealthFactor.toFixed(2)} is below minimum ${protocolPolicy.minHealthFactor.toFixed(2)}.`);
28
+ }
29
+ }
30
+ }
31
+ exports.DeFiPolicyGuard = DeFiPolicyGuard;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JupiterAdapter = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const protocols_1 = require("../protocols");
6
+ class JupiterAdapter {
7
+ protocol = "jupiter";
8
+ buildTradeIntent(snapshot) {
9
+ const solPriceUsd = snapshot.solPriceUsd ?? 0;
10
+ const buyThresholdUsd = snapshot.buyThresholdUsd ?? 0;
11
+ if (solPriceUsd <= 0 || buyThresholdUsd <= 0 || solPriceUsd > buyThresholdUsd) {
12
+ return null;
13
+ }
14
+ const amountLamports = Math.round(0.01 * web3_js_1.LAMPORTS_PER_SOL);
15
+ return {
16
+ action: "trade",
17
+ amountLamports,
18
+ marketId: protocols_1.PROTOCOL_PRESETS.jupiter.defaultMarketId,
19
+ memo: `DEFI_INTENT:JUPITER:trade:${amountLamports}`,
20
+ protocol: this.protocol,
21
+ slippageBps: 50
22
+ };
23
+ }
24
+ }
25
+ exports.JupiterAdapter = JupiterAdapter;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KaminoAdapter = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const protocols_1 = require("../protocols");
6
+ const USDC_ATOMIC = 1_000_000;
7
+ const MIN_BORROW_USDC_ATOMIC = 2 * USDC_ATOMIC;
8
+ const MIN_COLLATERAL_SOL_LAMPORTS = Math.round(0.75 * web3_js_1.LAMPORTS_PER_SOL);
9
+ class KaminoAdapter {
10
+ protocol = "kamino";
11
+ buildDepositIntent(snapshot) {
12
+ const idleUsdcAtomic = snapshot.idleUsdcAtomic ?? 0;
13
+ if (idleUsdcAtomic < 2 * USDC_ATOMIC) {
14
+ return null;
15
+ }
16
+ return {
17
+ action: "deposit",
18
+ amountLamports: Math.round(0.5 * web3_js_1.LAMPORTS_PER_SOL),
19
+ expectedHealthFactor: snapshot.healthFactor ?? 2,
20
+ marketId: protocols_1.PROTOCOL_PRESETS.kamino.defaultMarketId,
21
+ memo: "DEFI_INTENT:KAMINO:deposit:USDC",
22
+ protocol: this.protocol,
23
+ slippageBps: 40
24
+ };
25
+ }
26
+ buildBorrowIntent(snapshot) {
27
+ const borrowDemandUsdcAtomic = snapshot.borrowDemandUsdcAtomic ?? 0;
28
+ const collateralSolLamports = snapshot.collateralSolLamports ?? 0;
29
+ const expectedHealthFactor = snapshot.healthFactor ?? 0;
30
+ if (borrowDemandUsdcAtomic < MIN_BORROW_USDC_ATOMIC) {
31
+ return null;
32
+ }
33
+ if (collateralSolLamports < MIN_COLLATERAL_SOL_LAMPORTS) {
34
+ return null;
35
+ }
36
+ if (expectedHealthFactor < 2) {
37
+ return null;
38
+ }
39
+ return {
40
+ action: "borrow",
41
+ amountLamports: Math.round(0.25 * web3_js_1.LAMPORTS_PER_SOL),
42
+ expectedHealthFactor,
43
+ marketId: protocols_1.PROTOCOL_PRESETS.kamino.defaultMarketId,
44
+ memo: `DEFI_INTENT:KAMINO:borrow:USDC:${borrowDemandUsdcAtomic}`,
45
+ protocol: this.protocol,
46
+ slippageBps: 40
47
+ };
48
+ }
49
+ }
50
+ exports.KaminoAdapter = KaminoAdapter;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MarinadeAdapter = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const protocols_1 = require("../protocols");
6
+ class MarinadeAdapter {
7
+ protocol = "marinade";
8
+ buildStakeIntent(snapshot) {
9
+ const idleSolLamports = snapshot.idleSolLamports ?? 0;
10
+ const reserveLamports = Math.round(0.2 * web3_js_1.LAMPORTS_PER_SOL);
11
+ const amountLamports = Math.round(0.15 * web3_js_1.LAMPORTS_PER_SOL);
12
+ if (idleSolLamports <= reserveLamports + amountLamports) {
13
+ return null;
14
+ }
15
+ return {
16
+ action: "stake",
17
+ amountLamports,
18
+ marketId: protocols_1.PROTOCOL_PRESETS.marinade.defaultMarketId,
19
+ memo: `DEFI_INTENT:MARINADE:stake:${amountLamports}`,
20
+ protocol: this.protocol,
21
+ slippageBps: 25
22
+ };
23
+ }
24
+ }
25
+ exports.MarinadeAdapter = MarinadeAdapter;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RaydiumAdapter = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const RaydiumLpInstructionBuilder_1 = require("../lp/RaydiumLpInstructionBuilder");
6
+ const protocols_1 = require("../protocols");
7
+ class RaydiumAdapter {
8
+ protocol = "raydium";
9
+ lpInstructionBuilder = new RaydiumLpInstructionBuilder_1.RaydiumLpInstructionBuilder();
10
+ createDefaultPositionSettings() {
11
+ return {
12
+ harvestThresholdAtomic: 250_000,
13
+ maxCapitalLamports: Math.round(0.2 * web3_js_1.LAMPORTS_PER_SOL),
14
+ maxSlippageBps: 80,
15
+ poolId: protocols_1.PROTOCOL_PRESETS.raydium.defaultMarketId,
16
+ rebalanceOnOutOfRange: true,
17
+ tokenPair: "SOL/USDC"
18
+ };
19
+ }
20
+ buildAddLiquidityPlan(settings) {
21
+ const resolvedSettings = settings ?? this.createDefaultPositionSettings();
22
+ return this.lpInstructionBuilder.buildAddLiquidityPlan({
23
+ depositLamports: Math.round(0.12 * web3_js_1.LAMPORTS_PER_SOL),
24
+ settings: resolvedSettings
25
+ });
26
+ }
27
+ async buildAddLiquidityTransactionDraft(input) {
28
+ return this.lpInstructionBuilder.buildAddLiquidityTransactionDraft(input);
29
+ }
30
+ buildAddLiquidityIntent(snapshot, settings) {
31
+ if (!snapshot.liquidityInRange) {
32
+ return null;
33
+ }
34
+ const plan = this.buildAddLiquidityPlan(settings);
35
+ return {
36
+ action: plan.action,
37
+ amountLamports: plan.amountLamports,
38
+ marketId: plan.poolId,
39
+ memo: `DEFI_INTENT:RAYDIUM:${plan.action}:${plan.tokenPair}`,
40
+ protocol: this.protocol,
41
+ slippageBps: plan.slippageBps
42
+ };
43
+ }
44
+ }
45
+ exports.RaydiumAdapter = RaydiumAdapter;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertKaminoInstruction = convertKaminoInstruction;
4
+ const kit_1 = require("@solana/kit");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ function convertKaminoInstruction(instruction) {
7
+ return new web3_js_1.TransactionInstruction({
8
+ data: Buffer.from(instruction.data ?? new Uint8Array()),
9
+ keys: (instruction.accounts ?? []).map((account) => convertAccount(account)),
10
+ programId: new web3_js_1.PublicKey(instruction.programAddress)
11
+ });
12
+ }
13
+ function convertAccount(account) {
14
+ if ("lookupTableAddress" in account && account.lookupTableAddress) {
15
+ throw new Error(`Kamino instruction references lookup table ${account.lookupTableAddress}; lookup-table-backed Kamino transactions are not supported by this live path yet.`);
16
+ }
17
+ return {
18
+ isSigner: account.role === kit_1.AccountRole.READONLY_SIGNER ||
19
+ account.role === kit_1.AccountRole.WRITABLE_SIGNER,
20
+ isWritable: account.role === kit_1.AccountRole.WRITABLE ||
21
+ account.role === kit_1.AccountRole.WRITABLE_SIGNER,
22
+ pubkey: new web3_js_1.PublicKey(account.address)
23
+ };
24
+ }
@@ -0,0 +1,60 @@
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.loadKaminoLiveConfig = loadKaminoLiveConfig;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ const web3_js_1 = require("@solana/web3.js");
10
+ const env_1 = require("../../config/env");
11
+ function loadKaminoLiveConfig() {
12
+ const configPath = path_1.default.resolve(process.cwd(), (0, env_1.getKaminoLiveConfigPath)());
13
+ if (!(0, fs_1.existsSync)(configPath)) {
14
+ throw new Error(`Kamino live config not found at ${configPath}. Create kamino_live.json from kamino_live.example.json first.`);
15
+ }
16
+ const raw = (0, fs_1.readFileSync)(configPath, "utf8");
17
+ const parsed = JSON.parse(raw);
18
+ return {
19
+ actions: {
20
+ borrowAmountRaw: parsePositiveBigInt(parsed.actions?.borrowAmountRaw, "actions.borrowAmountRaw"),
21
+ depositAmountRaw: parsePositiveBigInt(parsed.actions?.depositAmountRaw, "actions.depositAmountRaw")
22
+ },
23
+ borrowMint: parsePublicKey(parsed.borrowMint, "borrowMint"),
24
+ cluster: parseOptionalCluster(parsed.cluster),
25
+ depositMint: parsePublicKey(parsed.depositMint, "depositMint"),
26
+ marketAddress: parsePublicKey(parsed.marketAddress, "marketAddress"),
27
+ programId: parsePublicKey(parsed.programId, "programId")
28
+ };
29
+ }
30
+ function parseOptionalCluster(value) {
31
+ if (value === undefined) {
32
+ return undefined;
33
+ }
34
+ if (value === "devnet" || value === "localnet" || value === "mainnet-beta") {
35
+ return value;
36
+ }
37
+ throw new Error("cluster must be one of 'devnet', 'localnet', or 'mainnet-beta'.");
38
+ }
39
+ function parsePositiveBigInt(value, field) {
40
+ if (typeof value === "number") {
41
+ if (!Number.isInteger(value) || value <= 0) {
42
+ throw new Error(`${field} must be a positive integer or digit string.`);
43
+ }
44
+ return BigInt(value);
45
+ }
46
+ if (typeof value === "string" && /^[0-9]+$/u.test(value)) {
47
+ const parsed = BigInt(value);
48
+ if (parsed <= 0n) {
49
+ throw new Error(`${field} must be greater than zero.`);
50
+ }
51
+ return parsed;
52
+ }
53
+ throw new Error(`${field} must be a positive integer or digit string.`);
54
+ }
55
+ function parsePublicKey(value, field) {
56
+ if (typeof value !== "string" || value.trim().length === 0) {
57
+ throw new Error(`${field} must be a base58 public key string.`);
58
+ }
59
+ return new web3_js_1.PublicKey(value).toBase58();
60
+ }
@@ -0,0 +1,68 @@
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.loadKaminoMarketWithFallback = loadKaminoMarketWithFallback;
7
+ const kit_1 = require("@solana/kit");
8
+ const klend_sdk_1 = require("@kamino-finance/klend-sdk");
9
+ const decimal_js_1 = __importDefault(require("decimal.js"));
10
+ const readCdnData_1 = require("@kamino-finance/klend-sdk/dist/utils/readCdnData");
11
+ async function loadKaminoMarketWithFallback(input) {
12
+ const rpc = (0, kit_1.createSolanaRpc)(input.rpcUrl);
13
+ if (input.cluster !== "devnet") {
14
+ const market = await klend_sdk_1.KaminoMarket.load(rpc, input.marketAddress, klend_sdk_1.DEFAULT_RECENT_SLOT_DURATION_MS, input.programAddress);
15
+ if (!market) {
16
+ throw new Error(`Kamino market ${input.marketAddress} could not be loaded from ${input.rpcUrl}.`);
17
+ }
18
+ return market;
19
+ }
20
+ input.logger?.("loading Kamino devnet market via reserve-state compatibility path (fallback reserve prices)");
21
+ const [marketState, reserveStates, cdnResourcesData] = await Promise.all([
22
+ klend_sdk_1.LendingMarket.fetch(rpc, input.marketAddress, input.programAddress),
23
+ (0, klend_sdk_1.getReserveStatesForMarket)(input.marketAddress, rpc, input.programAddress),
24
+ (0, readCdnData_1.fetchKaminoCdnData)()
25
+ ]);
26
+ if (!marketState) {
27
+ throw new Error(`Kamino market ${input.marketAddress} could not be loaded from ${input.rpcUrl}.`);
28
+ }
29
+ const mintAddresses = reserveStates.map((reserve) => reserve.state.liquidity.mintPubkey);
30
+ const mintAccounts = (await rpc.getMultipleAccounts(mintAddresses).send()).value;
31
+ const mintOwners = new Map();
32
+ mintAddresses.forEach((mintAddress, index) => {
33
+ const mintAccount = mintAccounts[index];
34
+ if (mintAccount) {
35
+ mintOwners.set(mintAddress, mintAccount.owner);
36
+ }
37
+ });
38
+ const reserves = new Map();
39
+ for (const reserveWithAddress of reserveStates) {
40
+ const normalizedReserveState = normalizeReserveTokenProgram(reserveWithAddress.state, mintOwners.get(reserveWithAddress.state.liquidity.mintPubkey));
41
+ const reserve = klend_sdk_1.KaminoReserve.initialize(reserveWithAddress.address, normalizedReserveState, createFallbackOracleData(normalizedReserveState), rpc, klend_sdk_1.DEFAULT_RECENT_SLOT_DURATION_MS, cdnResourcesData);
42
+ reserves.set(reserve.address, reserve);
43
+ }
44
+ return klend_sdk_1.KaminoMarket.loadWithReserves(rpc, marketState, reserves, input.marketAddress, klend_sdk_1.DEFAULT_RECENT_SLOT_DURATION_MS, input.programAddress);
45
+ }
46
+ function createFallbackOracleData(reserveState) {
47
+ const marketPrice = new klend_sdk_1.Fraction(reserveState.liquidity.marketPriceSf).toDecimal();
48
+ const price = marketPrice.greaterThan(0) ? marketPrice : new decimal_js_1.default(1);
49
+ return {
50
+ decimals: decimal_js_1.default.pow(10, reserveState.liquidity.mintDecimals.toString()),
51
+ mintAddress: reserveState.liquidity.mintPubkey,
52
+ price,
53
+ timestamp: BigInt(Math.floor(Date.now() / 1000)),
54
+ valid: true
55
+ };
56
+ }
57
+ function normalizeReserveTokenProgram(reserveState, mintOwner) {
58
+ if (!mintOwner || reserveState.liquidity.tokenProgram !== (0, kit_1.address)("11111111111111111111111111111111")) {
59
+ return reserveState;
60
+ }
61
+ return {
62
+ ...reserveState,
63
+ liquidity: {
64
+ ...reserveState.liquidity,
65
+ tokenProgram: mintOwner
66
+ }
67
+ };
68
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RaydiumLpInstructionBuilder = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const raydium_sdk_v2_1 = require("@raydium-io/raydium-sdk-v2");
6
+ const programs_1 = require("../../solana/programs");
7
+ class RaydiumLpInstructionBuilder {
8
+ buildAddLiquidityPlan(input) {
9
+ return {
10
+ action: "add_liquidity",
11
+ amountLamports: Math.min(input.depositLamports, input.settings.maxCapitalLamports),
12
+ operatorSummary: `Add liquidity on Raydium ${input.settings.tokenPair} with max slippage ${input.settings.maxSlippageBps} bps.`,
13
+ poolId: input.settings.poolId,
14
+ protocol: "raydium",
15
+ requiredAccounts: [
16
+ `${input.settings.poolId}:pool-state`,
17
+ `${input.settings.poolId}:lp-vault`,
18
+ `${input.settings.tokenPair}:token-a-ata`,
19
+ `${input.settings.tokenPair}:token-b-ata`
20
+ ],
21
+ slippageBps: input.settings.maxSlippageBps,
22
+ tokenPair: input.settings.tokenPair
23
+ };
24
+ }
25
+ async buildAddLiquidityTransactionDraft(input) {
26
+ const instruction = (0, raydium_sdk_v2_1.makeAddLiquidityInstruction)({
27
+ baseAmountIn: input.baseAmountIn,
28
+ fixedSide: input.fixedSide ?? "base",
29
+ otherAmountMin: input.otherAmountMin,
30
+ poolInfo: {
31
+ id: input.poolConfig.poolId,
32
+ lpMint: {
33
+ address: input.poolConfig.lpMint
34
+ },
35
+ marketId: input.poolConfig.marketId,
36
+ pooltype: [input.poolConfig.poolType],
37
+ programId: input.poolConfig.programId
38
+ },
39
+ poolKeys: {
40
+ authority: input.poolConfig.authority,
41
+ marketEventQueue: input.poolConfig.marketEventQueue,
42
+ openOrders: input.poolConfig.openOrders,
43
+ targetOrders: input.poolConfig.targetOrders,
44
+ vault: {
45
+ A: input.poolConfig.baseVault,
46
+ B: input.poolConfig.quoteVault
47
+ }
48
+ },
49
+ quoteAmountIn: input.quoteAmountIn,
50
+ userKeys: {
51
+ baseTokenAccount: new web3_js_1.PublicKey(input.userTokenAccounts.baseTokenAccount),
52
+ lpTokenAccount: new web3_js_1.PublicKey(input.userTokenAccounts.lpTokenAccount),
53
+ owner: input.owner.publicKey,
54
+ quoteTokenAccount: new web3_js_1.PublicKey(input.userTokenAccounts.quoteTokenAccount)
55
+ }
56
+ });
57
+ const message = new web3_js_1.TransactionMessage({
58
+ payerKey: input.owner.publicKey,
59
+ recentBlockhash: input.recentBlockhash ?? programs_1.MOCK_BLOCKHASH,
60
+ instructions: [instruction]
61
+ }).compileToV0Message();
62
+ const transaction = new web3_js_1.VersionedTransaction(message);
63
+ return input.owner.signTransaction(transaction);
64
+ }
65
+ buildHarvestFeesPlan(input) {
66
+ const rewards = input.snapshot.rewardsClaimableAtomic ?? 0;
67
+ if (rewards < input.settings.harvestThresholdAtomic) {
68
+ return null;
69
+ }
70
+ return {
71
+ action: "harvest",
72
+ amountLamports: 0,
73
+ operatorSummary: `Harvest accrued Raydium fees for ${input.settings.tokenPair}.`,
74
+ poolId: input.settings.poolId,
75
+ protocol: "raydium",
76
+ requiredAccounts: [
77
+ `${input.settings.poolId}:pool-state`,
78
+ `${input.settings.poolId}:fee-vault`
79
+ ],
80
+ slippageBps: 0,
81
+ tokenPair: input.settings.tokenPair
82
+ };
83
+ }
84
+ buildRemoveLiquidityPlan(input) {
85
+ return {
86
+ action: "remove_liquidity",
87
+ amountLamports: Math.min(input.withdrawLamports, input.settings.maxCapitalLamports),
88
+ operatorSummary: `Remove liquidity from Raydium ${input.settings.tokenPair}.`,
89
+ poolId: input.settings.poolId,
90
+ protocol: "raydium",
91
+ requiredAccounts: [
92
+ `${input.settings.poolId}:pool-state`,
93
+ `${input.settings.poolId}:lp-token-ata`
94
+ ],
95
+ slippageBps: input.settings.maxSlippageBps,
96
+ tokenPair: input.settings.tokenPair
97
+ };
98
+ }
99
+ }
100
+ exports.RaydiumLpInstructionBuilder = RaydiumLpInstructionBuilder;
@@ -0,0 +1,62 @@
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.loadRaydiumLpDevnetConfig = loadRaydiumLpDevnetConfig;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ const web3_js_1 = require("@solana/web3.js");
10
+ const env_1 = require("../../config/env");
11
+ function loadRaydiumLpDevnetConfig() {
12
+ const configPath = path_1.default.resolve(process.cwd(), (0, env_1.getRaydiumLpConfigPath)());
13
+ if (!(0, fs_1.existsSync)(configPath)) {
14
+ throw new Error(`Raydium LP config not found at ${configPath}. Create raydium_lp.devnet.json from the example file first.`);
15
+ }
16
+ const raw = (0, fs_1.readFileSync)(configPath, "utf8");
17
+ const parsed = JSON.parse(raw);
18
+ const config = {
19
+ amounts: {
20
+ baseAmountIn: parsePositiveInteger(parsed.amounts?.baseAmountIn, "amounts.baseAmountIn"),
21
+ otherAmountMin: parsePositiveInteger(parsed.amounts?.otherAmountMin, "amounts.otherAmountMin"),
22
+ quoteAmountIn: parsePositiveInteger(parsed.amounts?.quoteAmountIn, "amounts.quoteAmountIn")
23
+ },
24
+ poolConfig: {
25
+ authority: parsePublicKey(parsed.poolConfig?.authority, "poolConfig.authority"),
26
+ baseVault: parsePublicKey(parsed.poolConfig?.baseVault, "poolConfig.baseVault"),
27
+ lpMint: parsePublicKey(parsed.poolConfig?.lpMint, "poolConfig.lpMint"),
28
+ marketEventQueue: parsePublicKey(parsed.poolConfig?.marketEventQueue, "poolConfig.marketEventQueue"),
29
+ marketId: parsePublicKey(parsed.poolConfig?.marketId, "poolConfig.marketId"),
30
+ openOrders: parsePublicKey(parsed.poolConfig?.openOrders, "poolConfig.openOrders"),
31
+ poolId: parsePublicKey(parsed.poolConfig?.poolId, "poolConfig.poolId"),
32
+ poolType: parsePoolType(parsed.poolConfig?.poolType),
33
+ programId: parsePublicKey(parsed.poolConfig?.programId, "poolConfig.programId"),
34
+ quoteVault: parsePublicKey(parsed.poolConfig?.quoteVault, "poolConfig.quoteVault"),
35
+ targetOrders: parsePublicKey(parsed.poolConfig?.targetOrders, "poolConfig.targetOrders")
36
+ },
37
+ userTokenAccounts: {
38
+ baseTokenAccount: parsePublicKey(parsed.userTokenAccounts?.baseTokenAccount, "userTokenAccounts.baseTokenAccount"),
39
+ lpTokenAccount: parsePublicKey(parsed.userTokenAccounts?.lpTokenAccount, "userTokenAccounts.lpTokenAccount"),
40
+ quoteTokenAccount: parsePublicKey(parsed.userTokenAccounts?.quoteTokenAccount, "userTokenAccounts.quoteTokenAccount")
41
+ }
42
+ };
43
+ return config;
44
+ }
45
+ function parsePositiveInteger(value, field) {
46
+ if (!Number.isInteger(value) || value <= 0) {
47
+ throw new Error(`${field} must be a positive integer.`);
48
+ }
49
+ return value;
50
+ }
51
+ function parsePoolType(value) {
52
+ if (value === "Standard" || value === "StablePool") {
53
+ return value;
54
+ }
55
+ throw new Error("poolConfig.poolType must be either 'Standard' or 'StablePool'.");
56
+ }
57
+ function parsePublicKey(value, field) {
58
+ if (typeof value !== "string" || value.trim().length === 0) {
59
+ throw new Error(`${field} must be a base58 public key string.`);
60
+ }
61
+ return new web3_js_1.PublicKey(value).toBase58();
62
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PROTOCOL_PRESETS = void 0;
4
+ exports.PROTOCOL_PRESETS = {
5
+ jupiter: {
6
+ defaultMarketId: "sol-usdc",
7
+ description: "Spot swap routing for token rebalancing.",
8
+ label: "Jupiter",
9
+ protocol: "jupiter"
10
+ },
11
+ kamino: {
12
+ defaultMarketId: "main-usdc-vault",
13
+ description: "Yield and lending posture for idle stablecoin capital.",
14
+ label: "Kamino",
15
+ protocol: "kamino"
16
+ },
17
+ marinade: {
18
+ defaultMarketId: "primary-stake-pool",
19
+ description: "Liquid staking posture for idle SOL reserves.",
20
+ label: "Marinade",
21
+ protocol: "marinade"
22
+ },
23
+ raydium: {
24
+ defaultMarketId: "sol-usdc-core-pool",
25
+ description: "AMM liquidity posture for SOL/USDC LP management.",
26
+ label: "Raydium",
27
+ protocol: "raydium"
28
+ }
29
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });