First Strategy
StrategyEngine runs YAML-defined step graphs on top of DeFiRuntime.
Strategy YAML
Section titled “Strategy YAML”name: first-strategychain: solana-mainnetonError: pausesteps: - id: wait-window type: watch condition: type: time afterTimestamp: 1700000000 pollIntervalMs: 5000
- id: buy-sol type: action action: type: swap inputToken: USDC outputToken: SOL amount: "1000000" amountUsd: 1 slippageBps: 50Execute it
Section titled “Execute it”import { ConsoleLogger, DeFiRuntime, StrategyEngine, TypedEmitter, parseStrategyFromYaml, type RuntimeEvents,} from '@stendar/core';import { JupiterProvider } from '@stendar/provider-jupiter';import { SolanaChainAdapter } from '@stendar/solana';import { RawKeypairAdapter } from '@stendar/wallet-core';
const strategyYamlString = `name: first-strategychain: solana-mainnetonError: pausesteps: - id: wait-window type: watch condition: type: time afterTimestamp: 1700000000 pollIntervalMs: 5000 - id: buy-sol type: action action: type: swap inputToken: USDC outputToken: SOL amount: "1000000" amountUsd: 1 slippageBps: 50`;
process.loadEnvFile?.();
const rpcUrl = process.env.SOLANA_RPC_URL;const privateKey = process.env.WALLET_PRIVATE_KEY;if (!rpcUrl || !privateKey) { throw new Error('Missing SOLANA_RPC_URL or WALLET_PRIVATE_KEY');}
const runtime = new DeFiRuntime({ chains: [new SolanaChainAdapter({ rpcUrl })], providers: [new JupiterProvider()], wallet: new RawKeypairAdapter(privateKey), dryRun: true, logger: new ConsoleLogger({ component: 'first-strategy' }),});
const events = new TypedEmitter<RuntimeEvents>();// Strategy events (strategy:*) fire on this emitter.// Runtime events (tx:*, policy:*) fire on runtime.on() instead.events.on('strategy:step_started', ({ stepId }) => console.log('step', stepId));events.on('strategy:completed', ({ executionId }) => console.log('done', executionId));
await runtime.start();try { const strategy = parseStrategyFromYaml(strategyYamlString); const engine = new StrategyEngine(runtime, events, new ConsoleLogger({ component: 'engine' })); // Wait for strategy completion so runtime.stop() in finally does not race engine execution. const done = new Promise<void>((resolve) => events.on('strategy:completed', () => resolve())); const executionId = await engine.start(strategy); console.log('started', executionId); await done;} finally { await runtime.stop();}For strategy structure and step semantics, continue to Strategies concept.