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 | const MAINNET_HOSTNAMES = [ |
| #2 | "api.mainnet-beta.solana.com", |
| #3 | "mainnet.helius-rpc.com", |
| #4 | "mainnet.rpc.jito.wtf", |
| #5 | "solana-mainnet", |
| #6 | "mainnet-beta", |
| #7 | ]; |
| #8 | export function rejectMainnet(rpcUrl) { |
| #9 | if (process.env["MAINNET_OK"] === "1") |
| #10 | return; |
| #11 | const lowered = rpcUrl.toLowerCase(); |
| #12 | for (const host of MAINNET_HOSTNAMES) { |
| #13 | if (lowered.includes(host)) { |
| #14 | throw new Error(`[SAFETY] Mainnet RPC URL rejected: "${rpcUrl}". Goblin mode is devnet paper only.`); |
| #15 | } |
| #16 | } |
| #17 | } |
| #18 | function mulberry32(seed) { |
| #19 | return function random() { |
| #20 | seed |= 0; |
| #21 | seed = (seed + 0x6d2b79f5) | 0; |
| #22 | let t = Math.imul(seed ^ (seed >>> 15), 1 | seed); |
| #23 | t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; |
| #24 | return ((t ^ (t >>> 14)) >>> 0) / 4294967296; |
| #25 | }; |
| #26 | } |
| #27 | export class SynthObserver { |
| #28 | rand; |
| #29 | lastClose; |
| #30 | candles = []; |
| #31 | windowSize; |
| #32 | constructor(seed = 42, startPrice = 150_000, windowSize = 20) { |
| #33 | this.rand = mulberry32(seed); |
| #34 | this.lastClose = startPrice; |
| #35 | this.windowSize = windowSize; |
| #36 | } |
| #37 | tick(now = new Date()) { |
| #38 | const move = (this.rand() - 0.48) * 0.03; |
| #39 | const open = this.lastClose; |
| #40 | const close = Math.max(1, Math.round(open * (1 + move))); |
| #41 | const high = Math.round(Math.max(open, close) * (1 + this.rand() * 0.01)); |
| #42 | const low = Math.round(Math.min(open, close) * (1 - this.rand() * 0.01)); |
| #43 | const volume = Math.round(1_000_000 + this.rand() * 9_000_000); |
| #44 | this.candles.push({ t: now.toISOString(), o: open, h: high, l: low, c: close, v: volume }); |
| #45 | if (this.candles.length > this.windowSize) |
| #46 | this.candles.shift(); |
| #47 | this.lastClose = close; |
| #48 | const whaleRoll = this.rand(); |
| #49 | const bias = whaleRoll > 0.66 ? "long" : whaleRoll < 0.34 ? "short" : "neutral"; |
| #50 | const notional = Math.round(250_000 + this.rand() * 8_000_000); |
| #51 | const description = bias === "neutral" |
| #52 | ? `no dominant whale impulse; ${notional.toLocaleString()} lamports churned` |
| #53 | : `${bias} whale impulse; ${notional.toLocaleString()} lamports synthetic flow`; |
| #54 | return { |
| #55 | candles: [...this.candles], |
| #56 | whale_activity: { bias, notional_lamports: notional, description }, |
| #57 | }; |
| #58 | } |
| #59 | } |
| #60 | export async function observeFromHelius(rpcUrl, state, windowSize = 20) { |
| #61 | rejectMainnet(rpcUrl); |
| #62 | console.warn("[observe] Helius adapter not wired; using deterministic synth candles"); |
| #63 | const synth = new SynthObserver(state.tick, 150_000, windowSize); |
| #64 | for (let i = 0; i < Math.min(state.tick, windowSize); i += 1) |
| #65 | synth.tick(); |
| #66 | return synth.tick().candles; |
| #67 | } |
| #68 | export function isStale(candles, maxAgeSeconds = 60) { |
| #69 | if (candles.length === 0) |
| #70 | return true; |
| #71 | const last = candles[candles.length - 1]; |
| #72 | const age = (Date.now() - new Date(last.t).getTime()) / 1000; |
| #73 | return age > maxAgeSeconds; |
| #74 | } |
| #75 | //# sourceMappingURL=observe.js.map |