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 | --- |
| #2 | name: pump-ts-vanity |
| #3 | description: "Educational single-threaded TypeScript vanity address generator for Solana using @solana/web3.js with async iteration, event-loop yielding, streaming generator API, and best-effort memory zeroization." |
| #4 | metadata: |
| #5 | openclaw: |
| #6 | homepage: https://github.com/nirholas/pump-fun-sdk |
| #7 | --- |
| #8 | |
| #9 | # TypeScript Vanity Generator — Educational Reference Implementation |
| #10 | |
| #11 | Single-threaded TypeScript vanity address generator using @solana/web3.js with async iteration, event-loop yielding, and streaming generator API. |
| #12 | |
| #13 | ## Architecture |
| #14 | |
| #15 | ``` |
| #16 | CLI / Library API |
| #17 | │ |
| #18 | VanityGenerator |
| #19 | │ |
| #20 | async generator loop |
| #21 | │ |
| #22 | Keypair.generate() per iteration |
| #23 | │ |
| #24 | AddressMatcher.matches() |
| #25 | │ |
| #26 | yield on match / yield progress |
| #27 | ``` |
| #28 | |
| #29 | ## Library API (3 Usage Patterns) |
| #30 | |
| #31 | ```typescript |
| #32 | // 1. Async generator (streaming) |
| #33 | for await (const result of generateVanityAddress({ prefix: 'pump' })) { |
| #34 | console.log(result.address); |
| #35 | break; // stop after first match |
| #36 | } |
| #37 | |
| #38 | // 2. First match (promise) |
| #39 | const result = await findVanityAddress({ prefix: 'pump' }); |
| #40 | |
| #41 | // 3. Batch generation |
| #42 | const results = await findVanityAddresses({ prefix: 'So', count: 5 }); |
| #43 | ``` |
| #44 | |
| #45 | ## Event-Loop Yielding |
| #46 | |
| #47 | ```typescript |
| #48 | async function* generateVanityAddress(config: VanityConfig) { |
| #49 | let attempts = 0; |
| #50 | while (true) { |
| #51 | attempts++; |
| #52 | if (attempts % 1000 === 0) { |
| #53 | await new Promise(resolve => setImmediate(resolve)); |
| #54 | } |
| #55 | const keypair = Keypair.generate(); |
| #56 | const address = keypair.publicKey.toBase58(); |
| #57 | if (matcher.matches(address)) { |
| #58 | yield { keypair, address, attempts }; |
| #59 | } |
| #60 | } |
| #61 | } |
| #62 | ``` |
| #63 | |
| #64 | Yields to the event loop every 1,000 iterations to prevent blocking. |
| #65 | |
| #66 | ## Performance Comparison |
| #67 | |
| #68 | | Feature | Rust | TypeScript | |
| #69 | |---------|------|-----------| |
| #70 | | Speed | 100K+ keys/sec | ~5K keys/sec | |
| #71 | | Parallelism | Rayon (multi-core) | Single-threaded | |
| #72 | | Memory safety | Zeroize trait | Best-effort fill(0) | |
| #73 | | Use case | Production | Educational/prototyping | |
| #74 | |
| #75 | ## Best-Effort Security |
| #76 | |
| #77 | ```typescript |
| #78 | // Zeroize secret key after use |
| #79 | const secretKey = keypair.secretKey; |
| #80 | try { |
| #81 | // ... use keypair |
| #82 | } finally { |
| #83 | secretKey.fill(0); |
| #84 | } |
| #85 | ``` |
| #86 | |
| #87 | JavaScript's garbage collector may copy/relocate buffers, so `fill(0)` is best-effort. |
| #88 | |
| #89 | ## Patterns to Follow |
| #90 | |
| #91 | - Use `@solana/web3.js` `Keypair.generate()` — never custom RNG |
| #92 | - Yield to event loop periodically in async generators |
| #93 | - Call `secretKey.fill(0)` after use (best-effort zeroization) |
| #94 | - Validate Base58 patterns before starting generation |
| #95 | - Use `setImmediate` or `setTimeout(0)` for yielding, not `process.nextTick` |
| #96 | |
| #97 | ## Common Pitfalls |
| #98 | |
| #99 | - Single-threaded — orders of magnitude slower than Rust for long prefixes |
| #100 | - GC may relocate buffers before `fill(0)` — no guaranteed memory cleanup in JS |
| #101 | - Base58 is case-sensitive — validate user input patterns |
| #102 | - `Keypair.generate()` returns 64-byte array (32 secret + 32 public) |
| #103 | |
| #104 |