$npx -y skills add keep-starknet-strange/starknet-agentic --skill starknet-defiExecute DeFi operations on Starknet including token swaps via avnu aggregator, DCA recurring buys, STRK staking, and lending/borrowing. Supports gasless transactions.
| 1 | # Starknet DeFi Skill |
| 2 | |
| 3 | Execute DeFi operations on Starknet using avnu aggregator and native protocols. |
| 4 | |
| 5 | ## When to Use |
| 6 | |
| 7 | - Swaps, DCA orders, staking, and lending or borrowing flows on Starknet. |
| 8 | - Agent workflows that need AVNU routing, paymaster support, or protocol-specific DeFi execution. |
| 9 | |
| 10 | ## When NOT to Use |
| 11 | |
| 12 | - Plain wallet management without DeFi intent. |
| 13 | - Cairo contract authoring, deployment operations, or security auditing. |
| 14 | |
| 15 | ## Quick Start |
| 16 | |
| 17 | 1. Install the AVNU + starknet.js dependencies and point the skill at a funded Starknet account. |
| 18 | 2. Use [skills catalog](../README.md) when the flow expands into wallet setup, deployment, or auditing. |
| 19 | |
| 20 | ## Prerequisites |
| 21 | |
| 22 | ```bash |
| 23 | npm install starknet@^8.9.1 @avnu/avnu-sdk@^4.0.1 |
| 24 | ``` |
| 25 | |
| 26 | ## Token Swaps (avnu SDK v4) |
| 27 | |
| 28 | ### Get Quote and Execute Swap |
| 29 | |
| 30 | ```typescript |
| 31 | import { getQuotes, executeSwap, type QuoteRequest } from "@avnu/avnu-sdk"; |
| 32 | import { Account, RpcProvider, ETransactionVersion } from "starknet"; |
| 33 | |
| 34 | const provider = new RpcProvider({ nodeUrl: process.env.STARKNET_RPC_URL }); |
| 35 | |
| 36 | // starknet.js v8: Account uses options object |
| 37 | const account = new Account({ |
| 38 | provider, |
| 39 | address, |
| 40 | signer: privateKey, |
| 41 | transactionVersion: ETransactionVersion.V3, |
| 42 | }); |
| 43 | |
| 44 | // Resolve token addresses via avnu SDK (or use MCP server's TokenService) |
| 45 | import { fetchVerifiedTokenBySymbol } from '@avnu/avnu-sdk'; |
| 46 | |
| 47 | const eth = await fetchVerifiedTokenBySymbol('ETH'); |
| 48 | const strk = await fetchVerifiedTokenBySymbol('STRK'); |
| 49 | |
| 50 | // SDK v4: getQuotes takes QuoteRequest object directly |
| 51 | const quoteParams: QuoteRequest = { |
| 52 | sellTokenAddress: eth.address, |
| 53 | buyTokenAddress: strk.address, |
| 54 | sellAmount: BigInt(10 ** 17), // 0.1 ETH |
| 55 | takerAddress: account.address, |
| 56 | }; |
| 57 | |
| 58 | const quotes = await getQuotes(quoteParams); |
| 59 | const bestQuote = quotes[0]; |
| 60 | |
| 61 | // SDK v4: executeSwap takes single object param |
| 62 | const result = await executeSwap({ |
| 63 | provider: account, |
| 64 | quote: bestQuote, |
| 65 | slippage: 0.01, // 1% |
| 66 | executeApprove: true, |
| 67 | }); |
| 68 | console.log("Tx:", result.transactionHash); |
| 69 | ``` |
| 70 | |
| 71 | ### Quote Response Fields (SDK v4) |
| 72 | |
| 73 | ```typescript |
| 74 | interface Quote { |
| 75 | quoteId: string; |
| 76 | sellTokenAddress: string; |
| 77 | buyTokenAddress: string; |
| 78 | sellAmount: bigint; |
| 79 | buyAmount: bigint; |
| 80 | sellAmountInUsd: number; |
| 81 | buyAmountInUsd: number; |
| 82 | priceImpact: number; // In basis points (15 = 0.15%) |
| 83 | gasFeesInUsd: number; |
| 84 | routes: Array<{ |
| 85 | name: string; // e.g., "Ekubo", "JediSwap" |
| 86 | percent: number; // e.g., 0.8 = 80% |
| 87 | }>; |
| 88 | fee: { |
| 89 | avnuFees: bigint; |
| 90 | integratorFees: bigint; |
| 91 | }; |
| 92 | } |
| 93 | ``` |
| 94 | |
| 95 | ### Build Swap Calls (for multicall composition) |
| 96 | |
| 97 | ```typescript |
| 98 | import { quoteToCalls } from "@avnu/avnu-sdk"; |
| 99 | |
| 100 | const calls = await quoteToCalls({ |
| 101 | quote: bestQuote, |
| 102 | takerAddress: account.address, |
| 103 | slippage: 0.01, |
| 104 | includeApprove: true, |
| 105 | }); |
| 106 | // `calls` can be combined with other calls in account.execute([...calls, ...otherCalls]) |
| 107 | ``` |
| 108 | |
| 109 | ### Gasless Swap (Pay Gas in Token) - SDK v4 + PaymasterRpc |
| 110 | |
| 111 | ```typescript |
| 112 | import { getQuotes, executeSwap } from "@avnu/avnu-sdk"; |
| 113 | import { PaymasterRpc } from "starknet"; |
| 114 | |
| 115 | const quotes = await getQuotes(quoteParams); |
| 116 | const bestQuote = quotes[0]; |
| 117 | |
| 118 | // SDK v4: Use PaymasterRpc from starknet.js |
| 119 | // Mainnet: https://starknet.paymaster.avnu.fi |
| 120 | // Sepolia: https://sepolia.paymaster.avnu.fi |
| 121 | const paymaster = new PaymasterRpc({ |
| 122 | nodeUrl: process.env.AVNU_PAYMASTER_URL || "https://starknet.paymaster.avnu.fi", |
| 123 | }); |
| 124 | |
| 125 | const result = await executeSwap({ |
| 126 | provider: account, |
| 127 | quote: bestQuote, |
| 128 | slippage: 0.01, |
| 129 | executeApprove: true, |
| 130 | paymaster: { |
| 131 | active: true, |
| 132 | provider: paymaster, |
| 133 | params: { |
| 134 | feeMode: { |
| 135 | mode: "default", |
| 136 | gasToken: "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", // USDC |
| 137 | }, |
| 138 | }, |
| 139 | }, |
| 140 | }); |
| 141 | ``` |
| 142 | |
| 143 | ## DCA (Dollar Cost Averaging) |
| 144 | |
| 145 | ### Create DCA Order |
| 146 | |
| 147 | ```typescript |
| 148 | import { executeCreateDca } from "@avnu/avnu-sdk"; |
| 149 | import moment from "moment"; |
| 150 | |
| 151 | const dcaOrder = { |
| 152 | sellTokenAddress: usdcAddress, |
| 153 | buyTokenAddress: strkAddress, |
| 154 | totalAmount: parseUnits("100", 6), // Total 100 USDC |
| 155 | numberOfOrders: 10, // Split into 10 orders |
| 156 | frequency: moment.duration(1, "day"), // moment.Duration object, not string |
| 157 | startAt: Math.floor(Date.now() / 1000), |
| 158 | }; |
| 159 | |
| 160 | const result = await executeCreateDca({ |
| 161 | provider: account, |
| 162 | order: dcaOrder, |
| 163 | }); |
| 164 | ``` |
| 165 | |
| 166 | ### Check and Cancel DCA |
| 167 | |
| 168 | ```typescript |
| 169 | import { getDcaOrders, executeCancelDca, DcaOrderStatus } from "@avnu/avnu-sdk"; |
| 170 | |
| 171 | const orders = await getDcaOrders({ |
| 172 | traderAddress: account.address, |
| 173 | stat |