@pickhooks/sdk 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +113 -4
- package/dist/abis/agents.d.ts +2418 -0
- package/dist/abis/agents.js +4 -0
- package/dist/abis/index.d.ts +2 -0
- package/dist/abis/index.js +2 -0
- package/dist/abis/sticky2.d.ts +3750 -0
- package/dist/abis/sticky2.js +8 -0
- package/dist/addresses.d.ts +14 -1
- package/dist/addresses.js +11 -2
- package/dist/agents-catalog.d.ts +318 -0
- package/dist/agents-catalog.js +353 -0
- package/dist/agents.d.ts +543 -0
- package/dist/agents.js +667 -0
- package/dist/desks.d.ts +298 -0
- package/dist/desks.js +343 -0
- package/dist/errors.js +69 -2
- package/dist/index.d.ts +33 -2
- package/dist/index.js +41 -8
- package/dist/sticky-sim.d.ts +125 -0
- package/dist/sticky-sim.js +637 -0
- package/dist/sticky.d.ts +74 -4
- package/dist/sticky.js +171 -43
- package/dist/tlock.d.ts +67 -0
- package/dist/tlock.js +185 -0
- package/dist/tx.d.ts +2 -0
- package/dist/tx.js +9 -0
- package/dist/v2.d.ts +106 -0
- package/dist/v2.js +61 -0
- package/dist/wallet.d.ts +80 -0
- package/dist/wallet.js +115 -0
- package/dist/watch.d.ts +82 -0
- package/dist/watch.js +194 -0
- package/package.json +10 -1
package/README.md
CHANGED
|
@@ -10,6 +10,9 @@ Every pickhooks product, one client:
|
|
|
10
10
|
* **pools** (`ph.pools`) and **curve calls** (`ph.calls`): coins with their rules in the pool's hook; renting a step of a coin's curve.
|
|
11
11
|
* **Lever** (`ph.lever`, the first lever: `ph.leverV1`): longs and shorts on a coin's own liquidity.
|
|
12
12
|
* **dip bids** (`ph.dips`): floors at a strike, bought from a maker's bid.
|
|
13
|
+
* **agents** (`ph.agents`): coins run by an agent that rewrites their rule program live, inside limits the chain checks. Read a coin's program as sentences, **be the agent yourself** (`brief` hands any model the pickhooks pilot's own prompt, `act` sends what it decided), veto a change or fire the agent as a holder, launch an agent coin with your own bot as its pilot.
|
|
14
|
+
* **watch** (`ph.watch`): live events for terminals and bots: every launch on the pad, every trade of a coin, everything that happens to an agent coin.
|
|
15
|
+
* **wallet** (`ph.wallet`): one address in, everything it holds on pickhooks out: coins by mode with what is sellable right now, BNB owed by the hooks, coins locked at the agents desk, dip bid floors.
|
|
13
16
|
|
|
14
17
|
For a terminal the point is the same everywhere: before a trade is signed, the SDK asks the coin, and a refusal comes back as the rule's sentence ("Refused by the rule "Max per buy". No buy over 0.5% of supply.") instead of "honeypot".
|
|
15
18
|
|
|
@@ -137,8 +140,9 @@ await ph.sticky.coin(token);
|
|
|
137
140
|
await ph.sticky.wallet(token, who); // balance, sellable now, lots (amount, locked, since, marks)
|
|
138
141
|
const v = await ph.sticky.check({ token, side: "sell", wallet, amount });
|
|
139
142
|
// { ok: true } or { ok: false, row: 1, text: "Refused by rule 2: Sniper jail. A sell is refused when …" }
|
|
140
|
-
await ph.sticky.buy({ token, bnbIn }); // quote, check, then the buy through
|
|
143
|
+
await ph.sticky.buy({ token, bnbIn }); // quote, check, then the buy through the better of the coin's two venues
|
|
141
144
|
await ph.sticky.sell({ token, amount }); // check first: a refusing rule stops it before anything is signed
|
|
145
|
+
await ph.sticky.quote({ token, side: "sell", amount }); // { amountOut, venue: "v3" | "v2", v3, v2 }: the V3 pool and the V2 pair, the better one wins
|
|
142
146
|
await ph.sticky.lift(token, row); // the creator lifts a row for good
|
|
143
147
|
```
|
|
144
148
|
|
|
@@ -153,6 +157,16 @@ await ph.sticky.launch({ name, symbol, metadata, picks: [{ id: "devlock", params
|
|
|
153
157
|
|
|
154
158
|
The editor's checks run first (a row the site would refuse stops before anything is signed, in words), then the validator on chain. Rows that lock shares take `scriptHours` (10 minutes to 30 days).
|
|
155
159
|
|
|
160
|
+
**The test run, before the launch.** The launcher's test run, offline: the table on a fresh coin with random trades (the creator's first buy, three snipers in the first blocks, wallets that buy, hold and sell, bags split to fresh wallets). It runs the coin's own rule engine, checked against the contract trade by trade. The same seed gives the same run.
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
const run = ph.sticky.testRun({ picks, script, devBuyBnb: 0.05, seed: 7, trades: 200 });
|
|
164
|
+
run.report; // refusals per row, longest wait to sell, snipers, split bags, when everyone is free, burn, pot, a scanner's test
|
|
165
|
+
run.text; // the same as sentences: "A scanner's test: its sell right after the buy is refused by rule 1, Hold time: it can show a honeypot."
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Numbers left out of a pick take the template's defaults (`{ id: "hold" }` is a hold time of 30 minutes); `ph.sticky.table({ picks, script })` returns the rows and release a launch would send.
|
|
169
|
+
|
|
156
170
|
Sticky coins trade in a PancakeSwap V3 pool of 1 % and a V2 pair, so any router can trade them. For a terminal the point is `check()`: instead of "honeypot", show the row that stops the trade, in words.
|
|
157
171
|
|
|
158
172
|
**A quote that a rule refuses.** PancakeSwap's QuoterV2 runs the swap, so a buy a rule refuses fails in the quoter, and the quoter does not pass the coin's reason on (it says "Unexpected error"). `quote()` of sticky coins and of coins with rules then checks the buy again with `estimateBuy(token, bnbIn)` (the pool's liquidity at its price) and throws the rule's sentence (`code: "Blocked"`). Pass `wallet` to check for that wallet. The estimate names rules; never use it as a minimum.
|
|
@@ -242,7 +256,7 @@ await ph.dips.close(id); // the maker takes the fre
|
|
|
242
256
|
|
|
243
257
|
## HOOKS infra: `ph.infra`
|
|
244
258
|
|
|
245
|
-
|
|
259
|
+
On mainnet since 09.10.2026 (executor `0xCCea8f8195Dd3c62C28e218C002316e67B95bb36`, floor factory `0xcaA38326d43071e5a7a940c144042a14DC42086F`; `ph.infra.on` says which part is live).
|
|
246
260
|
|
|
247
261
|
* **Floors:** a BNB reserve under a coin (one per coin, anyone can open and feed it). A holder hands coins in for reserve / circulating, less 2 % (1 % stays and lifts the floor, 1 % to the protocol); the coins go to 0xdead. No owner, no withdraw: the floor only rises.
|
|
248
262
|
* **Protected buy:** one transaction buys through PancakeSwap's own routers and a dip floor for what arrived. pickhooks.com picks the route and the bid; `protect()` sends what the site built, after checking it goes to the executor.
|
|
@@ -257,6 +271,97 @@ const o = await ph.infra.offer({ token, bnbIn }); // the route, the bids that ca
|
|
|
257
271
|
await ph.infra.protect({ token, bnbIn }); // { coins, floorId, premium }
|
|
258
272
|
```
|
|
259
273
|
|
|
274
|
+
## sticky 2 and its desks: `ph.sticky2`, `ph.cover`, `ph.auction`, `ph.dark`, `ph.launchDesk`
|
|
275
|
+
|
|
276
|
+
On mainnet since 11.10.2026 (factory `0xB9b90378Cf621a625a4AcBA9B95a7f204e6Df54c`, dev cover `0xf6e66a4DadfB0700603342D244dE6F999B2725DF`, rule auction `0x874CA64571774f2ae0A3fFa0A578B046910aDb35`, dark launch `0x304c6604e96627FDdc7a94b7a691A0673A80F765`, launch desk `0x81508f3fCc535c29a49226E61D39188b6D479d61`). On a fork, pass other addresses with `createPickhooks({ addresses })`.
|
|
277
|
+
|
|
278
|
+
* **sticky 2** (`ph.sticky2`): everything `ph.sticky` does, on the second factory. The coin also counts what its creator sold, from any wallet the DEV coins went through, and can carry switch rows: rows that are off until a switcher (the rule auction) turns one on.
|
|
279
|
+
* **dev cover** (`ph.cover`): a writer puts BNB on a coin against its creator selling. A holder buys a policy for a premium; when the creator's sold share reaches the offer's mark (10, 25, 50 or 100 %), the policy pays its cover. Posted by the creator itself, it is a dev bond. A policy can only cover what the holder's coins are worth.
|
|
280
|
+
* **rule auction** (`ph.auction`): holders burn coins for one of the coin's switch rows; at the end of each round the game with the most burned is turned on.
|
|
281
|
+
* **dark launch** (`ph.dark`): a round before the coin exists. Bids show their BNB but seal their top price to a drand round that is signed only after the bidding. Once signed anyone opens the bids, everyone buys at one price, and the coin is born at that price with BNB on both sides. The round's BNB sits in the coin's V2 pair, so right after the birth a sell routes there (`quote` picks the venue; a sell into the one sided V3 curve would get almost nothing). Terminals do the same by themselves.
|
|
282
|
+
* **launch desk** (`ph.launchDesk`): a wallet's BNB that the pad's reply bot may launch with, only for that wallet, within the limits the wallet set.
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
await ph.sticky2.devCounters(token); // { bought, sold, soldBps, at: { 10, 25, 50, 100 } }
|
|
286
|
+
await ph.sticky2.switches(token); // { mask, on, switcher }
|
|
287
|
+
await ph.sticky2.launch({ name, symbol, metadata, picks: [{ id: "lucky" }, { id: "dipdrop" }, { id: "wakeup" }], switchRows: [1, 3, 5] });
|
|
288
|
+
// drop rows that switch; the rule auction runs them
|
|
289
|
+
|
|
290
|
+
const { id } = await ph.cover.post({ token, mark: 25, premiumBps: 300, duration: 86_400, stopBps: 1000, deposit });
|
|
291
|
+
await ph.cover.offers(token); // with `bond` when the creator wrote it, `live` when it sells
|
|
292
|
+
const q = await ph.cover.quote(id, cover); // { premium, fee, payout }
|
|
293
|
+
const p = await ph.cover.buy(id, cover); // pays exactly the quoted premium; p.id is the policy
|
|
294
|
+
await ph.cover.claim(p.id); // once the creator's sold share reached the mark
|
|
295
|
+
|
|
296
|
+
await ph.auction.state(token); // { round, endsAt, burned[8], mask, on, settleable }
|
|
297
|
+
await ph.auction.burn(token, game, amount); // approval, then the burn
|
|
298
|
+
|
|
299
|
+
await ph.dark.round(roundId); // endsAt, drandRound, state (0 bidding, 1 born, 2 failed), step, token
|
|
300
|
+
await ph.dark.prices(); // BNB per coin at each of the 24 steps
|
|
301
|
+
const b = await ph.dark.bid({ roundId, step: 9, deposit }); // seals step 9 to the round's drand round, then bids
|
|
302
|
+
await ph.dark.owedOf(b.id); // { coins, paid, claimableNow }
|
|
303
|
+
await ph.dark.claim(b.id);
|
|
304
|
+
const o = await ph.dark.opener(roundId); // once drand signed: the open transaction (anyone may send it)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
The seal is time-lock encryption to drand quicknet, the same scheme as find the dev. `@pickhooks/sdk/tlock` holds it on its own entry (`encrypt`, `decrypt`, `darkMessage`, `fetchRoundSig`, `roundAt`), so the main import does not load BLS12-381.
|
|
308
|
+
|
|
309
|
+
## Agents: `ph.agents`
|
|
310
|
+
|
|
311
|
+
On mainnet since 09.10.2026 (factory `0x5965e2D2128248ac2CB4FFf312CFB098a1eDA232`). An agent coin is a plain ERC20 in a PancakeSwap Infinity pool whose hook runs a **program**: the fee on each side (1 % up to the coin's cap), where the coin's part of every fee goes (burn, liquidity the coin owns for good, its HOOKS floor, a rewards pot, a jackpot, the creator, the treasury) and up to eight pool rules. The **pilot** (any wallet: the pickhooks agent, your bot, a model behind an MCP server) proposes a whole new program; the desk checks it against the coin's **envelope** (limits fixed for good at launch: max fee, max creator share, allowed rules, notice, gap, veto and fire shares) and the limits every agent coin lives with (sells can never be closed for good, no rule names a wallet, BNB never leaves the coin). The change is announced and lands after the notice; holders lock coins to **veto** it or to **fire** the pilot. Every router trades the coin.
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
const c = await ph.agents.coin(token); // program as sentences (c.lines), env, pending change, fire tally, buckets, runs, price
|
|
315
|
+
await ph.agents.coins({ limit: 20 }); // newest first
|
|
316
|
+
await ph.agents.quote({ token, side: "buy", amount: parseEther("0.01"), from }); // a refusing rule comes back as its sentence
|
|
317
|
+
await ph.agents.buy({ token, bnbIn }); await ph.agents.sell({ token, amount }); // through the UniversalRouter, rules checked first
|
|
318
|
+
|
|
319
|
+
// be the agent: the pickhooks pilot's prompt for any model, its answer back into a transaction
|
|
320
|
+
const b = await ph.agents.brief(token); // { system, user, schema, look, profile }
|
|
321
|
+
const answer = await yourModel(b.system, b.user, { schema: b.schema }); // { title, body, action, plan, move, expect }
|
|
322
|
+
const { tx, proposal } = await ph.agents.act(token, answer); // propose / move / null for "none"
|
|
323
|
+
if (tx) await ph.send(tx); // from the pilot's wallet (or ph.agents.pilot(token, answer) in one go)
|
|
324
|
+
|
|
325
|
+
// or write the program yourself, in plain units
|
|
326
|
+
await ph.agents.propose(token, { buy_fee_pct: 1.5, sell_fee_pct: 2, route: { burn: 50, lp: 20, floor: 10 }, rules: [{ id: "max_buy", values: { cap_pct: 1 } }] }, { title, body });
|
|
327
|
+
ph.agents.problemsOf(program, env); // the limits' problems, offline; checkProgram(token, program) asks the desk (eth_call as the pilot)
|
|
328
|
+
await ph.agents.move(token, "treasury", "burn", wei); await ph.agents.cancel(token); await ph.agents.handOver(token, to);
|
|
329
|
+
|
|
330
|
+
// holders
|
|
331
|
+
await ph.agents.veto(token, coins); await ph.agents.fire(token, coins); await ph.agents.withdraw(token);
|
|
332
|
+
await ph.agents.activate(token); // anyone lands a change that is due (the pickhooks keeper does too)
|
|
333
|
+
await ph.agents.burn(token); await ph.agents.addLiquidity(token); await ph.agents.feedFloor(token); // the runs anyone may trigger
|
|
334
|
+
|
|
335
|
+
// launch with your own pilot
|
|
336
|
+
const { metadata } = await ph.agents.prepareMetadata({ name, symbol, image, agent: { name: "whiskers", personality: "degen", objectives: ["depth"], mission } });
|
|
337
|
+
await ph.agents.launch({ name, symbol, metadata, plan, envelope: { maxFeeBps: 500, notice: 1800 }, pilot: myBot, devBuy });
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
`ph.agents.catalog()` is the vocabulary as plain data: the 18 rules an agent may use with their fields, the limits, the buckets, the personalities and objectives of a profile, the ABI tuples, the answer schema. The catalog, the pilot's prompt and the answer schema are a checked port of the site's and the keeper's (`npm run check`), so a bring your own agent runs on the same text the pickhooks agent does. The main import holds it all; `AGENT_RULES`, `toProgram`, `describeProgram`, `systemPrompt`, `ANSWER_SCHEMA`, `noteHash`, `parseAnswer` are exported on their own.
|
|
341
|
+
|
|
342
|
+
## Live events: `ph.watch`
|
|
343
|
+
|
|
344
|
+
Each watcher polls the RPC (HTTP is enough; `pollingInterval` default 3 s) and returns a function that stops it.
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
const stop = ph.watch.launches((l) => console.log(l.mode, l.symbol, l.token), { modes: ["sticky", "agents"] });
|
|
348
|
+
const stop2 = await ph.watch.trades(token, (t) => console.log(t.buy ? "buy" : "sell", t.coins, t.bnb ?? t.fee, t.trader));
|
|
349
|
+
const stop3 = await ph.watch.agent(token, (e) => console.log(e.event, e.args)); // Proposed, Activated, Vetoed, PilotFired, Burned, ...
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
`launches` covers every factory (sticky, rules v2 and v1, pools, curve calls, Lever, agents, hook any coin's new pools; `ph.watch.modes` lists the live ones) and reads name and symbol from the token. `trades` finds the coin's mode itself: the hook's `Traded` events for pools, curve calls, agents and hook any coin pools, the `Swap` events of the PancakeSwap V3 pool and V2 pair for sticky and rules coins.
|
|
353
|
+
|
|
354
|
+
## One address: `ph.wallet`
|
|
355
|
+
|
|
356
|
+
```ts
|
|
357
|
+
const w = await ph.wallet(address);
|
|
358
|
+
w.coins // every pickhooks coin it holds: mode, name, symbol, balance, sellable now (sticky: the unlocked lots; others: the coin asked for the whole balance, the refusal in words), price, value, page
|
|
359
|
+
w.claims // BNB owed: hook any coin (recapture shares, router credits), pools, curve calls, agents; totalBnb
|
|
360
|
+
w.locks // coins locked at the agents desk, per coin, and what they back (a veto, the firing)
|
|
361
|
+
w.floors // dip bid floors it holds
|
|
362
|
+
w.scanned // the factories covered and how many of their coins (the newest `limit` each, default 300)
|
|
363
|
+
```
|
|
364
|
+
|
|
260
365
|
## Building blocks: `ph.blocks`
|
|
261
366
|
|
|
262
367
|
The vocabulary of every rule, as plain data and offline: sticky rules' 12 ready blocks (numbers with their ranges, the sentence, the rows they make, what scanners show), the hook script grammar (triggers, actions, marks, variables with their units, operators, the checks a table must pass) and the rule book of coins with rules (each rule with its fields).
|
|
@@ -293,9 +398,13 @@ Every failure is a `PickhooksError` with `code` (the contract's error name, or `
|
|
|
293
398
|
| Lever Lens | `0x3f1a660FC365Af192acE4E761657cE61A6ED0F13` |
|
|
294
399
|
| lever (v1) factory | `0xeaB93e923170bd5331Db4300aF6F2555eBBF9615` |
|
|
295
400
|
| dip bids desk | `0xc73bcB859C3fD5Bd38A10B0aD9A862EAAf6765bf` |
|
|
401
|
+
| HOOKS executor (protected buy) | `0xCCea8f8195Dd3c62C28e218C002316e67B95bb36` |
|
|
402
|
+
| HOOKS floor factory | `0xcaA38326d43071e5a7a940c144042a14DC42086F` |
|
|
403
|
+
| agents factory | `0x5965e2D2128248ac2CB4FFf312CFB098a1eDA232` |
|
|
404
|
+
| the pickhooks agent (pilot wallet) | `0x85b85b75806446BB7AFa324D67B20cc1C29eCFB5` |
|
|
296
405
|
| $hooks | `0x07bcB8E8226f671300e135b4A61Dc157359b7777` |
|
|
297
406
|
|
|
298
|
-
All verified on BscScan. `BSC_MAINNET` holds these and PancakeSwap's; `createPickhooks({ addresses })` points the SDK elsewhere (a fork). The tax line's factory is not set yet (`anyTaxFactory` is zero until it is on mainnet). ABIs: `@pickhooks/sdk/abis`; the sticky encoder alone: `@pickhooks/sdk/rules`; the rule catalog of coins with rules: `@pickhooks/sdk/coin-rules`.
|
|
407
|
+
All verified on BscScan. `BSC_MAINNET` holds these and PancakeSwap's; `createPickhooks({ addresses })` points the SDK elsewhere (a fork). The tax line's factory is not set yet (`anyTaxFactory` is zero until it is on mainnet). ABIs: `@pickhooks/sdk/abis`; the drand time-lock: `@pickhooks/sdk/tlock`; the sticky encoder alone: `@pickhooks/sdk/rules`; the rule catalog of coins with rules: `@pickhooks/sdk/coin-rules`.
|
|
299
408
|
|
|
300
409
|
## Examples
|
|
301
410
|
|
|
@@ -307,4 +416,4 @@ They send nothing without `--send`.
|
|
|
307
416
|
|
|
308
417
|
## Tests
|
|
309
418
|
|
|
310
|
-
`npm test` (offline: pool ids, ranges, building, errors, the rule compiler). On a local BSC fork (`scripts/fork.sh`, anvil) against the live contracts: `npm run fork-proof` (hook any coin and sticky rules) and `npm run fork-proof-2` (coins with rules, pools, dip bids, Lever, lever v1, curve calls, and the tax line, which it deploys on the fork from a throwaway key). `npm run fork-proof-infra` runs floors and the protected buy on the infra rehearsal fork (`script/infra/rehearsal-fork.sh`, contracts deployed there by a throwaway key) against a dev server of the site. `npm run check` confirms the rule catalogs and the building blocks catalog are the site's.
|
|
419
|
+
`npm test` (offline: pool ids, ranges, building, errors, the rule compiler, the time-lock against the site's copy). On a local BSC fork (`scripts/fork.sh`, anvil) against the live contracts: `npm run fork-proof` (hook any coin and sticky rules) and `npm run fork-proof-2` (coins with rules, pools, dip bids, Lever, lever v1, curve calls, and the tax line, which it deploys on the fork from a throwaway key). `npm run fork-proof-infra` runs floors and the protected buy on the infra rehearsal fork (`script/infra/rehearsal-fork.sh`, contracts deployed there by a throwaway key) against a dev server of the site. `npm run check` confirms the rule catalogs and the building blocks catalog are the site's, and that the agents catalog and the pilot's prompt behave like the site's and the keeper's. `node test/mainnet-read-agents.mjs` reads the agents, watch and wallet parts against mainnet (nothing sent); the fork proof of those parts lives with the MCP server (`mcp/test/fork-proof-agents.mjs`: launch, trades, a model's answer landing through the desk, veto, fire, the watchers seeing it all).
|