repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | # Blockchain Antipatterns |
| #2 | |
| #3 | Common mistakes Claude Code makes with blockchain development, and the fix prompts that prevent them. |
| #4 | |
| #5 | --- |
| #6 | |
| #7 | ## 1. No Retry Logic on RPC Calls |
| #8 | |
| #9 | **Problem:** Generic RPC calls without error handling or retries. |
| #10 | |
| #11 | ```typescript |
| #12 | // BAD — Claude's default |
| #13 | const balance = await connection.getBalance(pubkey); |
| #14 | ``` |
| #15 | |
| #16 | ```typescript |
| #17 | // GOOD — production pattern |
| #18 | const balance = await withRetry( |
| #19 | () => connection.getBalance(pubkey), |
| #20 | { maxRetries: 3, backoffMs: 200 } |
| #21 | ); |
| #22 | ``` |
| #23 | |
| #24 | **Fix prompt:** |
| #25 | ``` |
| #26 | All RPC calls must use retry logic with exponential backoff. |
| #27 | Never call the RPC directly — always through a retry wrapper. |
| #28 | ``` |
| #29 | |
| #30 | --- |
| #31 | |
| #32 | ## 2. No Transaction Simulation |
| #33 | |
| #34 | **Problem:** Sending transactions without simulating first. |
| #35 | |
| #36 | ```typescript |
| #37 | // BAD — YOLO send |
| #38 | await sendAndConfirmTransaction(connection, tx, [signer]); |
| #39 | ``` |
| #40 | |
| #41 | ```typescript |
| #42 | // GOOD — simulate first |
| #43 | const sim = await connection.simulateTransaction(tx); |
| #44 | if (sim.value.err) { |
| #45 | throw new SimulationError(sim.value.err, sim.value.logs); |
| #46 | } |
| #47 | // then send with priority fee based on simulation CU |
| #48 | ``` |
| #49 | |
| #50 | **Fix prompt:** |
| #51 | ``` |
| #52 | Every transaction must be simulated before sending. |
| #53 | Use simulation results to set compute unit limit accurately. |
| #54 | Never send a transaction that hasn't been simulated. |
| #55 | ``` |
| #56 | |
| #57 | --- |
| #58 | |
| #59 | ## 3. Blocking on Confirmation |
| #60 | |
| #61 | **Problem:** Using `sendAndConfirmTransaction` which can hang indefinitely during congestion. |
| #62 | |
| #63 | ```typescript |
| #64 | // BAD — blocks forever on congestion |
| #65 | await sendAndConfirmTransaction(...); // can hang for 60s+ |
| #66 | ``` |
| #67 | |
| #68 | ```typescript |
| #69 | // GOOD — timeout and retry strategy |
| #70 | const sig = await sendWithTimeout(tx, { timeoutMs: 5000 }); |
| #71 | const confirmed = await pollConfirmation(sig, { maxAttempts: 10 }); |
| #72 | ``` |
| #73 | |
| #74 | **Fix prompt:** |
| #75 | ``` |
| #76 | Transaction confirmation must have explicit timeouts. |
| #77 | Implement a retry strategy for transactions that don't land. |
| #78 | Never block indefinitely waiting for confirmation. |
| #79 | ``` |
| #80 | |
| #81 | --- |
| #82 | |
| #83 | ## 4. Hardcoded Priority Fees |
| #84 | |
| #85 | **Problem:** Static priority fees that don't adapt to network conditions. |
| #86 | |
| #87 | ```typescript |
| #88 | // BAD — hardcoded, stale |
| #89 | tx.add(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1000 })); |
| #90 | ``` |
| #91 | |
| #92 | ```typescript |
| #93 | // GOOD — dynamic based on network |
| #94 | const priorityFee = await helius.getPriorityFeeEstimate(tx); |
| #95 | tx.add(ComputeBudgetProgram.setComputeUnitPrice({ |
| #96 | microLamports: priorityFee.high // or medium based on urgency |
| #97 | })); |
| #98 | ``` |
| #99 | |
| #100 | **Fix prompt:** |
| #101 | ``` |
| #102 | Priority fees must be estimated dynamically using Helius priority fee API. |
| #103 | Never hardcode priority fees — network conditions change constantly. |
| #104 | ``` |
| #105 | |
| #106 | --- |
| #107 | |
| #108 | ## 5. No MEV Protection for Swaps |
| #109 | |
| #110 | **Problem:** Submitting value-bearing transactions to the public mempool. |
| #111 | |
| #112 | ```typescript |
| #113 | // BAD — public mempool, sandwichable |
| #114 | await sendTransaction(swapTx); |
| #115 | ``` |
| #116 | |
| #117 | ```typescript |
| #118 | // GOOD — Jito bundle |
| #119 | await jito.sendBundle([swapTx], { tip: 10000 }); |
| #120 | ``` |
| #121 | |
| #122 | **Fix prompt:** |
| #123 | ``` |
| #124 | All value-bearing transactions (swaps, liquidations, arb) |
| #125 | must go through Jito bundles for MEV protection. |
| #126 | Public mempool submission only for non-sensitive operations. |
| #127 | ``` |
| #128 | |
| #129 | --- |
| #130 | |
| #131 | ## 6. Deprecated Solana Patterns |
| #132 | |
| #133 | **Problem:** Using outdated `@solana/web3.js` APIs. |
| #134 | |
| #135 | **Fix prompt:** |
| #136 | ``` |
| #137 | Do not use deprecated @solana/web3.js patterns. |
| #138 | Check the current API before using any web3.js function. |
| #139 | Prefer the newer transaction format (VersionedTransaction) over legacy. |
| #140 | ``` |
| #141 | |
| #142 | --- |
| #143 | |
| #144 | ## 7. No Compute Unit Management |
| #145 | |
| #146 | **Problem:** Not setting compute unit limits, wasting SOL on over-allocated CU. |
| #147 | |
| #148 | ```typescript |
| #149 | // BAD — default 200k CU, wasteful |
| #150 | const tx = new Transaction().add(swapInstruction); |
| #151 | ``` |
| #152 | |
| #153 | ```typescript |
| #154 | // GOOD — set CU based on simulation |
| #155 | const sim = await connection.simulateTransaction(tx); |
| #156 | const cuUsed = sim.value.unitsConsumed || 200_000; |
| #157 | tx.add(ComputeBudgetProgram.setComputeUnitLimit({ |
| #158 | units: Math.ceil(cuUsed * 1.2) // 20% buffer |
| #159 | })); |
| #160 | ``` |
| #161 | |
| #162 | **Fix prompt:** |
| #163 | ``` |
| #164 | Always set compute unit limits based on simulation results. |
| #165 | Add a 20% buffer to simulated CU usage. |
| #166 | Never use default compute units for production transactions. |
| #167 | ``` |
| #168 | |
| #169 | --- |
| #170 | |
| #171 | ## 8. Ignoring Account Constraints |
| #172 | |
| #173 | **Problem:** Not validating account ownership, mutability, or signer status. |
| #174 | |
| #175 | **Fix prompt:** |
| #176 | ``` |
| #177 | Every account passed to an instruction must be validated: |
| #178 | - Is it the correct owner? |
| #179 | - Is it marked writable when needed? |
| #180 | - Is the signer requirement correct? |
| #181 | - Is the PDA derivation verified? |
| #182 | For Anchor programs, use account constraints in the struct. |
| #183 | ``` |
| #184 | |
| #185 | --- |
| #186 | |
| #187 | ## 9. Synchronous RPC in Hot Paths |
| #188 | |
| #189 | **Problem:** Making blocking RPC calls in performance-critical loops. |
| #190 | |
| #191 | **Fix prompt:** |
| #192 | ``` |
| #193 | Never use synchronous RPC calls in hot paths. |
| #194 | Batch reads where possible with getMultipleAccountsInfo. |
| #195 | Pre-fetch data that doesn't change frequently. |
| #196 | Use websocket subscriptions for real-time state. |
| #197 | ``` |
| #198 | |
| #199 | --- |
| #200 | |
| #201 | ## 10. No Graceful Shutdown |
| #202 | |
| #203 | **Problem:** Process exits leave orphaned positions, pending transactions, or inconsistent state. |
| #204 | |
| #205 | **Fix prompt:** |
| #206 | ``` |
| #207 | Implement graceful shutdown that: |
| #208 | - Catches SIGTERM and SIGINT |
| #209 | - Closes open websocket connections |
| #210 | - Waits for in-flight transactions to resolve |
| #211 | - Logs final state for recovery |
| #212 | - Does not leave orphaned positions |
| #213 | ``` |
| #214 |