@bordrless/shared 0.8.0 → 0.10.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/dist/api.d.ts CHANGED
@@ -3,6 +3,8 @@
3
3
  * (`Amount`), dollar figures as numbers, times as unix seconds. A figure the backend could not
4
4
  * read is null, never zero.
5
5
  */
6
+ import type { RulesReadout } from './rules.ts';
7
+ import type { WorkshopReading } from './workshop.ts';
6
8
  export type Address = string;
7
9
  /** Base units, as a decimal string. */
8
10
  export type Amount = string;
@@ -100,6 +102,29 @@ export interface LaunchRulesInput {
100
102
  * token hook flags, and who can upgrade that program (null when it cannot be upgraded, or when it
101
103
  * has not been read). The site labels such a token "Custom hook, unverified" on every surface.
102
104
  */
105
+ /** A hook's code, upgrade authority and attestations read from the chain. checkedAt is Unix seconds. */
106
+ export interface HookRiskStatus {
107
+ status: 'available' | 'unavailable';
108
+ checkedAt: number;
109
+ class?: 'immutable' | 'timelocked' | 'managed' | 'author' | 'missing';
110
+ delaySecs?: number | null;
111
+ pending?: {
112
+ hash: string;
113
+ eta: number;
114
+ } | null;
115
+ audited?: 'current' | 'stale' | false;
116
+ blocked?: boolean;
117
+ provenance?: 'protocol' | 'studio' | 'unattested' | 'none';
118
+ studio?: {
119
+ buildHash: string;
120
+ simPass: boolean;
121
+ cutMaxBps: number;
122
+ current: boolean;
123
+ revoked?: boolean;
124
+ } | null;
125
+ severity: 'low' | 'medium' | 'high';
126
+ words: string;
127
+ }
103
128
  export interface CustomHookInfo {
104
129
  program: Address;
105
130
  flags: number;
@@ -109,6 +134,72 @@ export interface CustomHookInfo {
109
134
  upgradeable: boolean | null;
110
135
  /** What the hook does, for a hook Studio built (`HookAbout`); null (or absent) for any other, which the site describes from its flags. */
111
136
  about?: HookAbout | null;
137
+ /** Live code and attestation status, including hooks built outside Studio. */
138
+ risk?: HookRiskStatus | null;
139
+ /**
140
+ * Bordrless's own words for a Workshop hook (`HookReading`), filled on a launch's own page
141
+ * (`LaunchDetail`): null for a hook deployed outside the Workshop; absent from older servers and
142
+ * from lists.
143
+ */
144
+ workshop?: HookReading | null;
145
+ /**
146
+ * A composed hook's rule set (docs/rules-lane.md §4): the hook is the rules engine and the set is
147
+ * the `RuleSet` bound to the launch's config, as the chain holds it (`RulesReadout`: its bytes and
148
+ * what they say). The one place the set travels: `workshop` beside it is the synthetic reading
149
+ * (`lane: 'rules'`, the words alone). Null for any other hook, or a set that could not be read;
150
+ * absent from older servers and from lists.
151
+ */
152
+ rules?: RulesReadout | null;
153
+ /**
154
+ * Its SOL cut (`QuoteCutInfo`), read live from the launch on a launch's own page (`LaunchDetail`):
155
+ * null when the launch takes none or could not be read; absent from older servers and from lists.
156
+ */
157
+ quoteCut?: QuoteCutInfo | null;
158
+ }
159
+ /**
160
+ * A custom hook's SOL cut (the launchpad of 13 Oct: a config made with `create_quote_cut_config`): on
161
+ * a trade the launchpad asks the hook for a rate, at most its side's cap, and takes it from the
162
+ * trade's SOL with the creator fee (a buy's SOL in, a sell's SOL out). It takes no tokens, and a send
163
+ * pays none of it.
164
+ */
165
+ export interface QuoteCutInfo {
166
+ /** The caps, basis points of the trade's SOL (each at most 1,000). */
167
+ maxBuyBps: number;
168
+ maxSellBps: number;
169
+ /** SOL the cut has taken so far, lamports (part of the creator fees); '0' for a config, which has taken nothing. */
170
+ takenLamports: Amount;
171
+ }
172
+ /**
173
+ * Bordrless's own words for a custom hook or companion that came through the Workshop, wherever a
174
+ * launcher or a buyer meets it (the owner, 2026-10-12: the site reads and puts official wording from
175
+ * Bordrless's checks, like "it takes 2% of every sell by a wallet over $1,000"): the item (its page
176
+ * is /workshop/<id>), the AI's reading of its source (what it does, the most it takes, what to
177
+ * watch), the largest cut of one transfer the trading test measured (a hook; null for a companion,
178
+ * which has no trading test) and the security review's verdict (`pass`: no finding above low;
179
+ * `warn`: passed with notes; `fail`: only in the reading lane, where the words are shown anyway).
180
+ * Served for an item that is approved and deployed (the Workshop lane), or matched (the reading
181
+ * lane, docs/workshop.md "The reading lane": the builder deployed the program themselves, and the
182
+ * words show while the code on chain stays the build Bordrless checked). A composed hook
183
+ * (docs/rules-lane.md §4) answers a synthetic one: `lane` and `verdict` `rules`, its words read
184
+ * from the rule set bound to the config (the set itself is `customHook.rules`), no measured cut,
185
+ * and `workshopId` '' while it is not listed.
186
+ */
187
+ export interface HookReading {
188
+ workshopId: string;
189
+ name: string;
190
+ author: Address;
191
+ /** A hook on trades (a hook item, or a pair's hook half), or a companion on the creator fee (a companion item, or a pair's script half). */
192
+ kind: 'hook' | 'companion';
193
+ reading: WorkshopReading | null;
194
+ measuredCutBps: number | null;
195
+ /** `rules`: a composed hook's, read from its rules (no review, no build, no trading test). */
196
+ verdict: 'pass' | 'warn' | 'fail' | 'rules' | null;
197
+ /** Who approved it: the checks ('auto', a clean pass) or the operator; null for items approved before that was kept, and for the reading lane (nothing is approved). */
198
+ approvedBy?: 'auto' | 'operator' | null;
199
+ /** `workshop`: Bordrless deployed it under its own key; `reading`: its builder deployed it, and Bordrless read the source that matches it; `rules`: composed from Bordrless rules and run by the rules engine. Absent from older servers: `workshop`. */
200
+ lane?: 'workshop' | 'reading' | 'rules';
201
+ /** With a `fail` verdict: the titles of the review's first findings (the most severe first), for the site to say what failed. Absent otherwise. */
202
+ findings?: string[];
112
203
  }
113
204
  /**
114
205
  * Bordrless's official summary of a hook Studio deployed: written once by the assistant from the
@@ -139,6 +230,7 @@ export interface HookMeasured {
139
230
  */
140
231
  export interface HookAbout {
141
232
  program: Address;
233
+ risk?: HookRiskStatus | null;
142
234
  /** The Studio project's name, as its author called it. */
143
235
  title: string;
144
236
  /** Bordrless's summary; null until it is written (the site then says what the flags allow). */
@@ -176,8 +268,12 @@ export interface LaunchConfigData {
176
268
  creatorFeeBps: number;
177
269
  customHook: {
178
270
  program: Address;
179
- flags: number; /** As `CustomHookInfo.about`. */
271
+ flags: number;
272
+ /** As `CustomHookInfo.about`. */
180
273
  about?: HookAbout | null;
274
+ risk?: HookRiskStatus | null;
275
+ /** As `CustomHookInfo.rules`: a composed hook's rule set, read from the `RuleSet` bound to this config; null for any other hook or an unbound one. Absent from older servers. */
276
+ rules?: RulesReadout | null;
181
277
  } | null;
182
278
  label: string;
183
279
  }
@@ -209,10 +305,50 @@ export interface ConfigInspection {
209
305
  /**
210
306
  * The hook is a game hook made in Studio (docs/games.md "Phase 2"): its kind and the constants
211
307
  * its source fixes. The config then launches a jackpot or streak coin through the companion
212
- * (`companion.game` of that kind); null or absent for any other hook.
308
+ * (`companion.game` of that kind); null or absent for any other hook, and for a Workshop pair's
309
+ * hook (its own script stands in for the game companion: `requiredCompanion`).
213
310
  */
214
311
  game?: import('./studio.ts').StudioGameSettings | null;
312
+ /**
313
+ * The companion a launch of this config must come with (the shape the on-chain `LaunchConfig`
314
+ * field will take, docs/HANDOFF-2026-10-12.md §4.5): `game` when the config's hook is a game hook
315
+ * (what `game` says), `script` when its hook belongs to a Workshop pair (docs/workshop.md
316
+ * "Pairs": the launch sends `companion.script` with that program, or is refused
317
+ * `companion_required`), else `none`. Absent from older servers.
318
+ */
319
+ requiredCompanion?: RequiredCompanion;
320
+ /**
321
+ * Bordrless's own words for the config's custom hook (`HookReading`) when it is a Workshop hook
322
+ * (or a pair's hook) that is approved and deployed, or a composed hook's synthetic reading
323
+ * (`lane: 'rules'`; its set is `config.customHook.rules`); null for a hook deployed outside the
324
+ * Workshop, one no longer approved, or the rules engine with no set bound. Absent from older servers.
325
+ */
326
+ hook?: HookReading | null;
215
327
  }
328
+ /** What a config's launch must come with: nothing in particular, a game of a kind, or a Workshop pair's script. */
329
+ export type RequiredCompanion = {
330
+ kind: 'none';
331
+ } | {
332
+ kind: 'game';
333
+ game: GameKindName;
334
+ } | {
335
+ kind: 'script';
336
+ /** The pair's companion script program: what `companion.script.program` must be (a preset's: the script its launch request names, `companion.lossCover` for Lossback). */
337
+ program: Address;
338
+ /** The pair's Workshop item (its page is /workshop/<id>), its name, its reading's title and its author. A Bordrless preset (`preset`) has no item and no author: both null. */
339
+ workshopId: string | null;
340
+ name: string;
341
+ title: string | null;
342
+ author: Address | null;
343
+ /** A Bordrless preset the config's hook belongs to: `lossCover` (docs/loss-cover.md; the site says Lossback), whose launch request is `companion.lossCover`, not `companion.script`. Absent for a pair and from older servers. */
344
+ preset?: 'lossCover';
345
+ /** Bordrless's reading of the pair (one for both halves), as `HookReading.reading`. Absent from older servers. */
346
+ reading?: WorkshopReading | null;
347
+ /** A companion script has no trading test: never a measured cut. */
348
+ measuredCutBps?: null;
349
+ /** The script half's security review verdict, as `HookReading.verdict`. Absent from older servers. */
350
+ verdict?: 'pass' | 'warn' | null;
351
+ };
216
352
  /** Live figures of a launch's token rules; each null when the launch lacks the rule or it is not tracked. */
217
353
  export interface RuleStats {
218
354
  /** Lamports distributed to holders as holder rewards, all time. */
@@ -257,6 +393,8 @@ export interface ProgramInfo {
257
393
  /** Phase 3a: present (true) when the upgrade authority is the program's own `hook_timelock` account. */
258
394
  timelocked?: boolean;
259
395
  }
396
+ /** Who a launch's creator fee goes to, read from the chain (docs/companions.md "Who may hold a launch's creator fee on the site"): a wallet, the companion program's pot, a program nobody can upgrade (shown, labelled), or a program someone can still upgrade (the launch is hidden). Null until read. */
397
+ export type CreatorKind = 'wallet' | 'companion' | 'program' | 'program-immutable';
260
398
  export interface LaunchSummary {
261
399
  mint: Address;
262
400
  name: string;
@@ -264,6 +402,8 @@ export interface LaunchSummary {
264
402
  image: string | null;
265
403
  description: string;
266
404
  creator: Address;
405
+ /** Who the creator fee goes to; absent from older servers. */
406
+ creatorKind?: CreatorKind | null;
267
407
  pool: Address;
268
408
  status: LaunchStatus;
269
409
  createdAt: number;
@@ -305,6 +445,8 @@ export interface LaunchSummary {
305
445
  config: Address | null;
306
446
  /** The creator's own token hook (§5.8); null when the mint's hook is the kit or none. */
307
447
  customHook: CustomHookInfo | null;
448
+ /** The program that is this launch's creator (docs/companions.md), as a list names it: null for a launch whose creator is a wallet; absent from an older backend. `LaunchDetail.companion` has its live figures. */
449
+ companionTag?: CompanionTag | null;
308
450
  /** How Bordrless is paid on this launch's pool: 'share' (a share of what the rules collect, `protocolShareBps`) or 'flat' (`protocolFeeBps` of the quote). */
309
451
  protocolModel: ProtocolModel;
310
452
  /** Under the share model, Bordrless's share of the cuts in basis points (2,500 = a quarter); null under the flat model. */
@@ -352,7 +494,8 @@ export interface LaunchDetail extends LaunchSummary {
352
494
  /** `GET /v1/launches?sort=`: newest first by default; `rewards24h` most paid to holders in 24 h first; `fees` lowest buy-then-sell fee first. */
353
495
  export type LaunchSort = 'new' | 'mcap' | 'volume' | 'trending' | 'graduated' | 'rewards24h' | 'fees';
354
496
  /** `GET /v1/launches?rules=a,b`: only launches that have every rule listed (`custom_hook`: launched with a creator's own hook). */
355
- export type RuleFilter = 'rewards' | 'burn' | 'max_wallet' | 'creator_lock' | 'early_lock' | 'custom_hook';
497
+ /** The board's filters: kit rules, and the pre-built hooks by name (2026-10-12: Snowball, the Jackpot draw, Half-Life, buy back & burn, the Workshop's last-buyer and streak games, Lossback as `loss_cover`). `custom_hook` stays for older links. */
498
+ export type RuleFilter = 'rewards' | 'burn' | 'max_wallet' | 'creator_lock' | 'early_lock' | 'custom_hook' | 'snowball' | 'jackpot' | 'last_buyer' | 'streak' | 'half_life' | 'buyback' | 'loss_cover';
356
499
  export interface LaunchList {
357
500
  launches: LaunchSummary[];
358
501
  total: number;
@@ -583,14 +726,286 @@ export interface LaunchPrepareRequest {
583
726
  * preset splits by name; with `game`, a lottery coin (docs/games.md): the split's holders' share is
584
727
  * then 0 and the pot's part (`game.potBps`) makes the four add up to 10,000.
585
728
  */
586
- export type CompanionRequest = {
729
+ export type CompanionRequest = ({
587
730
  split: CompanionSplitBps;
588
731
  vestDays?: number;
589
732
  game?: GameRequest;
733
+ snowball?: SnowballRequest;
734
+ script?: ScriptRequest;
735
+ lossCover?: LossCoverRequest;
590
736
  } | {
591
737
  template: CompanionTemplate;
592
738
  vestDays?: number;
593
- };
739
+ }) & CompanionExtras;
740
+ /**
741
+ * What any companion request may add (2026-10-13, docs/payees-and-wallet-payouts.md), each set once
742
+ * before the launch, the mint signing:
743
+ * - `payees`: up to 10 wallets that share the launcher's part of the creator fee (the split's
744
+ * `beneficiaryBps`), each a fixed share of that part (1 to 10,000 basis points, 10,000 in all at
745
+ * most); the launcher keeps the rest. Not the launcher, the companion or its creator address, each
746
+ * named once. Bounds: `payeesProblem`. The setup carries `set_payees`, in its own transaction when
747
+ * the setup leaves no room (a Lossback or custom hook's setup).
748
+ * - `allowWalletPayouts`: a custom hook's script with payout terms (`script.payout`, made with
749
+ * `create_script_v2`) may also pay any wallet SOL from the pot, within those terms. Refused
750
+ * (`companion_rules`) on any other companion: `walletPayoutsProblem`.
751
+ */
752
+ export interface CompanionExtras {
753
+ payees?: PayeeRequest[];
754
+ allowWalletPayouts?: boolean;
755
+ }
756
+ /** A wallet that shares the launcher's part of the creator fee (`set_payees`): its share of that part, basis points. */
757
+ export interface PayeeRequest {
758
+ wallet: Address;
759
+ bps: number;
760
+ }
761
+ /** A payee as the token page shows it (`CompanionSummary.payees`): its share of the launcher's part, what it was paid and what it is owed (its account could not take it yet), lamports. */
762
+ export interface PayeeSummary {
763
+ wallet: Address;
764
+ bps: number;
765
+ paid: Amount;
766
+ owed: Amount;
767
+ }
768
+ /**
769
+ * A Lossback coin as the launch request names it (docs/loss-cover.md; the programs and the policy
770
+ * say Loss cover): the companion's pot pays every holder under water the same share of what they
771
+ * are down, in rounds of `roundSecs`, once the pot holds `minPotLamports`; a holding counts from
772
+ * `minHolding` base units and gets `coverBps` of its loss covered when the pot can. The split's
773
+ * buyback and holders' parts are 0; the pot's part is what the split's launcher part leaves
774
+ * (10,000 with a launcher part of 0). Everything else (the step, the shares per step, holding and
775
+ * round, the least loss, the wait after a buy) is fixed by `LOSS_COVER_DEFAULTS`. Bounds:
776
+ * `lossCoverProblem`. Refused (`companion_rules`) beside a game, a Snowball or a script, and
777
+ * (`loss_cover_off`) while Lossback launches are closed or the creator fee has no config.
778
+ */
779
+ export interface LossCoverRequest {
780
+ roundSecs: number;
781
+ minPotLamports: Amount;
782
+ coverBps: number;
783
+ minHolding: Amount;
784
+ }
785
+ /**
786
+ * The terms a Lossback coin runs on, as the chain holds them: the script's six (`CoverState`:
787
+ * `coverBps`, `minHolding`, `minLossLamports`, `minAgeSecs`, `roundSecs`, `minPotLamports`), the
788
+ * companion's payout terms (`PayoutTerms`: `stepBps`, `holdingBps`, `roundBps` is `window_bps`,
789
+ * the window is the round) and the step (`Script.interval`).
790
+ */
791
+ export interface LossCoverTerms {
792
+ roundSecs: number;
793
+ stepSecs: number;
794
+ stepBps: number;
795
+ holdingBps: number;
796
+ roundBps: number;
797
+ coverBps: number;
798
+ minHolding: Amount;
799
+ minLossLamports: Amount;
800
+ minAgeSecs: number;
801
+ minPotLamports: Amount;
802
+ }
803
+ /** A Lossback coin's figures as its token page shows them (`CompanionSummary.lossCover`), read from the chain and the indexer's payouts. */
804
+ export interface LossCoverSummary {
805
+ /** The hook program, its state for the mint (`["state", mint]`), the script program, its state (`["script-state", mint]`) and the payout terms (`["payout-terms", mint]`). */
806
+ hook: Address;
807
+ hookState: Address;
808
+ script: Address;
809
+ scriptState: Address;
810
+ payoutTerms: Address;
811
+ /** The pot (`Companion.pendingPot`), lamports. */
812
+ pot: Amount;
813
+ /** Lamports paid to holders all time, and entries recorded all time (touches included), the terms'. */
814
+ paidTotal: Amount;
815
+ payouts: number;
816
+ /** Distinct holdings paid above 0 so far (the indexer's `script_payouts`). */
817
+ holdersCovered: number;
818
+ /** The round the script last stepped in (0 before the first), and the round the clock is in now. */
819
+ round: number;
820
+ currentRound: number;
821
+ /** The share of its uncovered loss each holder is paid this round: `min(10,000, b / l_prev)` in basis points; 0 in a round that only measures. */
822
+ roundShareBps: number;
823
+ /** The round's budget (the pot at its first step), what it has paid and what is left. */
824
+ roundBudget: Amount;
825
+ roundPaid: Amount;
826
+ roundBudgetLeft: Amount;
827
+ /** The uncovered loss measured over the previous round (what this round's share is computed from) and so far this round. */
828
+ lossPrev: Amount;
829
+ lossCur: Amount;
830
+ /** Holdings measured this round, and rounds stepped so far. */
831
+ measured: number;
832
+ rounds: number;
833
+ /** When the round the script last stepped in began (0 before the first), when the current round ends, when a holder was last paid (0: never), when the next step may run. */
834
+ lastRoundAt: number;
835
+ nextRoundAt: number;
836
+ lastPaidAt: number;
837
+ nextStepAt: number;
838
+ /** Whether the pot holds the least a round starts with. */
839
+ minPotMet: boolean;
840
+ terms: LossCoverTerms;
841
+ }
842
+ /**
843
+ * `GET /v1/companion/:mint/cover/:owner`: one holder's own cover on a Lossback coin, from the
844
+ * holding's record (the hook data), the pool's price now and the script's round.
845
+ */
846
+ export interface LossCoverHoldingSummary {
847
+ owner: Address;
848
+ holding: Address;
849
+ /** Whether the owner holds the token (a holding with a record); every figure is 0 without one. */
850
+ holds: boolean;
851
+ /** Tokens held, base units; the tokens the record covers (the balance as of its last write). */
852
+ balance: Amount;
853
+ recorded: Amount;
854
+ /** The average entry price (lamports per base unit times 10^12) and in SOL per whole token; the pool's price now the same way. */
855
+ entry: Amount;
856
+ entrySolPerToken: number;
857
+ spot: Amount;
858
+ spotSolPerToken: number;
859
+ /** Lamports the holding is down (0 above water), the part the cover applies to, what it has been paid, and what it is still owed. */
860
+ loss: Amount;
861
+ covered: Amount;
862
+ paid: Amount;
863
+ owed: Amount;
864
+ /** What the current round would pay it at the round's share, lamports (0 in a measuring round, or when not eligible). */
865
+ payNow: Amount;
866
+ /** Whether a step would take it now, and why not in one sentence. */
867
+ eligible: boolean;
868
+ reason: string | null;
869
+ /** The round it was last measured or paid in (0: never), whether that is the current round, and when the holding's wait after its last buy ends. */
870
+ lastRound: number;
871
+ paidThisRound: boolean;
872
+ countsFrom: number;
873
+ /** The current round, and when it ends. */
874
+ round: number;
875
+ nextRoundAt: number;
876
+ }
877
+ /**
878
+ * A custom companion as the launch request names it (2026-10-12, docs/scripts.md): a Workshop
879
+ * script (`program`, a companion item that Bordrless approved, deployed and approved on chain)
880
+ * decides what the companion's pot does. The pot is `potBps` of every creator-fee claim (with the
881
+ * split's parts it adds up to 10,000); the companion calls the script's `companion_step` at most
882
+ * once every `interval` seconds (10 to a day), from a minute after the launch; `initData` is what
883
+ * the script's `companion_init` gets once (base64 or hex, at most 512 bytes; empty for none) and
884
+ * `stateLen` the size of the state the companion makes for it (0 to 10,240 bytes; the Workshop
885
+ * item's reading says what the script needs). Bounds: `scriptProblem`. Refused (`companion_rules`)
886
+ * beside a game or a Snowball, and (`script_not_approved`) when the program is not an approved,
887
+ * deployed Workshop companion whose on-chain approval holds.
888
+ */
889
+ export interface ScriptRequest {
890
+ potBps: number;
891
+ program: Address;
892
+ interval: number;
893
+ initData: string;
894
+ stateLen: number;
895
+ /** Payout terms (2026-10-13): the script is made with `create_script_v2`, its payouts bound by them; absent, `create_script` (no payouts). Bounds: `scriptProblem`. */
896
+ payout?: PayoutTermsRequest;
897
+ }
898
+ /**
899
+ * A script's payout terms as a launch request names them (the companion's `PayoutTerms`, made by
900
+ * `create_script_v2`): the most one step pays (`stepBps` of the pot at the step's start), the most
901
+ * one holding or wallet gets of a step's budget (`holdingBps`), and the most a window pays
902
+ * (`windowBps` of the pot at the window's first step), the window `windowSecs` long (10 s to a day).
903
+ */
904
+ export interface PayoutTermsRequest {
905
+ stepBps: number;
906
+ holdingBps: number;
907
+ windowBps: number;
908
+ windowSecs: number;
909
+ }
910
+ /** A custom companion's script as its token page shows it (`CompanionSummary.script`), read from the chain and the Workshop. */
911
+ export interface ScriptSummary {
912
+ /** Its account, `PDA(["script", mint])` under the companion program. */
913
+ address: Address;
914
+ /** The script program (a Workshop companion item's, deployed under Bordrless's key). */
915
+ program: Address;
916
+ /** Its author, paid half of what every fee claim takes from the launch; null when none (or the author launched it themselves: no extra share). */
917
+ author: Address | null;
918
+ /** The least time between steps, seconds. */
919
+ interval: number;
920
+ /** When it last stepped (unix seconds; 0: not yet). */
921
+ lastAt: number;
922
+ /** When the next step may run (a minute after the launch at the earliest). */
923
+ nextStepAt: number;
924
+ /** Steps run so far. */
925
+ steps: number;
926
+ /** SOL the script may spend (the companion's pot), lamports. */
927
+ pot: Amount;
928
+ /** The pot's part of every fee claim. */
929
+ potBps: number;
930
+ /** What the author has been paid so far, lamports. */
931
+ authorPaid: Amount;
932
+ /** The size of the script's state the companion made, bytes (0: none). */
933
+ stateLen: number;
934
+ /** The Workshop item it came from: its id (its page is /workshop/<id>), name and the AI reading's title; null for a script approved outside the Workshop. */
935
+ workshopId: string | null;
936
+ name: string | null;
937
+ title: string | null;
938
+ /**
939
+ * Whether Bordrless checked and approved the code: a Workshop script. False for an immutable
940
+ * program launched unreviewed (docs/scripts.md "Unreviewed scripts": no Workshop item, no author,
941
+ * no author's share), which the site names "Custom hook (unreviewed)". Absent from older servers.
942
+ */
943
+ reviewed?: boolean;
944
+ /** Bordrless's reading of the Workshop item it came from (`HookReading.reading`); null for a script outside the Workshop. Absent from older servers. */
945
+ reading?: WorkshopReading | null;
946
+ /** The security review's verdict of that item (`HookReading.verdict`; `fail` only in the reading lane); null for a script outside the Workshop. Absent from older servers. */
947
+ verdict?: 'pass' | 'warn' | 'fail' | null;
948
+ /**
949
+ * `reading` when the script was deployed by its builder (immutable, outside the Workshop) and a
950
+ * reading-lane item matches its code: Bordrless's words show with `reviewed` false. Absent for a
951
+ * Workshop script and from older servers.
952
+ */
953
+ lane?: 'workshop' | 'reading';
954
+ /** Its payout terms let it pay any wallet SOL from the pot (`allow_wallet_payouts`, `PayoutTerms.reserved[0]`, 2026-10-13); absent otherwise and from older servers. */
955
+ walletPayouts?: true;
956
+ }
957
+ /**
958
+ * A Snowball companion as the launch request names it (2026-10-12): the companion's part of every
959
+ * creator fee claim (`potBps`; with the split's parts it adds up to 10,000) fills a pot that makes
960
+ * volume in the token on its own pool, once every `interval` seconds: a buy of `buyBps` of the pot
961
+ * when the price falls `buyStepBps` below its reference, a sell of `sellBps` of its tokens when it
962
+ * rises `sellStepBps` above, and with `flatTrades` a trade anyway when it hasn't moved (on the side
963
+ * that rebalances what it holds). One trade moves at most `poolBps` of the pool's SOL side. The
964
+ * presets are `SNOWBALL_PRESETS`; bounds `snowballProblem`.
965
+ */
966
+ export interface SnowballRequest {
967
+ potBps: number;
968
+ buyStepBps: number;
969
+ sellStepBps: number;
970
+ buyBps: number;
971
+ sellBps: number;
972
+ poolBps: number;
973
+ interval: number;
974
+ flatTrades: boolean;
975
+ }
976
+ /** A Snowball's terms without its part of the fee: what a preset sets and the custom controls change. */
977
+ export type SnowballTerms = Omit<SnowballRequest, 'potBps'>;
978
+ /** A Snowball's market maker as its token page shows it (`CompanionSummary.snowball`), read from the chain. */
979
+ export interface SnowballSummary {
980
+ /** Its account, `PDA(["snowball", mint])` under the companion program. */
981
+ address: Address;
982
+ buyStepBps: number;
983
+ sellStepBps: number;
984
+ buyBps: number;
985
+ sellBps: number;
986
+ /** The most one trade moves, as a share of the pool's SOL side. */
987
+ poolBps: number;
988
+ /** The least time between trades, seconds. */
989
+ interval: number;
990
+ /** It trades every interval even when the price hasn't moved. */
991
+ flatTrades: boolean;
992
+ /** SOL it holds to buy with (the companion's pot), lamports. */
993
+ pot: Amount;
994
+ /** Tokens it holds to sell, base units. */
995
+ tokensHeld: Amount;
996
+ /** The next buy waits for the price at or below `buyBelow`, the next sell at or above `sellAbove` (SOL per whole token). */
997
+ buyBelow: number;
998
+ sellAbove: number;
999
+ buys: number;
1000
+ sells: number;
1001
+ /** SOL spent on buys and received from sells, lamports; tokens bought and sold, base units. */
1002
+ solSpent: Amount;
1003
+ solReceived: Amount;
1004
+ tokensBought: Amount;
1005
+ tokensSold: Amount;
1006
+ /** When it last traded or followed the price (unix seconds; 0: not yet). */
1007
+ lastAt: number;
1008
+ }
594
1009
  /** The kinds of game a companion runs (the companion's `GameKind`): the lottery (phase 1), the last-buyer jackpot and the holding streak (phase 2). */
595
1010
  export type GameKindName = 'lottery' | 'jackpot' | 'streak' | 'strategy';
596
1011
  /**
@@ -864,6 +1279,24 @@ export interface CompanionSplitBps {
864
1279
  /** Paid to the launcher (the beneficiary), in SOL. */
865
1280
  beneficiaryBps: number;
866
1281
  }
1282
+ /**
1283
+ * A launch's companion as a list names it (2026-10-12): what takes its creator fee, fixed at launch, without
1284
+ * the live figures (`CompanionSummary` has those), so a card can say "Snowball 2%" without reading the chain.
1285
+ */
1286
+ export interface CompanionTag {
1287
+ split: CompanionSplitBps;
1288
+ /** The game it runs and the pot's part of every fee claim; null without a game. */
1289
+ game: {
1290
+ kind: GameKindName;
1291
+ potBps: number;
1292
+ } | null;
1293
+ /** A Snowball: its pot makes a market in the token (its part of the fee is what the split leaves). */
1294
+ snowball: boolean;
1295
+ /** A custom companion (2026-10-12): a Workshop script spends its pot. Absent from tags stored before scripts. */
1296
+ script?: boolean;
1297
+ /** A Lossback coin (docs/loss-cover.md): its script is the Loss cover script. Absent from tags stored before Lossback, and from every other tag. */
1298
+ lossCover?: boolean;
1299
+ }
867
1300
  /** A launch's companion as its token page shows it (`LaunchDetail.companion`): lamports and token base units as strings. */
868
1301
  export interface CompanionSummary {
869
1302
  /** The companion's account, `PDA(["companion", mint])` under the companion program. */
@@ -900,6 +1333,14 @@ export interface CompanionSummary {
900
1333
  nextBuybackAt: number | null;
901
1334
  /** The lottery this companion runs (docs/games.md): its settings and the hook's terms; null for a companion without a game. */
902
1335
  game: GameSummary | null;
1336
+ /** A Snowball's market maker (2026-10-12); null for any other companion. */
1337
+ snowball: SnowballSummary | null;
1338
+ /** A custom companion's script (2026-10-12, docs/scripts.md); null for any other companion; absent from older servers. */
1339
+ script?: ScriptSummary | null;
1340
+ /** A Lossback coin's figures (docs/loss-cover.md); null for any other companion (a Lossback coin's `script` is set too); absent from older servers. */
1341
+ lossCover?: LossCoverSummary | null;
1342
+ /** The wallets that share the launcher's part (`set_payees`, 2026-10-13); null for a companion without payees (or whose payees can't be read); absent from older servers. */
1343
+ payees?: PayeeSummary[] | null;
903
1344
  }
904
1345
  /**
905
1346
  * `GET /v1/companion/:mint`: a mint's companion as a launch that may not have finished needs it.
@@ -915,6 +1356,10 @@ export interface CompanionStatus {
915
1356
  refundable: Amount | null;
916
1357
  /** The lottery this companion runs, live (docs/games.md), the caller's tickets with `?wallet=`; null for a companion without a game (absent from older servers). */
917
1358
  game?: GameStatus | null;
1359
+ /** A custom companion's script, once launched (docs/scripts.md); null for any other companion (absent from older servers, and before the launch). */
1360
+ script?: ScriptSummary | null;
1361
+ /** A Lossback coin's figures, once launched (docs/loss-cover.md); null for any other companion (absent from older servers, and before the launch). */
1362
+ lossCover?: LossCoverSummary | null;
918
1363
  }
919
1364
  /** `POST /v1/companion/refund/prepare`: a companion's funding back to the wallet that set it up, for a launch that never happened. The mint's key signs it after the wallet. */
920
1365
  export interface CompanionRefundRequest {
@@ -1135,6 +1580,140 @@ export interface LiquidityPrepareResponse {
1135
1580
  transactions: PreparedTx[];
1136
1581
  quote: LiquidityQuote;
1137
1582
  }
1583
+ /** Which of a mint's four authorities (`set_authority`'s kinds). */
1584
+ export type MintAuthorityKind = 'mint' | 'freeze' | 'hook' | 'metadata';
1585
+ /** One fact of a mint's risk label (docs/dex.md §6.2), in the words every surface uses. */
1586
+ export interface MintRiskReason {
1587
+ kind: 'hook_missing' | 'hook_authority' | 'freeze_authority' | 'mint_authority' | 'hook' | 'metadata_authority' | 'fixed';
1588
+ severity: 'low' | 'medium' | 'high';
1589
+ words: string;
1590
+ }
1591
+ /** A mint's risk label: the highest severity, its first sentence, every reason, and the authorities still held (and by whom). */
1592
+ export interface MintRisk {
1593
+ severity: 'low' | 'medium' | 'high';
1594
+ words: string;
1595
+ reasons: MintRiskReason[];
1596
+ /** The authorities still set on the mint, each with its key. */
1597
+ held: {
1598
+ kind: MintAuthorityKind;
1599
+ authority: Address;
1600
+ }[];
1601
+ }
1602
+ /** The base token of a pool to be created, as the mint account has it. */
1603
+ export interface PoolCreateToken {
1604
+ mint: Address;
1605
+ symbol: string;
1606
+ name: string;
1607
+ decimals: number;
1608
+ image: string | null;
1609
+ supply: Amount;
1610
+ /** 0 when unlimited. */
1611
+ maxSupply: Amount;
1612
+ creator: Address;
1613
+ hookProgram: Address | null;
1614
+ /** How the site names it (from addresses, never from names): a launch of the launchpad, a bridged asset, or a free mint. */
1615
+ identity: 'launch' | 'bridged' | 'free';
1616
+ }
1617
+ /** A pool of the same pair that exists already: the depth, the price and the tier. */
1618
+ export interface ExistingPool {
1619
+ pool: Address;
1620
+ lpFeeBps: number;
1621
+ hookProgram: Address | null;
1622
+ /** The launchpad made it: its launch pool. */
1623
+ launch: boolean;
1624
+ curve: boolean;
1625
+ baseReserve: Amount;
1626
+ quoteReserve: Amount;
1627
+ /** Whole quote per whole token; null while the pool has no reserves. */
1628
+ priceQuote: number | null;
1629
+ tvlUsd: number | null;
1630
+ }
1631
+ export interface PoolCreateQuoteRequest {
1632
+ baseMint: Address;
1633
+ /** One of `POOL_FEE_TIERS_BPS`. */
1634
+ lpFeeBps: number;
1635
+ /** The wallet, for its balances; the quote stands without one. */
1636
+ owner?: Address;
1637
+ /** Base units of the token to deposit. */
1638
+ baseAmount?: Amount;
1639
+ /** Lamports of SOL (bridged in the same transaction) to deposit. */
1640
+ quoteAmount?: Amount;
1641
+ }
1642
+ /** The first deposit as quoted: the price it sets, the LP it mints and the FDV it implies. */
1643
+ export interface PoolCreateDeposit {
1644
+ baseAmount: Amount;
1645
+ quoteAmount: Amount;
1646
+ /** `isqrt(base · quote) − 1,000`, 9 decimals. */
1647
+ lpAmount: Amount;
1648
+ /** Whole SOL per whole token. */
1649
+ priceQuote: number;
1650
+ /** Fully diluted value in lamports (the price times `maxSupply`, or `supply` when unlimited), as a decimal string. */
1651
+ fdvLamports: Amount;
1652
+ fdvUsd: number | null;
1653
+ }
1654
+ export interface PoolCreateQuote {
1655
+ token: PoolCreateToken;
1656
+ quoteMint: Address;
1657
+ quoteSymbol: string;
1658
+ quoteDecimals: number;
1659
+ lpFeeBps: number;
1660
+ /** The DEX config's flat protocol rate of the quote side, which the new pool copies at creation. */
1661
+ protocolFeeBps: number;
1662
+ /** The pool this pair, tier and no hook would live at. */
1663
+ pool: Address;
1664
+ lpMint: Address;
1665
+ /** That pool, when it exists already (the form then offers to add liquidity instead). */
1666
+ exists: ExistingPool | null;
1667
+ /** Every other pool of the pair (the launch pool, other tiers, hooked ones), deepest first. */
1668
+ otherPools: ExistingPool[];
1669
+ /** The wallet's balances, with an owner. */
1670
+ balances: {
1671
+ lamports: Amount;
1672
+ base: Amount;
1673
+ bridgedSol: Amount;
1674
+ } | null;
1675
+ deposit: PoolCreateDeposit | null;
1676
+ risk: MintRisk;
1677
+ /** Rent the creator pays for the new accounts (the pool, the LP mint, two vaults, the LP holding, and the quote holding when missing). */
1678
+ rentLamports: Amount;
1679
+ solUsd: number | null;
1680
+ }
1681
+ export interface PoolCreatePrepareRequest {
1682
+ owner: Address;
1683
+ baseMint: Address;
1684
+ lpFeeBps: number;
1685
+ baseAmount: Amount;
1686
+ quoteAmount: Amount;
1687
+ /** Burn the LP in a second transaction, a permanent lock (docs/dex.md §5.1). */
1688
+ burnLp?: boolean;
1689
+ }
1690
+ export interface PoolCreatePrepareResponse {
1691
+ transactions: PreparedTx[];
1692
+ quote: PoolCreateQuote;
1693
+ pool: Address;
1694
+ lpMint: Address;
1695
+ }
1696
+ /** Burn LP of a pool the wallet holds: all of it, or `amount` (9 decimals). */
1697
+ export interface LpBurnPrepareRequest {
1698
+ owner: Address;
1699
+ pool: Address;
1700
+ amount?: Amount;
1701
+ }
1702
+ export interface LpBurnPrepareResponse {
1703
+ transactions: PreparedTx[];
1704
+ /** LP burned, 9 decimals. */
1705
+ amount: Amount;
1706
+ }
1707
+ /** Revoke authorities the wallet holds on a mint, for ever (`set_authority(kind, None)` for each). */
1708
+ export interface AuthorityPrepareRequest {
1709
+ owner: Address;
1710
+ mint: Address;
1711
+ kinds: MintAuthorityKind[];
1712
+ }
1713
+ export interface AuthorityPrepareResponse {
1714
+ transactions: PreparedTx[];
1715
+ kinds: MintAuthorityKind[];
1716
+ }
1138
1717
  export interface ApiErrorBody {
1139
1718
  error: string;
1140
1719
  code?: string;