<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Slip]]></title><description><![CDATA[Slip]]></description><link>https://binnen48-slip.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>Slip</title><link>https://binnen48-slip.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 10 Sep 2026 09:24:24 GMT</lastBuildDate><atom:link href="https://binnen48-slip.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Close empty Solana token accounts and reclaim rent (no seed, public RPC)]]></title><description><![CDATA[Every SPL token account on Solana is a rent-exempt account. When you first receive a token, an Associated Token Account (ATA) is created for that mint and funded with the rent-exempt minimum. The acco]]></description><link>https://binnen48-slip.hashnode.dev/close-empty-solana-token-accounts-and-reclaim-rent-no-seed-public-rpc</link><guid isPermaLink="true">https://binnen48-slip.hashnode.dev/close-empty-solana-token-accounts-and-reclaim-rent-no-seed-public-rpc</guid><category><![CDATA[Solana]]></category><category><![CDATA[Web3]]></category><category><![CDATA[csv]]></category><category><![CDATA[RPC]]></category><dc:creator><![CDATA[binnen48]]></dc:creator><pubDate>Wed, 02 Sep 2026 18:16:28 GMT</pubDate><content:encoded><![CDATA[<p>Every SPL token account on Solana is a rent-exempt account. When you first receive a token, an Associated Token Account (ATA) is created for that mint and funded with the rent-exempt minimum. The account data for a standard token account is 165 bytes, which works out to roughly 0.00204 SOL locked per ATA.</p>
<p>That deposit is not a fee. It is refundable. But it stays locked as long as the account exists, even after you have sold or bridged every last unit of the token. Airdrops, failed NFT mints, dust from AMM routing and abandoned meme coins each leave one empty ATA behind, and a wallet that has been active for a couple of years commonly carries 50 to 300 of them. At ~0.002 SOL each, that is real money sitting idle.</p>
<h2>Finding the empty accounts with a public RPC</h2>
<pre><code class="language-bash">curl -s https://api.mainnet-beta.solana.com -X POST -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"getTokenAccountsByOwner","params":["YOUR_WALLET_ADDRESS",{"programId":"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"},{"encoding":"jsonParsed"}]}'
</code></pre>
<p>Each item comes back with a parsed info block. The test for "closable" is simple: tokenAmount.amount == "0" means the account holds nothing and can be closed. Two extra checks are worth making before you act:</p>
<h2>Closing them</h2>
<p>Closing an ATA transfers the rent lamports back to the owner and deletes the account. You have three sane routes:</p>
<ol>
<li>Phantom: the token list has a close-account flow for zero-balance entries; it signs locally.</li>
<li>Solflare: same idea, exposed in the token detail view.</li>
<li>CLI, the most predictable for bulk work:</li>
</ol>
<pre><code class="language-bash">spl-token accounts --verbose
spl-token close --address &lt;ATA_ADDRESS&gt;
</code></pre>
<p>spl-token close refuses non-empty accounts by default, which is the safety net you want. You can wrap it in a shell loop over the addresses your RPC query returned, and you can fit roughly a dozen close instructions into one transaction if you build it with @solana/web3.js instead.</p>
<h2>The one rule that matters</h2>
<p>Never paste a seed phrase or private key into a website. No legitimate tool needs it. Closing an account requires a signature, which your wallet produces locally, so the site never sees the key. Any page that asks for 12 or 24 words to "scan" or "recover" your rent is stealing your wallet, full stop. A read-only address lookup needs nothing but the public address.</p>
<p>That is the whole technique: two RPC calls, filter on amount == 0, sign the closes in your own wallet. The <a href="https://binnen48.github.io/reclaim/how.html">free how-to</a> walks through doing it by hand, and <a href="https://binnen48.github.io/slip/">Slip</a> is a related tool if you need the output tidied for bookkeeping.</p>
<p>If you would rather not script it, <a href="https://binnen48.github.io/reclaim/">Reclaim</a> is an optional 8 USDC browser tool that runs those same queries against both token programs and hands you a CSV of closable accounts: no wallet connect, no seed, address in, CSV out.</p>
<ul>
<li>Skip anything with state "frozen"; a frozen account cannot be closed.</li>
<li>Token-2022 extensions: some mints carry a transfer hook or a permanent delegate. The account still closes, but read the parsed extension list rather than assuming.</li>
</ul>
<p>Public RPCs rate-limit aggressively, so if you are looping over many wallets, batch and back off. For a single wallet the two calls above are enough.</p>
<p>You do not need a private key, a wallet connection or an indexer to enumerate them. getTokenAccountsByOwner is a read-only RPC call that takes a wallet address and a program id.</p>
<p>The important detail: there are two token programs. Classic SPL Token is <code>TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA</code>, and Token-2022 is <code>TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb</code>. Most tools only query the first one and silently miss half your accounts, so make both calls.</p>
]]></content:encoded></item><item><title><![CDATA[Export a Solana wallet to CSV with public RPC (no API key)]]></title><description><![CDATA[Getting a full transaction history for a Solana address out to CSV does not require a paid indexer or an API key. Two JSON-RPC methods on a public endpoint are enough.
Step 1: getSignaturesForAddress
]]></description><link>https://binnen48-slip.hashnode.dev/export-a-solana-wallet-to-csv-with-public-rpc-no-api-key</link><guid isPermaLink="true">https://binnen48-slip.hashnode.dev/export-a-solana-wallet-to-csv-with-public-rpc-no-api-key</guid><dc:creator><![CDATA[binnen48]]></dc:creator><pubDate>Wed, 02 Sep 2026 17:54:24 GMT</pubDate><content:encoded><![CDATA[<p>Getting a full transaction history for a Solana address out to CSV does not require a paid indexer or an API key. Two JSON-RPC methods on a public endpoint are enough.</p>
<h2>Step 1: getSignaturesForAddress</h2>
<p>Ask the RPC node for the signatures that touched the address, newest first. A single call returns at most 1000 entries.</p>
<pre><code>curl https://api.mainnet-beta.solana.com -s -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"getSignaturesForAddress","params":["&lt;WALLET&gt;",{"limit":1000}]}'
</code></pre>
<p>Each item gives you signature, slot, blockTime, err and memo. That alone is not enough for a CSV with amounts, but it is the index you iterate over.</p>
<h2>Step 2: pagination with before</h2>
<p>To walk further back in history, take the signature of the last item in the page and pass it as <code>before</code> on the next call. Repeat until the node returns fewer results than your limit, or an empty array.</p>
<pre><code>curl https://api.mainnet-beta.solana.com -s -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"getSignaturesForAddress","params":["&lt;WALLET&gt;",{"limit":1000,"before":"&lt;LAST_SIGNATURE&gt;"}]}'
</code></pre>
<p>There is also <code>until</code> if you only want activity newer than a known signature, which is handy for incremental exports where you already have last month's CSV.</p>
<h2>Step 3: getTransaction for the details</h2>
<p>For every signature, fetch the transaction and read the balance deltas.</p>
<pre><code>curl https://api.mainnet-beta.solana.com -s -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"getTransaction","params":["&lt;SIGNATURE&gt;",{"encoding":"jsonParsed","maxSupportedTransactionVersion":0}]}'
</code></pre>
<p>The useful fields:</p>
<ul>
<li><code>meta.preBalances</code> / <code>meta.postBalances</code>: lamport deltas per account index; divide by 1e9 for SOL, and subtract <code>meta.fee</code> where the wallet is fee payer.</li>
<li><code>meta.preTokenBalances</code> / <code>meta.postTokenBalances</code>: SPL token deltas, with mint, owner and <code>uiTokenAmount.decimals</code> already resolved.</li>
<li><code>blockTime</code>: Unix seconds, the timestamp column of your CSV.</li>
<li><code>meta.err</code>: skip or flag failed transactions; they still cost a fee.</li>
</ul>
<p>Pass <code>maxSupportedTransactionVersion: 0</code> or versioned transactions come back as an error instead of a payload.</p>
<p>A reasonable CSV schema: <code>timestamp,signature,direction,asset,amount,counterparty,fee,status</code>.</p>
<h2>Step 4: getTokenAccountsByOwner for token balances</h2>
<p>Deltas tell you what moved; for a current holdings snapshot, enumerate the token accounts the wallet owns.</p>
<pre><code>curl https://api.mainnet-beta.solana.com -s -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"getTokenAccountsByOwner","params":["&lt;WALLET&gt;",{"programId":"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"},{"encoding":"jsonParsed"}]}'
</code></pre>
<p>Each result carries the mint and <code>tokenAmount</code> (raw amount plus decimals). Token-2022 assets live under a different program id, so run the call twice if the wallet holds them.</p>
<h2>Public RPC rate limits</h2>
<p>The public endpoint is rate limited and returns HTTP 429 under load. Practical habits:</p>
<ul>
<li>One getTransaction per signature means a wallet with 5,000 transactions needs 5,000 calls. Serialize them; do not fan out a hundred at a time.</li>
<li>Sleep 100-200 ms between calls and back off exponentially on 429.</li>
<li>Cache every fetched transaction to disk by signature. Transactions are immutable, so a re-run should hit your cache, not the network.</li>
<li>Public nodes prune older ledger data; for very old history you may need an archival provider.</li>
<li>getSignaturesForAddress only returns transactions where the address is a mentioned account, so wallets whose activity flows through associated token accounts need those accounts queried too.</li>
</ul>
<h2>Not tax advice</h2>
<p>This is a data-extraction walkthrough, not tax advice. Cost basis, fee treatment, staking rewards and airdrop timing depend on your jurisdiction; check with a professional before filing anything derived from this CSV.</p>
<p>A copy-paste script version of the above is here: <a href="https://binnen48.github.io/slip/export.html">export.html</a></p>
<p>If you would rather not run scripts at all, Slip is an optional browser version of the same export for 8 USDC.</p>
]]></content:encoded></item></channel></rss>