# Altana Skills, full catalog > Every listed skill in full. 10 skills, each tested by Altana on a fork > of BNB mainnet before listing. Source of truth: https://raw.githubusercontent.com/altananetwork/skills/main/index.json > > Each section gives the canonical page, the raw markdown URL, the version, and the > sha256 of the markdown body that follows, so any reader can verify it independently. > Human catalog: https://skills.altana.network --- # PancakeSwap Trading - id: pancakeswap-trading - page: https://skills.altana.network/skill/pancakeswap-trading - source: https://skills.altana.network/skills/pancakeswap-trading/SKILL.md - chain: bnb - version: 1.0.0 - sha256: 8721c5294ac8e3475ab7b14c41f397061e9c4de550f86c5ec17a51da8db1f4d5 - verified: fork-tested by Altana on 2026-07-21 --- name: pancakeswap-trading description: Buy and sell tokens on PancakeSwap on BNB Chain through an Altana session. In and out of positions fast, with quotes, slippage protection, and full-balance exits. --- # PancakeSwap Trading Trade tokens on PancakeSwap V2 on BNB Chain as an Altana session. Submit onchain writes only through your Altana session executor (`execute(calls)` with the SDK, or the `session_execute` MCP tool). Reads can go directly against the RPC. ## Reference Everything you need to trade PancakeSwap well: the right contracts, quoting, token quirks, and safe slippage habits. ### Addresses (BNB Chain mainnet) | Contract | Address | |---|---| | PancakeSwap V2 Router | `0x10ED43C718714eb63d5aA57B78B54704E256024E` | | WBNB | `0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c` | | USDT (BSC-USD) | `0x55d398326f99059fF775485246999027B3197955` | ### Quirks that cause mistakes - USDT on BNB Chain has 18 decimals, not 6 like Ethereum. $20 is `20n * 10n**18n`. - The target token may have different decimals. Read `decimals()` before computing amounts. - Route selection: quote the direct pair AND the WBNB hop (`[USDT, WBNB, TOKEN]`) with `getAmountsOut`, then use whichever quotes better. Deep majors often have a direct USDT pool; most tokens only have a WBNB pool. - Approve before each swap direction: `approve(router, amount)` on the input token (USDT before buying, the token before selling back). - Fee-on-transfer tokens (transfer taxes) need the `swapExactTokensForTokensSupportingFeeOnTransferTokens` variant. Detect by simulating the standard swap first; if it reverts with sufficient allowance and balance, switch. ### Router functions (Uniswap V2 style) - Quote: `getAmountsOut(uint256 amountIn, address[] path) returns (uint256[])` - Swap: `swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] path, address to, uint256 deadline)` - `amountOutMin`: quote minus 1 to 3 percent slippage. Never 0. - `deadline`: unix seconds, now + 600. ## Playbook ### Play: enter-position Buy a token with USDT. Parameters: token address, USDT amount, slippage (default 1%). **Typical time:** ~15s 1. Read the token's `decimals()`. Quote both routes with `getAmountsOut`; pick the better. 2. `execute([approve(USDT, router, amount), swap(amount, quote minus slippage, path, wallet, now+600)])` 3. Verify the token balance increased before reporting success. ### Play: exit-position Sell part or all of a position back to USDT. Parameters: token address, amount or "all". **Typical time:** ~15s 1. For "all", read the live token balance and use the full amount. 2. Quote the reverse path. `execute([approve(TOKEN, router, amount), swap(...)])` 3. Verify USDT increased and the token balance decreased accordingly. ### Play: round-trip In and out in one move: buy, confirm, sell. Parameters: token, USDT amount, slippage. **Typical time:** ~50s including your own verification reads Write one script that quotes, buys, reads the received token balance in the same run, then approves and sells that exact balance back. One script, four transactions, no pauses between steps. Verify final balances onchain and report amounts and tx hashes. ### Play: tp-sl-watch Enter, then monitor and exit at take profit or stop loss. Parameters: token, amount, take-profit %, stop-loss %. **Typical time:** runs until an exit triggers 1. Run enter-position. Record the entry quote. 2. Loop: every few seconds re-quote the position's USDT value with `getAmountsOut`. 3. When value crosses take-profit or stop-loss, run exit-position with "all". 4. Report entry, exit, and realized result. Re-quote before exiting; never sell on a stale quote. ## Guards (do not remove) - `amountOutMin` is always a fresh quote minus slippage. Never 0. - Verify balances onchain after each leg; report only what the chain confirms. - If a swap reverts, requote once with +1% slippage and retry a single time; otherwise stop and report. Do not improvise outside the session scope. --- # Four.meme Trading - id: four-meme - page: https://skills.altana.network/skill/four-meme - source: https://skills.altana.network/skills/four-meme/SKILL.md - chain: bnb - version: 1.0.0 - sha256: c39a51afa14cee0ff6dac9803547641f07f3c58efc8bae9dc6ad5c3353e0070b - verified: fork-tested by Altana on 2026-07-21 --- name: four-meme description: Buy and sell memecoins on Four.meme bonding curves on BNB Chain through an Altana session. Quote with the helper, spend native BNB on the curve, check graduation, and hand off to PancakeSwap once a token graduates. --- # Four.meme Trading Trade memecoins on Four.meme, BNB Chain's dominant launchpad, as an Altana session. Tokens trade on a bonding curve inside TokenManager2 until they graduate to PancakeSwap. Submit onchain writes only through your Altana session executor (`execute(calls)` with the SDK, or the `session_execute` MCP tool). Reads, including every quote, can go directly against the RPC. ## Reference Everything you need to trade the curve well: the right contracts, how to quote, how buys spend native BNB, and how to tell when a token has graduated. ### Addresses (BNB Chain mainnet) | Contract | Address | |---|---| | TokenManager2 (curve, V2) | `0x5c952063c7fc8610FFDB798152D69F0B9550762b` | | TokenManagerHelper3 (quotes and status) | `0xF251F83e40a78868FcfA3FA4599Dad6494E46034` | | PancakeSwap V2 Router (after graduation) | `0x10ED43C718714eb63d5aA57B78B54704E256024E` | | WBNB | `0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c` | ### Quirks that cause mistakes - Curve buys spend native BNB as `msg.value`, not an ERC20. The session must be allowed to send native value to TokenManager2. Always size the value from a fresh quote, never from a guess. - The raised token is per token. For the common case it is native BNB, and `getTokenInfo` returns `quote` as the zero address. Some tokens raise in an ERC20 such as USD1. Read `tryBuy` first: if `amountMsgValue` is nonzero you send that as BNB value; if `amountApproval` is nonzero you approve that ERC20 to TokenManager2 and send zero value. - Selling returns BNB. Approve the token to TokenManager2 before selling, then call `sellToken`. Selling needs no native value. - Four.meme tokens use 18 decimals. - Graduation: `getTokenInfo` returns `liquidityAdded`. Once it is true the token has left the curve and trades on PancakeSwap V2. Curve buys and sells revert after graduation, so switch to the router. - Curve progress: compare `funds` to `maxFunds` (BNB raised so far against the graduation target), or `offers` to `maxOffers` (curve token supply). When funds reach the target the token graduates. - Some tokens are TaxTokens with their own transfer fees. The curve quote already includes the trading fee, but a token's transfer tax can still reduce what actually lands in the wallet, so verify the received balance rather than trusting the quote. ### Helper functions (reads, TokenManagerHelper3) - Status: `getTokenInfo(address token) returns (uint256 version, address tokenManager, address quote, uint256 lastPrice, uint256 tradingFeeRate, uint256 minTradingFee, uint256 launchTime, uint256 offers, uint256 maxOffers, uint256 funds, uint256 maxFunds, bool liquidityAdded)` - Buy quote: `tryBuy(address token, uint256 amount, uint256 funds) returns (address tokenManager, address quote, uint256 estimatedAmount, uint256 estimatedCost, uint256 estimatedFee, uint256 amountMsgValue, uint256 amountApproval, uint256 amountFunds)`. Pass `amount` = 0 and `funds` = the BNB you want to spend to quote by spend; `amountMsgValue` is the exact BNB value to send. - Sell quote: `trySell(address token, uint256 amount) returns (address tokenManager, address quote, uint256 funds, uint256 fee)`. `funds` is the BNB you would receive before your min. ### Curve functions (writes, TokenManager2) - Buy: `buyTokenAMAP(address token, uint256 funds, uint256 minAmount)` payable. `funds` is the BNB you spend, and you send it as value; `minAmount` is the buy quote's `estimatedAmount` minus 1 to 5 percent slippage. Never 0. - Sell: `sellToken(address token, uint256 amount, uint256 minFunds)`. `minFunds` is the sell quote's `funds` minus 1 to 5 percent slippage. Never 0. ## Playbook ### Play: check-curve-status Report where a token sits on the curve and whether it has graduated. Parameters: token address. **Typical time:** ~5s 1. Read `getTokenInfo(token)`. 2. If `liquidityAdded` is true, report graduated and point at PancakeSwap. 3. Otherwise report progress as `funds` against `maxFunds` and the last price. ### Play: buy-on-curve Buy a token on its bonding curve with BNB. Parameters: token address, BNB to spend, slippage (default 3%). **Typical time:** ~15s 1. Confirm the token has not graduated with `getTokenInfo`. 2. Quote with `tryBuy(token, 0, fundsToSpend)`. Read `amountMsgValue` and `estimatedAmount`. 3. `execute([{ to: TokenManager2, data: buyTokenAMAP(token, fundsToSpend, estimatedAmount minus slippage), value: amountMsgValue }])` 4. Verify the token balance increased before reporting success. ### Play: sell-on-curve Sell part or all of a curve position back to BNB. Parameters: token address, amount or "all". **Typical time:** ~15s 1. For "all", read the live token balance and use the full amount. 2. Quote with `trySell(token, amount)`. Read `funds`. 3. `execute([approve(token, TokenManager2, amount), sellToken(token, amount, funds minus slippage)])` 4. Verify the BNB balance increased and the token balance decreased. ### Play: round-trip In and out in one move: buy, confirm, sell. Parameters: token, BNB to spend, slippage. **Typical time:** ~50s including your own verification reads Write one script that quotes with `tryBuy`, buys with the returned `amountMsgValue` as value, reads the received token balance in the same run, then quotes with `trySell`, approves, and sells that exact balance back. One script, three transactions, no pauses between steps. Verify final balances onchain and report amounts and tx hashes. ### Play: graduation-handoff Trade a token that has already graduated. Parameters: token, side, amount. **Typical time:** ~15s 1. Read `getTokenInfo`. If `liquidityAdded` is true, the curve is closed. 2. Trade the token on PancakeSwap V2 through the router instead, quoting the `[WBNB, TOKEN]` path with `getAmountsOut`. See the pancakeswap-trading skill for the router playbook. 3. Never send curve calls for a graduated token; they revert. ## Guards (do not remove) - Size every buy's value and every sell's min from a fresh `tryBuy` or `trySell`. Never send a guessed native value, and never set `minAmount` or `minFunds` to 0. - Check `liquidityAdded` before any curve write. If it is true, hand off to PancakeSwap. - Verify balances onchain after each leg; report only what the chain confirms. - If a curve call reverts, requote once with 1 percent more slippage and retry a single time; otherwise stop and report. Do not improvise outside the session scope. --- # PancakeSwap Liquidity - id: pancakeswap-liquidity - page: https://skills.altana.network/skill/pancakeswap-liquidity - source: https://skills.altana.network/skills/pancakeswap-liquidity/SKILL.md - chain: bnb - version: 1.0.0 - sha256: 80d8bb4435689a2a696b22ebbf295c7f805c43f6287d1cd0c6e97951c3548b0f - verified: fork-tested by Altana on 2026-07-21 --- name: pancakeswap-liquidity description: Provide and withdraw liquidity on PancakeSwap V2 on BNB Chain through an Altana session. Pair two tokens at the pool ratio to mint LP tokens, check a position's share and underlying value, and burn LP back to both tokens. --- # PancakeSwap Liquidity Provide liquidity to PancakeSwap V2 pools on BNB Chain as an Altana session. You deposit two tokens at the pool's current ratio and receive an LP token; the LP token is the pair contract itself. Submit onchain writes only through your Altana session executor (`execute(calls)` with the SDK, or the `session_execute` MCP tool). Reads can go directly against the RPC. ## Reference Everything you need to add and remove liquidity well: the right contracts, how to size deposits to the live pool ratio, and the approvals each leg needs. ### Addresses (BNB Chain mainnet) | Contract | Address | |---|---| | PancakeSwap V2 Router | `0x10ED43C718714eb63d5aA57B78B54704E256024E` | | PancakeSwap V2 Factory | `0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73` | | WBNB | `0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c` | | USDT (BSC-USD) | `0x55d398326f99059fF775485246999027B3197955` | | USDT/WBNB pair (LP token) | `0x16b9a82891338f9bA80E2D6970FddA79D1eb0daE` | Find any other pair with `factory.getPair(tokenA, tokenB)`. The returned address is both the pool and the LP token you hold. ### Quirks that cause mistakes - Deposits must match the live pool ratio. Read `getReserves()` on the pair and size the second amount with `quote`: `amountBOptimal = amountA * reserveB / reserveA`. Send a desired amount that matches; the router pulls only what the ratio allows and refunds the rest, so any excess of one side sits idle. - `getReserves()` returns `(reserve0, reserve1, blockTimestampLast)` ordered by `token0` / `token1`, which are sorted by address, not by the order you pass. Check `token0()` on the pair to map reserves to tokens. For USDT/WBNB, `token0` is USDT. - USDT on BNB Chain has 18 decimals, not 6 like Ethereum. $20 is `20n * 10n**18n`. - Approve both input tokens to the router before `addLiquidity`. Approve the LP token (the pair) to the router before `removeLiquidity`; without it the burn reverts. - The min amounts guard against ratio drift between quoting and mining. Set `amountAMin` / `amountBMin` to a few percent under desired. Never 0. - `deadline`: unix seconds, now + 600. - Concentrated liquidity (PancakeSwap V3 and Infinity) is a different product with price ranges and NFT positions. It is not covered by this skill; this skill is V2 only. ### Router functions (Uniswap V2 style) - Add: `addLiquidity(address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline) returns (uint256 amountA, uint256 amountB, uint256 liquidity)` - Remove: `removeLiquidity(address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline) returns (uint256 amountA, uint256 amountB)` - Pair reads: `getReserves() returns (uint112, uint112, uint32)`, `totalSupply() returns (uint256)`, `balanceOf(address) returns (uint256)`, `token0()`, `token1()`. ## Playbook ### Play: add-liquidity Pair two tokens at the pool ratio and receive LP tokens. Parameters: tokenA, tokenB, amount of one side (the other is derived), slippage (default 1%). **Typical time:** ~15s 1. Resolve the pair with `factory.getPair(tokenA, tokenB)`. Read `token0()` and `getReserves()` to map reserves to your tokens. 2. Pick the amount of one side. Derive the other with `amountBDesired = amountA * reserveB / reserveA`. Set each min to desired minus slippage. 3. `execute([approve(tokenA, router, amountADesired), approve(tokenB, router, amountBDesired), addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin, wallet, now+600)])` 4. Verify the LP token balance (`pair.balanceOf(wallet)`) increased before reporting success. ### Play: remove-liquidity Burn LP tokens back to both underlying tokens, full or partial. Parameters: pair (or the two tokens), amount of LP or "all". **Typical time:** ~15s 1. For "all", read the live LP balance (`pair.balanceOf(wallet)`) and use the full amount. 2. Estimate the tokens you should get back from your share: `reserveX * liquidity / totalSupply` for each side. Set `amountAMin` / `amountBMin` to a few percent under those estimates. 3. `execute([approve(pair, router, liquidity), removeLiquidity(tokenA, tokenB, liquidity, amountAMin, amountBMin, wallet, now+600)])` 4. Verify both token balances increased and the LP balance dropped by the burned amount. ### Play: position-check Report a position's size without changing anything. Parameters: pair (or the two tokens). **Typical time:** ~5s, reads only 1. Read `pair.balanceOf(wallet)` (your LP), `pair.totalSupply()` (all LP), and `pair.getReserves()`. 2. Your pool share is `balanceOf / totalSupply`. Your underlying is `reserveX * balanceOf / totalSupply` for each token. 3. Report the LP balance, the share as a percent, and the two underlying amounts. No session write is needed for a check. ## Guards (do not remove) - `amountAMin` / `amountBMin` are always desired minus slippage, never 0. - Size the second deposit from a fresh `getReserves` read; never assume a 50/50 or a stale ratio. - Verify balances onchain after each leg; report only what the chain confirms. - Approve the LP token to the router before removing; the burn reverts otherwise. - This skill is PancakeSwap V2 only. Do not improvise V3 or Infinity concentrated positions, and do not act outside the session scope. --- # Copy Trade - id: copy-trade - page: https://skills.altana.network/skill/copy-trade - source: https://skills.altana.network/skills/copy-trade/SKILL.md - chain: bnb - version: 1.1.0 - sha256: d5458abd494a096f4ba208e7e534259fffdd1b5351a37130ec634514e18d1e37 - verified: fork-tested by Altana on 2026-07-21 --- name: copy-trade description: Mirror a chosen wallet's PancakeSwap trades under hard session caps. Watch a leader onchain, screen what it buys, and copy buys and sells sized to your own per-trade and total budget, never more. --- # Copy Trade Follow one wallet (the leader) and mirror its PancakeSwap V2 trades with your own money, under a session budget it cannot make you exceed. The person running this skill names the leader wallet. You never choose it and never guess it: with no address given, there is nothing to copy, so ask for one before anything else. This skill composes two capabilities you already have: detection (reading the leader's trades from public RPC logs) and execution (the same PancakeSwap trading session as the `pancakeswap-trading` skill). You never hand the leader your keys. Your worst case is bounded by the session cap, and that bound is the whole point. Submit onchain writes only through your Altana session executor (`execute(calls)` with the SDK, or the `session_execute` MCP tool). All detection reads go directly against the RPC. ## Reference ### Addresses (BNB Chain mainnet) | Contract | Address | |---|---| | PancakeSwap V2 Router | `0x10ED43C718714eb63d5aA57B78B54704E256024E` | | PancakeSwap V2 Factory | `0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73` | | WBNB | `0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c` | | USDT (BSC-USD) | `0x55d398326f99059fF775485246999027B3197955` | ### Detecting the leader's trades (reads only) A PancakeSwap V2 pair emits on every swap: ``` event Swap(address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to) ``` - `to` (topic 2) is the trade recipient. On the final hop of the leader's buy or sell, `to` is the leader. Filter `getLogs` for this event with topic 2 set to the leader address to find every trade that paid out to it. - Which token did the leader receive? Read the emitting pair's `token0()` and `token1()`. The side with a non-zero `amountOut` is the token that flowed to the leader. If that token is not USDT and not WBNB, the leader just bought it. If the token out is USDT or WBNB, the leader was selling something back. - Track ERC-20 `Transfer(from, to, value)` logs with topic 2 set to the leader to confirm the size and token of what it received, independent of the router path. - Poll `getLogs` from the last block you checked forward. Never act on a log you have not decoded down to a concrete token address and amount. ### Sizing a mirror - Read the input token's `decimals()` and the mirror token's `decimals()` before computing any amount. USDT on BNB Chain has 18 decimals, not 6. - Mirror size is `min(leader-proportional size, per-trade max, budget remaining)`. Leader-proportional means: match the fraction of its own USDT balance the leader spent, applied to your budget. When in doubt, the per-trade max wins. - Quote before every trade with the router's `getAmountsOut(uint256 amountIn, address[] path)`. Try the direct USDT pair and the WBNB hop (`[USDT, WBNB, TOKEN]`); use whichever quotes better. - `swapExactTokensForTokens(amountIn, amountOutMin, path, to, deadline)` with `amountOutMin` set to the fresh quote minus 1 to 3 percent slippage, never 0. `deadline` is now + 600 seconds. Approve the input token to the router first. ## Playbook ### Play: follow Mirror the leader's buys under caps. Parameters: leader wallet (required), per-trade max (USDT, required), total budget (USDT, required), optional token screen. **Typical time:** runs until the budget is spent or you stop it 1. Confirm you were given an explicit leader wallet address, a per-trade max, and a total budget. If any of the three is missing, stop and ask for it. Do not start the loop on a partial set. 2. Record the current block as your watermark and read your starting USDT balance. The total budget is a hard ceiling on cumulative USDT spent across all mirrors. 3. Loop: poll `getLogs` for pair `Swap` events with topic 2 = the leader, from the watermark forward. Decode each into (token, side, amount) and advance the watermark. 4. For each new leader buy: screen the token first. Recommended: run the `dexscreener-token-radar` skill's `token-screen` play on the token address. If it fails the liquidity screen (thin pool, honeypot shape, unknown to both sources), skip it and log why. Do not mirror it. 5. Size the mirror as `min(leader proportion, per-trade max, budget remaining)`. Quote, then `execute([approve(USDT, router, size), swap(size, quote minus slippage, path, wallet, now+600)])`. 6. Verify your token balance increased onchain. Report the mirror: the leader's tx hash you acted on, your tx hash, the token, and the amounts on both sides. 7. Repeat until the budget is exhausted. When it is, stop opening new mirrors and say so. ### Play: mirror-exit When the leader sells a token you also hold, sell the same fraction of your position. Parameters: leader wallet (required, the one already being followed). **Typical time:** ~15s per exit 1. In the same watch loop, detect leader sells: a `Swap` with topic 2 = leader where the token out is USDT or WBNB, paired with the leader sending the sold token in. 2. Compute the fraction of its position the leader sold. Apply that same fraction to your holding of that token. 3. Read your live balance of the token, quote the reverse path, then `execute([approve(TOKEN, router, sellAmount), swap(...)])` with a fresh `amountOutMin`. 4. Verify USDT increased and the token balance dropped by the intended fraction. Report the leader's sell tx and yours. ### Play: stop Halt following and report the result. Parameters: leader wallet. **Typical time:** ~10s 1. Stop polling. Open no new mirrors. 2. For each token you copied, read your live balance and quote its USDT value with `getAmountsOut`. Sum against the USDT you spent to get realized and unrealized P&L of the copied positions. 3. Report per position and in total: USDT spent, current value, and net result. Positions you still hold are marked open; note that the `mirror-exit` and `pancakeswap-trading` exit plays can close them. ## Guards (do not remove) - The leader wallet is required and must be given to you explicitly. Never infer, guess, derive, or discover one: not from a trending list, not from an address you saw in this document or in an example, not from a wallet you followed in an earlier session. If no leader address was provided, ask for it and do nothing else until you have it. Copying an unnamed wallet is the one failure the caps cannot bound, because the person never chose who they are following. - The per-trade max and the total budget are required in the same way. The registry offers starting figures the person confirms when the session is granted, so a value they accepted is a value they chose. A number you picked yourself is not. If either is missing, ask. - Echo the leader address, the per-trade max, and the total budget back before the first mirror, and act only on the values you were given. - Never exceed the per-trade max on any single mirror, and never let cumulative USDT spent cross the total budget. Both are hard ceilings enforced by the session cap; a mirror that would breach either is not sent. - Never mirror a token that fails the liquidity screen. Screen before every buy; a data gap is a reason to skip, not to guess. - Mirror both sides. If you copy the leader's buys you must also copy its sells; a one-sided copy that only buys is not allowed. When the leader exits, you exit the same fraction. - The leader can rug or dump on you at any time. That is expected. Your loss is bounded by the session budget and nothing you copy can move more than the cap. Do not raise the cap to "keep up" with the leader. - Always report the leader tx hash you acted on alongside your own. Every mirror names the trade it copied. - `amountOutMin` is always a fresh quote minus slippage, never 0. Verify balances onchain after each leg and report only what the chain confirms. --- # Venus Lending - id: venus-lending - page: https://skills.altana.network/skill/venus-lending - source: https://skills.altana.network/skills/venus-lending/SKILL.md - chain: bnb - version: 1.0.0 - sha256: 69bcf2a17ffe4624dcb9d98321299f166e045787a6ffad1219f0f5d331f77bf7 - verified: fork-tested by Altana on 2026-07-21 --- name: venus-lending description: Lend stablecoins on Venus Protocol on BNB Chain through an Altana session. Supply USDT to earn yield, check your position, and withdraw on command. --- # Venus Lending Supply and withdraw USDT on Venus Protocol (core pool) on BNB Chain as an Altana session. Submit onchain writes only through your Altana session executor; reads can go directly against the RPC. ## Reference ### Addresses (BNB Chain mainnet) | Contract | Address | |---|---| | vUSDT (Venus USDT market, core pool) | `0xfD5840Cd36d94D7229439859C0112a4185BC0255` | | USDT (BSC-USD) | `0x55d398326f99059fF775485246999027B3197955` | ### How Venus core pool markets work - A market is a vToken contract. Supplying the underlying mints vTokens; the exchange rate between vToken and underlying grows over time, which is how interest accrues. - Supply: `approve(vUSDT, amount)` on USDT, then `vUSDT.mint(uint256 amount)`. `mint` returns 0 on success (Compound-style error codes, it does not revert on some failures). Always verify by reading balances after. - Withdraw by underlying amount: `vUSDT.redeemUnderlying(uint256 amount)`; withdraw everything: `vUSDT.redeem(uint256 vTokenAmount)` with your full vToken balance. - Position value: `balanceOfUnderlying(address)` (non-view, call it with a static call) or `balanceOf(address)` times `exchangeRateStored()` divided by 1e18. - USDT has 18 decimals on BNB Chain. vUSDT has 8 decimals. ### Quirks that cause mistakes - Compound-style calls return error codes instead of reverting. A transaction can succeed while the operation failed. Verify the vToken balance actually changed. - `balanceOfUnderlying` is not a view function; use a static call to read it. - Redeeming can fail if the market lacks liquidity; check `getCash()` first for large amounts. ## Playbook ### Play: supply Lend USDT to earn yield. Parameters: USDT amount. **Typical time:** ~15s 1. `execute([approve(USDT, vUSDT, amount), vUSDT.mint(amount)])` 2. Verify vUSDT balance increased and USDT decreased by the amount. Report the position value via a static call to `balanceOfUnderlying`. ### Play: withdraw Withdraw part or all of the position. Parameters: amount or "all". **Typical time:** ~15s 1. For a partial amount: `execute([vUSDT.redeemUnderlying(amount)])`. For "all": read `balanceOf(wallet)` on vUSDT and `execute([vUSDT.redeem(fullVTokenBalance)])`. 2. Verify USDT increased and vUSDT decreased. Report amounts and tx hashes. ### Play: position-check Read-only status. No transaction. Parameters: none. **Typical time:** ~5s Static-call `balanceOfUnderlying(wallet)`, read `exchangeRateStored` and the current supply rate `supplyRatePerBlock()`, and report the position value and approximate APY (rate per block times blocks per year, about 10.5M on BNB Chain). ## Guards (do not remove) - After every mint or redeem, verify balances changed as expected; success of the transaction alone does not mean the operation succeeded. - Never approve more than the amount being supplied in this action. - If a redeem fails, check `getCash()` and report the market liquidity rather than retrying blindly. --- # x402 API Payments - id: x402-payments - page: https://skills.altana.network/skill/x402-payments - source: https://skills.altana.network/skills/x402-payments/SKILL.md - chain: multi - version: 1.0.0 - sha256: 8250aae2d2ba2ce1320e5fc1b48e6389e5751b197e787c3e65199143b9fb75b7 - verified: fork-tested by Altana on 2026-07-21 --- name: x402-payments description: Pay for APIs and services over HTTP with the x402 protocol from an Altana session. Per-use payments in stablecoins, no accounts or cards, spend-capped and revocable. --- # x402 API Payments Pay for HTTP resources that respond with `402 Payment Required` using the x402 protocol, from an Altana session wallet. Works for paid APIs, data feeds, and agent to agent services (including Binance's B402 marketplace on BNB Chain). ## Reference ### How x402 works 1. You request a resource; the server responds `402` with payment requirements (`accepts` list: scheme, network, asset, amount, receiver). 2. You sign a payment authorization with your wallet (no onchain transaction from you; the facilitator settles it) and retry the request with the `X-PAYMENT` header. 3. The server verifies, settles, and returns the resource plus a settlement receipt. ### With the Altana SDK `fetchWithX402(session, url, init?)` from `@altananetwork/sdk` does the whole loop: fetches, reads requirements, signs with the session, retries, and returns the final response. In an MCP host, the `x402_request` tool does the same. ### Quirks that matter - Amounts are in the asset's smallest unit; USDT on BNB Chain has 18 decimals. - The session signs with ERC-1271 through the smart account: the paying wallet is the smart account address, not the session key address. - Rails on BNB Chain use Permit2 with USDT. The wallet needs a one-time USDT approval to Permit2, which the SDK handles on first payment. - Payments count against the session's spend cap like any other outflow, and the session must not be expired. ## Playbook ### Play: pay-once Fetch one paid resource. Parameters: URL, maximum acceptable price. **Typical time:** ~10s 1. Call `fetchWithX402(session, url)`. 2. Before signing, compare the server's asked amount with the maximum price parameter; refuse and report if it asks for more. 3. Return the response body and the settlement receipt (tx hash if provided). ### Play: auto-refill Keep a metered service topped up. Parameters: URL, per-payment maximum, total budget. **Typical time:** runs until budget is spent Loop pay-once against the service's top-up endpoint whenever its balance endpoint reports low credit. Stop when the total budget parameter is spent, and report each payment as it happens. ## Guards (do not remove) - Always enforce the maximum price parameter; never sign an authorization above it. - Track cumulative spend across the run and stop at the stated budget. - Only pay endpoints the user named. Never follow a 402 from a redirect to a different host without reporting first. --- # Lista Liquid Staking - id: lista-staking - page: https://skills.altana.network/skill/lista-staking - source: https://skills.altana.network/skills/lista-staking/SKILL.md - chain: bnb - version: 1.0.0 - sha256: 67f15a40d3b2cf09a7317ca0a9e3a07dab083001cc17a999c46764cf1406e5ac - verified: fork-tested by Altana on 2026-07-21 --- name: lista-staking description: Liquid stake BNB on Lista DAO through an Altana session. Deposit native BNB to receive slisBNB, check your position and the exchange rate, and run the two-step async withdrawal (request now, claim after the unbonding period). --- # Lista Liquid Staking Liquid stake BNB with Lista DAO on BNB Chain as an Altana session. Deposit native BNB into the ListaStakeManager and receive slisBNB, a reward-bearing token whose value in BNB grows over time. Submit onchain writes only through your Altana session executor (`execute(calls)` with the SDK, or the `session_execute` MCP tool). Reads, including the exchange rate and your withdrawal requests, can go directly against the RPC. ## Reference ### Addresses (BNB Chain mainnet) | Contract | Address | |---|---| | ListaStakeManager (deposit BNB, get slisBNB) | `0x1adB950d8bB3dA4bE104211D5AB038628e477fE6` | | slisBNB (Staked Lista BNB) | `0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B` | ### How Lista liquid staking works - Staking is a native BNB deposit: call `deposit()` payable on the ListaStakeManager with the BNB you want to stake as `msg.value`. The manager mints slisBNB to your wallet. The session must be allowed to send native value to the manager. - slisBNB is reward-bearing, not rebasing: your balance stays fixed and each slisBNB is worth more BNB over time. One slisBNB is worth more than one BNB, so a deposit of 1 BNB mints fewer than 1 slisBNB. Read the rate before staking; never assume 1:1. - Exchange rate reads on the manager: - `convertBnbToSnBnb(uint256 bnbAmount) view returns (uint256)` is the slisBNB you receive for a given BNB deposit. - `convertSnBnbToBnb(uint256 slisBnbAmount) view returns (uint256)` is the BNB a given slisBNB balance is currently worth. - Withdrawing is asynchronous and two-step (see the quirks below). - slisBNB has 18 decimals. BNB is native (18 decimals). ### Withdrawal flow (two steps, with an unbonding wait between) You cannot swap slisBNB back to BNB on the manager in one call. The flow mirrors BNB Chain native unstaking: 1. `requestWithdraw(uint256 amountInSlisBnb)` burns/escrows that slisBNB and records a pending withdrawal request against your address. This transfers slisBNB from your wallet into the manager, so you must `approve(manager, amountInSlisBnb)` on slisBNB first. 2. Wait out the unbonding period (the BNB staking cooldown, roughly 7 to 15 days). The request is not claimable until it elapses. 3. `claimWithdraw(uint256 index)` pays out the BNB for a matured request. `index` is the position in your request list. Because the cooldown spans days, a stake and its claim never happen in one session. Stake and request are immediate; the claim is a separate later action. ### Withdrawal reads (manager) - `getUserWithdrawalRequests(address user) view returns ((uint256 uuid, uint256 amountInSnBnb, uint256 startTime)[])` is the list of your pending requests. Each entry carries a `uuid`, the `amountInSnBnb` (slisBNB) requested, and the `startTime`. A fresh entry appears here the moment `requestWithdraw` lands. - `getUserRequestStatus(address user, uint256 index) view returns (bool isClaimable, uint256 amount)` tells you whether request `index` has matured (`isClaimable`) and the BNB `amount` it will pay. It reverts with "Invalid index" if the request does not exist. Poll this and only call `claimWithdraw(index)` once `isClaimable` is true. ### Quirks that cause mistakes - Stake spends native BNB as `msg.value` on `deposit()`, not an ERC20. Size the value from the amount you intend to stake, and expect slisBNB back at the current rate, which is less than the BNB sent because slisBNB is worth more than BNB. - `requestWithdraw` pulls slisBNB via `transferFrom`. Without a prior slisBNB approve to the manager it reverts with "ERC20: insufficient allowance". Approve exactly the amount you are requesting. - The claim is gated by the unbonding period. Right after a request, `getUserRequestStatus` returns `isClaimable = false`. Do not call `claimWithdraw` until it flips true, or the claim reverts. - Verify the slisBNB received (stake) and the request recorded (withdraw) by reading onchain state; do not trust the amount you sent. ## Playbook ### Play: stake Liquid stake BNB and receive slisBNB. Parameters: BNB amount. **Typical time:** ~15s 1. Read `convertBnbToSnBnb(bnbAmount)` on the manager for the expected slisBNB out. 2. `execute([{ to: ListaStakeManager, data: deposit(), value: bnbAmount }])` 3. Verify the slisBNB balance increased by roughly the expected amount and report the slisBNB received and the tx hash. ### Play: unstake-request Start an async withdrawal of a slisBNB amount back to BNB. Parameters: slisBNB amount or "all". **Typical time:** ~15s 1. For "all", read the live slisBNB `balanceOf(wallet)` and use the full balance. 2. `execute([approve(slisBNB, ListaStakeManager, amount), requestWithdraw(amount)])` 3. Verify the slisBNB balance dropped by the amount and read `getUserWithdrawalRequests(wallet)` to confirm a new request is recorded. Report the request index and that the BNB becomes claimable after the unbonding period (roughly 7 to 15 days). Do not attempt to claim in this run. ### Play: claim (after the unbonding period) Claim a matured withdrawal request. Parameters: request index (default 0). Run this only days after `unstake-request`, once the cooldown has elapsed. **Typical time:** ~15s 1. Read `getUserRequestStatus(wallet, index)`. If `isClaimable` is false, report that the request has not matured and stop; do not send a claim. 2. If true, `execute([{ to: ListaStakeManager, data: claimWithdraw(index) }])`. 3. Verify the native BNB balance increased by about the status `amount` and report the BNB claimed and the tx hash. ### Play: position-check Read-only status. No transaction. Parameters: none. **Typical time:** ~5s Read slisBNB `balanceOf(wallet)`, convert it to BNB with `convertSnBnbToBnb(balance)` for the position value, and read `getUserWithdrawalRequests(wallet)` for any pending withdrawals. Report the slisBNB held, its current BNB value, and the state of any pending requests. ## Guards (do not remove) - Size the stake value from the BNB you intend to stake and expect less slisBNB back; never assume a 1:1 rate. Read `convertBnbToSnBnb` first. - Before `requestWithdraw`, approve exactly the slisBNB amount being requested to the manager, never more. - Never call `claimWithdraw` until `getUserRequestStatus` reports the request claimable; an early claim reverts. - Verify onchain state after each leg (slisBNB balance for a stake, the recorded request for a withdrawal, native BNB for a claim); report only what the chain confirms. --- # Aave V3 Lending - id: aave-v3-lending - page: https://skills.altana.network/skill/aave-v3-lending - source: https://skills.altana.network/skills/aave-v3-lending/SKILL.md - chain: bnb - version: 1.0.0 - sha256: 20416c8f288207d32abc6217b5cf7ef239d4fa80e1cbbe8184e5d4c892a82f81 - verified: fork-tested by Altana on 2026-07-21 --- name: aave-v3-lending description: Lend stablecoins on Aave V3 on BNB Chain through an Altana session. Supply USDT to earn yield, check your position, and withdraw on command. Supply and withdraw only, no borrowing. --- # Aave V3 Lending Supply and withdraw USDT on the Aave V3 market on BNB Chain as an Altana session. This skill covers supply and withdraw only; it does not cover borrowing. Submit onchain writes only through your Altana session executor; reads can go directly against the RPC. ## Reference ### Addresses (BNB Chain mainnet) | Contract | Address | |---|---| | Aave V3 Pool | `0x6807dc923806fE8Fd134338EABCA509979a7e0cB` | | aBnbUSDT (Aave USDT aToken) | `0xa9251ca9DE909CB71783723713B21E4233fbf1B1` | | USDT (BSC-USD) | `0x55d398326f99059fF775485246999027B3197955` | The Pool and aToken were confirmed against BNB mainnet: the Pool reports `POOL_REVISION` 11 and the official Aave addresses provider `0xff75B6da14FfbbfD355Daf7a2731456b3562Ba6D`. The aToken address is what the Pool itself returns from `getReserveData(USDT)`; that token reports symbol `aBnbUSDT` and `UNDERLYING_ASSET_ADDRESS` equal to USDT. ### How Aave V3 lending works - You supply the underlying asset to the Pool and receive an equal amount of the aToken (aBnbUSDT for USDT). The aToken is a rebasing receipt: its `balanceOf` grows in place as interest accrues, always 1:1 with the underlying you can withdraw. There is no exchange rate to convert. - Supply: `approve(Pool, amount)` on USDT, then `Pool.supply(asset, amount, onBehalfOf, referralCode)` with `asset` = USDT, `onBehalfOf` = your wallet, and `referralCode` = 0. - Withdraw a specific amount: `Pool.withdraw(asset, amount, to)`. Withdraw everything: `Pool.withdraw(asset, type(uint256).max, to)`; the max sentinel means the Pool withdraws your full aToken balance. - Position value: read `balanceOf(wallet)` on the aToken. That number is your live position in underlying units, interest included. - Supply APY: read `getReserveData(USDT)` and take the current liquidity rate (the third field, `currentLiquidityRate`), a per-year rate in ray (1e27). Dividing it by 1e27 gives the rate as a fraction, so about `currentLiquidityRate / 1e27 * 100` percent. - USDT has 18 decimals on BNB Chain, and aBnbUSDT also has 18 decimals. ### Quirks that cause mistakes - The aToken rebases in place: do not expect a fixed receipt amount, and do not divide by any exchange rate. `balanceOf` is already the withdrawable underlying. - Withdrawing with `type(uint256).max` withdraws the entire position, not a max of some cap. Use a concrete amount for a partial withdraw. - Supply reverts if the reserve is paused or frozen. Withdraw reverts if the reserve is paused. A frozen reserve still allows withdraw but blocks new supply. - Withdraw can revert if the Pool lacks available liquidity for a large amount, or if withdrawing would drop your position below what open borrows require. This skill does not borrow, so the borrow constraint does not apply here. ## Playbook ### Play: supply Lend USDT to earn yield. Parameters: USDT amount. **Typical time:** ~15s 1. `execute([approve(USDT, Pool, amount), Pool.supply(USDT, amount, wallet, 0)])` 2. Verify the aBnbUSDT balance increased by the amount (allow a tiny rounding tolerance from rebasing) and USDT decreased by the amount. Report the position value from the aToken `balanceOf`. ### Play: withdraw Withdraw part or all of the position. Parameters: amount or "all". **Typical time:** ~15s 1. For a partial amount: `execute([Pool.withdraw(USDT, amount, wallet)])`. For "all": `execute([Pool.withdraw(USDT, type(uint256).max, wallet)])`. 2. Verify USDT increased and the aBnbUSDT balance decreased (to about zero for a full withdraw). Report amounts and tx hashes. ### Play: position-check Read-only status. No transaction. Parameters: none. **Typical time:** ~5s Read `balanceOf(wallet)` on the aToken for the live position value in USDT, read `getReserveData(USDT)` and take `currentLiquidityRate` (ray, 1e27), and report the position value and the supply APY as `currentLiquidityRate / 1e27 * 100` percent. ## Guards (do not remove) - After every supply or withdraw, verify balances changed as expected before reporting success. - Never approve more than the amount being supplied in this action. - Treat the aToken `balanceOf` as the position value directly; never apply an exchange rate to it. - Use `type(uint256).max` only when the intent is to withdraw the entire position. --- # Token Radar - id: dexscreener-token-radar - page: https://skills.altana.network/skill/dexscreener-token-radar - source: https://skills.altana.network/skills/dexscreener-token-radar/SKILL.md - chain: bnb - version: 1.0.0 - sha256: dc541956a847e00c2793da679b8a4121a5b9f46f08f07d852b88f86681c39a0b - verified: fork-tested by Altana on 2026-07-21 --- name: dexscreener-token-radar description: Find trending BNB Chain tokens and screen them for liquidity and risk using public DexScreener and GeckoTerminal data before trading. Research only, no transactions. --- # DexScreener Token Radar Research skill: discover what is moving on BNB Chain and screen tokens before a trading skill (like pancakeswap-trading or four-meme) acts on them. This skill performs no transactions; its session permits no onchain calls at all. No API key is needed; both data sources are public. ## Reference ### Endpoints (public, no key) | Purpose | Endpoint | |---|---| | Trending pools on BSC | `https://api.geckoterminal.com/api/v2/networks/bsc/trending_pools` | | Pair detail | `https://api.dexscreener.com/latest/dex/pairs/bsc/` | | Token lookup (all pairs) | `https://api.dexscreener.com/latest/dex/tokens/` | | Free-text search | `https://api.dexscreener.com/latest/dex/search?q=` | Rate limits are roughly 300 requests per minute on the DexScreener latest endpoints and 30 per minute on GeckoTerminal; space out batch screens. ### Reading the data - Key pair fields: `priceUsd`, `liquidity.usd`, `volume.h24`, `priceChange.h24`, `txns.h24` (buys and sells), `pairCreatedAt`, `dexId`. - Prefer tokens with liquidity above roughly $100k and a healthy buy and sell mix; thin pools make any trade expensive and easy to manipulate. - A very new `pairCreatedAt` plus low liquidity plus one-sided buys is the classic honeypot shape; flag it, do not just skip it. - Volume without liquidity is a red flag (wash-trade shape), as is a token whose only pair is on an obscure DEX. - Neither source proves a token is safe to sell (transfer taxes and blocklists are not in this data). Recommend a small test trade through a trading skill before sizing up. ## Playbook ### Play: trending-scan List what is moving on BNB Chain right now. Parameters: how many (default 10). **Typical time:** ~15s 1. Fetch GeckoTerminal trending pools for bsc; take the top N. 2. For each pool, fetch the DexScreener pair detail for the richer fields. 3. Report a ranked table: token, address, price, 24h change, liquidity, 24h volume, buys and sells, pair age, and a one-line verdict (tradeable, caution, avoid) with the reason. ### Play: token-screen Deep check on one token before trading. Parameters: token address. **Typical time:** ~10s 1. Fetch all pairs for the token from DexScreener; identify the deepest pair. 2. Report: price, liquidity and where it lives, 24h volume and transaction mix, pair age, price change, and a clear verdict with reasons. If the token is unknown to both sources, say so; absence of data is itself a caution signal. ### Play: watch Poll a token until a condition is met. Parameters: token address, condition (price above or below X, liquidity drop, volume spike), check interval. **Typical time:** runs until the condition triggers Loop token-screen reads at the stated interval and report when the condition is met, so a trading skill can act on it. Respect the rate limits; default to one check per 30 seconds. ## Guards (do not remove) - Research only: this skill never submits transactions and its session permits no onchain calls. Anything requiring a transaction is handed off to a trading skill. - Report the token address with every symbol. Never recommend a token whose address you have not shown the user. - Data gaps are reported as caution, never silently skipped. - This data cannot prove sellability; always recommend a small test trade first. --- # Wallet Tracker - id: wallet-tracker - page: https://skills.altana.network/skill/wallet-tracker - source: https://skills.altana.network/skills/wallet-tracker/SKILL.md - chain: bnb - version: 1.0.0 - sha256: 271ce8f1bae98c3c943a2d48c454d762ac85000f9067bcaa25d11c9aed7525f9 - verified: fork-tested by Altana on 2026-07-21 --- name: wallet-tracker description: Track a BNB Chain wallet's trading activity using only public onchain data (RPC logs), no API keys. Watch new swaps, profile recent activity and holdings, and find a token's early buyers. Research only, no transactions. --- # Wallet Tracker Research skill: follow what a BNB Chain wallet is trading, straight from the chain. It reads PancakeSwap swap logs and ERC-20 transfer logs over a block window, so it needs no API key and no third-party indexer. This skill performs no transactions; its session permits no onchain calls at all. Hand any actual trading to a trading skill (like pancakeswap-trading). The honest boundary: RPC logs only reach back as far as your window covers. Full historical profit-and-loss ranking across a wallet's whole life needs an indexer. This skill works on recent windows and reports the exact window it covered. An optional free BscScan API key (`BSCSCAN_API_KEY`) extends the reachable history; without it, recent windows still work. ## Reference Everything you need to read a wallet's activity from public logs: the events, how to filter them by wallet without knowing the pairs, and the range limits to work around. ### Addresses (BNB Chain mainnet) | Contract | Address | |---|---| | PancakeSwap V2 Router | `0x10ED43C718714eb63d5aA57B78B54704E256024E` | | WBNB | `0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c` | | USDT (BSC-USD) | `0x55d398326f99059fF775485246999027B3197955` | Pair addresses are not hardcoded. You discover them from the logs themselves: a Swap log's `address` field is the pair that emitted it. That is what lets you track a wallet across every pair it touches without a pair list. ### The two events you filter on PancakeSwap V2 pair, one per swap: ``` Swap(address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to) topic0 = 0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822 ``` The `to` field (topic2) is who receives the output tokens. For a router swap, the final hop's `to` is the trader. So `getLogs` with `topic0 = Swap` and `topic2 = wallet`, and NO `address` filter, finds every swap that credited that wallet across ALL pairs in the window. Decode the non-zero `amountXOut` to size the buy; `token0`/`token1` on the pair tell you which side is which. ERC-20, one per token movement: ``` Transfer(address indexed from, address indexed to, uint256 value) topic0 = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef ``` Filter `topic2 = wallet` for tokens flowing IN (buys, receipts), `topic1 = wallet` for tokens flowing OUT (sells, sends). Set the `address` to a specific token to watch just that token, or leave it off to sweep every token the wallet moved. Indexed address topics are the 32-byte left-padded address (12 zero bytes then the 20 address bytes). ### Range limits and chunking Public BNB RPCs cap a single `getLogs` range, commonly somewhere between 1,000 and 50,000 blocks, and some also cap the number of logs returned. Treat 5,000 blocks per call as a safe default and chunk anything larger: loop `fromBlock`/`toBlock` in fixed steps and concatenate. If a call errors with a range or result-size message, halve the step and retry that chunk. BNB blocks are about 3 seconds, so roughly 1,200 blocks per hour and 20,000 blocks is about 17 hours. Convert the window the user asked for ("last day") into a block count before you start, and always report the block range you actually covered. ### Reconstructing holdings You do not need an indexer for a current position: read `balanceOf(wallet)` on each token the wallet touched in the window. Use the Transfer sweep to collect the set of token addresses, then call `balanceOf` for each. Transfers in minus transfers out over the window approximate flow, but `balanceOf` is the truth for what is held right now. Read `decimals()` before formatting amounts. ## Playbook ### Play: watch-wallet Poll for a wallet's new swaps and report each one. Parameters: wallet address, check interval (default 30s). **Typical time:** runs until stopped 1. Record the current block as your cursor. 2. Every interval, `getLogs` for Swap with `topic2 = wallet` from the cursor to the new tip (no `address` filter, so all pairs are covered). Advance the cursor to the tip. 3. For each new Swap: the log `address` is the pair; read its `token0`/`token1`, decode the non-zero in/out amounts, and report token, direction (which token came in), size, pair, and tx hash. Report the block range each poll covered. ### Play: profile-wallet Summarize a wallet's recent trading and current holdings. Parameters: wallet address, window (default last ~20,000 blocks, about 17 hours). **Typical time:** ~30s depending on window and chunking 1. Convert the window to a block range; chunk `getLogs` at about 5,000 blocks per call. 2. Sweep Swap logs with `topic2 = wallet` to list swaps received, and Transfer logs with `topic1 = wallet` (out) and `topic2 = wallet` (in) to list every token moved. 3. From the Transfer sweep, collect the distinct token addresses. For each, read `balanceOf(wallet)` and `decimals()` for current holdings. 4. Report: tokens traded, a rough buy/sell mix from swap directions, current holdings, and the exact block range covered. State plainly that this is the window's view, not lifetime PnL. ### Play: find-early-buyers Given a token, find its first buyers in the available window. Parameters: token address, how many (default 10). **Typical time:** ~30s 1. Find the token's pair(s): scan Transfer logs for the token, or Swap logs, from the earliest block your window reaches, and take the pair `address` from the earliest Swap. 2. Read the earliest Swap logs on that pair in ascending order; each Swap's `to` (topic2) is a buyer. Take the first N distinct `to` addresses that received the token (non-zero token-side `amountOut`). 3. For each early buyer, read `balanceOf` now to report who still holds versus who sold out. 4. Report the buyers, their entry block, and hold-versus-sold status. Be explicit that "early" means earliest within the window you could reach, not necessarily the token's true first buyers unless the window reaches its creation block. ## Guards (do not remove) - Research only: this skill never submits transactions and its session permits no onchain calls. Anything requiring a transaction is handed off to a trading skill. - Report the wallet and token addresses with every symbol. Never report activity for an address you have not shown the user. - Always state the block range (and rough time span) the report covers. A quiet wallet and a window that missed its trades look the same; say which one it is. - Never claim full-history or lifetime PnL from a windowed log scan. That needs an indexer; say so rather than implying completeness.