@bordrless/shared 0.7.0 → 0.9.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,7 @@
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 { WorkshopReading } from './workshop.ts';
6
7
  export type Address = string;
7
8
  /** Base units, as a decimal string. */
8
9
  export type Amount = string;
@@ -100,6 +101,29 @@ export interface LaunchRulesInput {
100
101
  * token hook flags, and who can upgrade that program (null when it cannot be upgraded, or when it
101
102
  * has not been read). The site labels such a token "Custom hook, unverified" on every surface.
102
103
  */
104
+ /** A hook's code, upgrade authority and attestations read from the chain. checkedAt is Unix seconds. */
105
+ export interface HookRiskStatus {
106
+ status: 'available' | 'unavailable';
107
+ checkedAt: number;
108
+ class?: 'immutable' | 'timelocked' | 'managed' | 'author' | 'missing';
109
+ delaySecs?: number | null;
110
+ pending?: {
111
+ hash: string;
112
+ eta: number;
113
+ } | null;
114
+ audited?: 'current' | 'stale' | false;
115
+ blocked?: boolean;
116
+ provenance?: 'protocol' | 'studio' | 'unattested' | 'none';
117
+ studio?: {
118
+ buildHash: string;
119
+ simPass: boolean;
120
+ cutMaxBps: number;
121
+ current: boolean;
122
+ revoked?: boolean;
123
+ } | null;
124
+ severity: 'low' | 'medium' | 'high';
125
+ words: string;
126
+ }
103
127
  export interface CustomHookInfo {
104
128
  program: Address;
105
129
  flags: number;
@@ -109,6 +133,42 @@ export interface CustomHookInfo {
109
133
  upgradeable: boolean | null;
110
134
  /** What the hook does, for a hook Studio built (`HookAbout`); null (or absent) for any other, which the site describes from its flags. */
111
135
  about?: HookAbout | null;
136
+ /** Live code and attestation status, including hooks built outside Studio. */
137
+ risk?: HookRiskStatus | null;
138
+ /**
139
+ * Bordrless's own words for a Workshop hook (`HookReading`), filled on a launch's own page
140
+ * (`LaunchDetail`): null for a hook deployed outside the Workshop; absent from older servers and
141
+ * from lists.
142
+ */
143
+ workshop?: HookReading | null;
144
+ }
145
+ /**
146
+ * Bordrless's own words for a custom hook or companion that came through the Workshop, wherever a
147
+ * launcher or a buyer meets it (the owner, 2026-10-12: the site reads and puts official wording from
148
+ * Bordrless's checks, like "it takes 2% of every sell by a wallet over $1,000"): the item (its page
149
+ * is /workshop/<id>), the AI's reading of its source (what it does, the most it takes, what to
150
+ * watch), the largest cut of one transfer the trading test measured (a hook; null for a companion,
151
+ * which has no trading test) and the security review's verdict (`pass`: no finding above low;
152
+ * `warn`: passed with notes; `fail`: only in the reading lane, where the words are shown anyway).
153
+ * Served for an item that is approved and deployed (the Workshop lane), or matched (the reading
154
+ * lane, docs/workshop.md "The reading lane": the builder deployed the program themselves, and the
155
+ * words show while the code on chain stays the build Bordrless checked).
156
+ */
157
+ export interface HookReading {
158
+ workshopId: string;
159
+ name: string;
160
+ author: Address;
161
+ /** 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). */
162
+ kind: 'hook' | 'companion';
163
+ reading: WorkshopReading | null;
164
+ measuredCutBps: number | null;
165
+ verdict: 'pass' | 'warn' | 'fail' | null;
166
+ /** 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). */
167
+ approvedBy?: 'auto' | 'operator' | null;
168
+ /** `workshop`: Bordrless deployed it under its own key; `reading`: its builder deployed it, and Bordrless read the source that matches it. Absent from older servers: `workshop`. */
169
+ lane?: 'workshop' | 'reading';
170
+ /** 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. */
171
+ findings?: string[];
112
172
  }
113
173
  /**
114
174
  * Bordrless's official summary of a hook Studio deployed: written once by the assistant from the
@@ -139,6 +199,7 @@ export interface HookMeasured {
139
199
  */
140
200
  export interface HookAbout {
141
201
  program: Address;
202
+ risk?: HookRiskStatus | null;
142
203
  /** The Studio project's name, as its author called it. */
143
204
  title: string;
144
205
  /** Bordrless's summary; null until it is written (the site then says what the flags allow). */
@@ -178,6 +239,7 @@ export interface LaunchConfigData {
178
239
  program: Address;
179
240
  flags: number; /** As `CustomHookInfo.about`. */
180
241
  about?: HookAbout | null;
242
+ risk?: HookRiskStatus | null;
181
243
  } | null;
182
244
  label: string;
183
245
  }
@@ -206,7 +268,52 @@ export interface ConfigInspection {
206
268
  authorShareBps: number;
207
269
  /** The hook was built and deployed by Studio: the launch prepares it for the mint itself (its standard `prepare`). */
208
270
  studioHook?: boolean;
271
+ /**
272
+ * The hook is a game hook made in Studio (docs/games.md "Phase 2"): its kind and the constants
273
+ * its source fixes. The config then launches a jackpot or streak coin through the companion
274
+ * (`companion.game` of that kind); null or absent for any other hook, and for a Workshop pair's
275
+ * hook (its own script stands in for the game companion: `requiredCompanion`).
276
+ */
277
+ game?: import('./studio.ts').StudioGameSettings | null;
278
+ /**
279
+ * The companion a launch of this config must come with (the shape the on-chain `LaunchConfig`
280
+ * field will take, docs/HANDOFF-2026-10-12.md §4.5): `game` when the config's hook is a game hook
281
+ * (what `game` says), `script` when its hook belongs to a Workshop pair (docs/workshop.md
282
+ * "Pairs": the launch sends `companion.script` with that program, or is refused
283
+ * `companion_required`), else `none`. Absent from older servers.
284
+ */
285
+ requiredCompanion?: RequiredCompanion;
286
+ /**
287
+ * Bordrless's own words for the config's custom hook (`HookReading`) when it is a Workshop hook
288
+ * (or a pair's hook) that is approved and deployed; null for a hook deployed outside the
289
+ * Workshop, or one no longer approved. Absent from older servers.
290
+ */
291
+ hook?: HookReading | null;
209
292
  }
293
+ /** What a config's launch must come with: nothing in particular, a game of a kind, or a Workshop pair's script. */
294
+ export type RequiredCompanion = {
295
+ kind: 'none';
296
+ } | {
297
+ kind: 'game';
298
+ game: GameKindName;
299
+ } | {
300
+ kind: 'script';
301
+ /** 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). */
302
+ program: Address;
303
+ /** 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. */
304
+ workshopId: string | null;
305
+ name: string;
306
+ title: string | null;
307
+ author: Address | null;
308
+ /** 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. */
309
+ preset?: 'lossCover';
310
+ /** Bordrless's reading of the pair (one for both halves), as `HookReading.reading`. Absent from older servers. */
311
+ reading?: WorkshopReading | null;
312
+ /** A companion script has no trading test: never a measured cut. */
313
+ measuredCutBps?: null;
314
+ /** The script half's security review verdict, as `HookReading.verdict`. Absent from older servers. */
315
+ verdict?: 'pass' | 'warn' | null;
316
+ };
210
317
  /** Live figures of a launch's token rules; each null when the launch lacks the rule or it is not tracked. */
211
318
  export interface RuleStats {
212
319
  /** Lamports distributed to holders as holder rewards, all time. */
@@ -248,7 +355,11 @@ export interface ProgramInfo {
248
355
  upgradeAuthority: Address | null;
249
356
  /** Whether the program can still be upgraded; null when unknown. */
250
357
  upgradeable: boolean | null;
358
+ /** Phase 3a: present (true) when the upgrade authority is the program's own `hook_timelock` account. */
359
+ timelocked?: boolean;
251
360
  }
361
+ /** 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. */
362
+ export type CreatorKind = 'wallet' | 'companion' | 'program' | 'program-immutable';
252
363
  export interface LaunchSummary {
253
364
  mint: Address;
254
365
  name: string;
@@ -256,6 +367,8 @@ export interface LaunchSummary {
256
367
  image: string | null;
257
368
  description: string;
258
369
  creator: Address;
370
+ /** Who the creator fee goes to; absent from older servers. */
371
+ creatorKind?: CreatorKind | null;
259
372
  pool: Address;
260
373
  status: LaunchStatus;
261
374
  createdAt: number;
@@ -297,6 +410,8 @@ export interface LaunchSummary {
297
410
  config: Address | null;
298
411
  /** The creator's own token hook (§5.8); null when the mint's hook is the kit or none. */
299
412
  customHook: CustomHookInfo | null;
413
+ /** 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. */
414
+ companionTag?: CompanionTag | null;
300
415
  /** How Bordrless is paid on this launch's pool: 'share' (a share of what the rules collect, `protocolShareBps`) or 'flat' (`protocolFeeBps` of the quote). */
301
416
  protocolModel: ProtocolModel;
302
417
  /** Under the share model, Bordrless's share of the cuts in basis points (2,500 = a quarter); null under the flat model. */
@@ -344,7 +459,8 @@ export interface LaunchDetail extends LaunchSummary {
344
459
  /** `GET /v1/launches?sort=`: newest first by default; `rewards24h` most paid to holders in 24 h first; `fees` lowest buy-then-sell fee first. */
345
460
  export type LaunchSort = 'new' | 'mcap' | 'volume' | 'trending' | 'graduated' | 'rewards24h' | 'fees';
346
461
  /** `GET /v1/launches?rules=a,b`: only launches that have every rule listed (`custom_hook`: launched with a creator's own hook). */
347
- export type RuleFilter = 'rewards' | 'burn' | 'max_wallet' | 'creator_lock' | 'early_lock' | 'custom_hook';
462
+ /** 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. */
463
+ export type RuleFilter = 'rewards' | 'burn' | 'max_wallet' | 'creator_lock' | 'early_lock' | 'custom_hook' | 'snowball' | 'jackpot' | 'last_buyer' | 'streak' | 'half_life' | 'buyback' | 'loss_cover';
348
464
  export interface LaunchList {
349
465
  launches: LaunchSummary[];
350
466
  total: number;
@@ -578,11 +694,268 @@ export interface LaunchPrepareRequest {
578
694
  export type CompanionRequest = {
579
695
  split: CompanionSplitBps;
580
696
  vestDays?: number;
581
- game?: LotteryRequest;
697
+ game?: GameRequest;
698
+ snowball?: SnowballRequest;
699
+ script?: ScriptRequest;
700
+ lossCover?: LossCoverRequest;
582
701
  } | {
583
702
  template: CompanionTemplate;
584
703
  vestDays?: number;
585
704
  };
705
+ /**
706
+ * A Lossback coin as the launch request names it (docs/loss-cover.md; the programs and the policy
707
+ * say Loss cover): the companion's pot pays every holder under water the same share of what they
708
+ * are down, in rounds of `roundSecs`, once the pot holds `minPotLamports`; a holding counts from
709
+ * `minHolding` base units and gets `coverBps` of its loss covered when the pot can. The split's
710
+ * buyback and holders' parts are 0; the pot's part is what the split's launcher part leaves
711
+ * (10,000 with a launcher part of 0). Everything else (the step, the shares per step, holding and
712
+ * round, the least loss, the wait after a buy) is fixed by `LOSS_COVER_DEFAULTS`. Bounds:
713
+ * `lossCoverProblem`. Refused (`companion_rules`) beside a game, a Snowball or a script, and
714
+ * (`loss_cover_off`) while Lossback launches are closed or the creator fee has no config.
715
+ */
716
+ export interface LossCoverRequest {
717
+ roundSecs: number;
718
+ minPotLamports: Amount;
719
+ coverBps: number;
720
+ minHolding: Amount;
721
+ }
722
+ /**
723
+ * The terms a Lossback coin runs on, as the chain holds them: the script's six (`CoverState`:
724
+ * `coverBps`, `minHolding`, `minLossLamports`, `minAgeSecs`, `roundSecs`, `minPotLamports`), the
725
+ * companion's payout terms (`PayoutTerms`: `stepBps`, `holdingBps`, `roundBps` is `window_bps`,
726
+ * the window is the round) and the step (`Script.interval`).
727
+ */
728
+ export interface LossCoverTerms {
729
+ roundSecs: number;
730
+ stepSecs: number;
731
+ stepBps: number;
732
+ holdingBps: number;
733
+ roundBps: number;
734
+ coverBps: number;
735
+ minHolding: Amount;
736
+ minLossLamports: Amount;
737
+ minAgeSecs: number;
738
+ minPotLamports: Amount;
739
+ }
740
+ /** A Lossback coin's figures as its token page shows them (`CompanionSummary.lossCover`), read from the chain and the indexer's payouts. */
741
+ export interface LossCoverSummary {
742
+ /** 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]`). */
743
+ hook: Address;
744
+ hookState: Address;
745
+ script: Address;
746
+ scriptState: Address;
747
+ termsAddress: Address;
748
+ /** The pot (`Companion.pendingPot`), lamports. */
749
+ pot: Amount;
750
+ /** Lamports paid to holders all time, and entries recorded all time (touches included), the terms'. */
751
+ paidTotal: Amount;
752
+ payouts: number;
753
+ /** Distinct holdings paid above 0 so far (the indexer's `script_payouts`). */
754
+ holdersCovered: number;
755
+ /** The round the script last stepped in (0 before the first), and the round the clock is in now. */
756
+ round: number;
757
+ currentRound: number;
758
+ /** 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. */
759
+ roundShareBps: number;
760
+ /** The round's budget (the pot at its first step), what it has paid and what is left. */
761
+ roundBudget: Amount;
762
+ roundPaid: Amount;
763
+ roundBudgetLeft: Amount;
764
+ /** The uncovered loss measured over the previous round (what this round's share is computed from) and so far this round. */
765
+ lossPrev: Amount;
766
+ lossCur: Amount;
767
+ /** Holdings measured this round, and rounds stepped so far. */
768
+ measured: number;
769
+ rounds: number;
770
+ /** 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. */
771
+ lastRoundAt: number;
772
+ nextRoundAt: number;
773
+ lastPaidAt: number;
774
+ nextStepAt: number;
775
+ /** Whether the pot holds the least a round starts with. */
776
+ minPotMet: boolean;
777
+ terms: LossCoverTerms;
778
+ }
779
+ /**
780
+ * `GET /v1/companion/:mint/cover/:owner`: one holder's own cover on a Lossback coin, from the
781
+ * holding's record (the hook data), the pool's price now and the script's round.
782
+ */
783
+ export interface LossCoverHoldingSummary {
784
+ owner: Address;
785
+ holding: Address;
786
+ /** Whether the owner holds the token (a holding with a record); every figure is 0 without one. */
787
+ holds: boolean;
788
+ /** Tokens held, base units; the tokens the record covers (the balance as of its last write). */
789
+ balance: Amount;
790
+ recorded: Amount;
791
+ /** 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. */
792
+ entry: Amount;
793
+ entrySolPerToken: number;
794
+ spot: Amount;
795
+ spotSolPerToken: number;
796
+ /** 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. */
797
+ loss: Amount;
798
+ covered: Amount;
799
+ paid: Amount;
800
+ owed: Amount;
801
+ /** What the current round would pay it at the round's share, lamports (0 in a measuring round, or when not eligible). */
802
+ payNow: Amount;
803
+ /** Whether a step would take it now, and why not in one sentence. */
804
+ eligible: boolean;
805
+ reason: string | null;
806
+ /** 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. */
807
+ lastRound: number;
808
+ paidThisRound: boolean;
809
+ countsFrom: number;
810
+ /** The current round, and when it ends. */
811
+ round: number;
812
+ nextRoundAt: number;
813
+ }
814
+ /**
815
+ * A custom companion as the launch request names it (2026-10-12, docs/scripts.md): a Workshop
816
+ * script (`program`, a companion item that Bordrless approved, deployed and approved on chain)
817
+ * decides what the companion's pot does. The pot is `potBps` of every creator-fee claim (with the
818
+ * split's parts it adds up to 10,000); the companion calls the script's `companion_step` at most
819
+ * once every `interval` seconds (10 to a day), from a minute after the launch; `initData` is what
820
+ * the script's `companion_init` gets once (base64 or hex, at most 512 bytes; empty for none) and
821
+ * `stateLen` the size of the state the companion makes for it (0 to 10,240 bytes; the Workshop
822
+ * item's reading says what the script needs). Bounds: `scriptProblem`. Refused (`companion_rules`)
823
+ * beside a game or a Snowball, and (`script_not_approved`) when the program is not an approved,
824
+ * deployed Workshop companion whose on-chain approval holds.
825
+ */
826
+ export interface ScriptRequest {
827
+ potBps: number;
828
+ program: Address;
829
+ interval: number;
830
+ initData: string;
831
+ stateLen: number;
832
+ }
833
+ /** A custom companion's script as its token page shows it (`CompanionSummary.script`), read from the chain and the Workshop. */
834
+ export interface ScriptSummary {
835
+ /** Its account, `PDA(["script", mint])` under the companion program. */
836
+ address: Address;
837
+ /** The script program (a Workshop companion item's, deployed under Bordrless's key). */
838
+ program: Address;
839
+ /** 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). */
840
+ author: Address | null;
841
+ /** The least time between steps, seconds. */
842
+ interval: number;
843
+ /** When it last stepped (unix seconds; 0: not yet). */
844
+ lastAt: number;
845
+ /** When the next step may run (a minute after the launch at the earliest). */
846
+ nextStepAt: number;
847
+ /** Steps run so far. */
848
+ steps: number;
849
+ /** SOL the script may spend (the companion's pot), lamports. */
850
+ pot: Amount;
851
+ /** The pot's part of every fee claim. */
852
+ potBps: number;
853
+ /** What the author has been paid so far, lamports. */
854
+ authorPaid: Amount;
855
+ /** The size of the script's state the companion made, bytes (0: none). */
856
+ stateLen: number;
857
+ /** 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. */
858
+ workshopId: string | null;
859
+ name: string | null;
860
+ title: string | null;
861
+ /**
862
+ * Whether Bordrless checked and approved the code: a Workshop script. False for an immutable
863
+ * program launched unreviewed (docs/scripts.md "Unreviewed scripts": no Workshop item, no author,
864
+ * no author's share), which the site names "Custom hook (unreviewed)". Absent from older servers.
865
+ */
866
+ reviewed?: boolean;
867
+ /** Bordrless's reading of the Workshop item it came from (`HookReading.reading`); null for a script outside the Workshop. Absent from older servers. */
868
+ reading?: WorkshopReading | null;
869
+ /** 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. */
870
+ verdict?: 'pass' | 'warn' | 'fail' | null;
871
+ /**
872
+ * `reading` when the script was deployed by its builder (immutable, outside the Workshop) and a
873
+ * reading-lane item matches its code: Bordrless's words show with `reviewed` false. Absent for a
874
+ * Workshop script and from older servers.
875
+ */
876
+ lane?: 'workshop' | 'reading';
877
+ }
878
+ /**
879
+ * A Snowball companion as the launch request names it (2026-10-12): the companion's part of every
880
+ * creator fee claim (`potBps`; with the split's parts it adds up to 10,000) fills a pot that makes
881
+ * volume in the token on its own pool, once every `interval` seconds: a buy of `buyBps` of the pot
882
+ * when the price falls `buyStepBps` below its reference, a sell of `sellBps` of its tokens when it
883
+ * rises `sellStepBps` above, and with `flatTrades` a trade anyway when it hasn't moved (on the side
884
+ * that rebalances what it holds). One trade moves at most `poolBps` of the pool's SOL side. The
885
+ * presets are `SNOWBALL_PRESETS`; bounds `snowballProblem`.
886
+ */
887
+ export interface SnowballRequest {
888
+ potBps: number;
889
+ buyStepBps: number;
890
+ sellStepBps: number;
891
+ buyBps: number;
892
+ sellBps: number;
893
+ poolBps: number;
894
+ interval: number;
895
+ flatTrades: boolean;
896
+ }
897
+ /** A Snowball's terms without its part of the fee: what a preset sets and the custom controls change. */
898
+ export type SnowballTerms = Omit<SnowballRequest, 'potBps'>;
899
+ /** A Snowball's market maker as its token page shows it (`CompanionSummary.snowball`), read from the chain. */
900
+ export interface SnowballSummary {
901
+ /** Its account, `PDA(["snowball", mint])` under the companion program. */
902
+ address: Address;
903
+ buyStepBps: number;
904
+ sellStepBps: number;
905
+ buyBps: number;
906
+ sellBps: number;
907
+ /** The most one trade moves, as a share of the pool's SOL side. */
908
+ poolBps: number;
909
+ /** The least time between trades, seconds. */
910
+ interval: number;
911
+ /** It trades every interval even when the price hasn't moved. */
912
+ flatTrades: boolean;
913
+ /** SOL it holds to buy with (the companion's pot), lamports. */
914
+ pot: Amount;
915
+ /** Tokens it holds to sell, base units. */
916
+ tokensHeld: Amount;
917
+ /** The next buy waits for the price at or below `buyBelow`, the next sell at or above `sellAbove` (SOL per whole token). */
918
+ buyBelow: number;
919
+ sellAbove: number;
920
+ buys: number;
921
+ sells: number;
922
+ /** SOL spent on buys and received from sells, lamports; tokens bought and sold, base units. */
923
+ solSpent: Amount;
924
+ solReceived: Amount;
925
+ tokensBought: Amount;
926
+ tokensSold: Amount;
927
+ /** When it last traded or followed the price (unix seconds; 0: not yet). */
928
+ lastAt: number;
929
+ }
930
+ /** 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). */
931
+ export type GameKindName = 'lottery' | 'jackpot' | 'streak' | 'strategy';
932
+ /**
933
+ * A game coin's game as the launch request names it: a lottery on Bordrless's lottery hook, or a
934
+ * jackpot or a streak on a game hook made in Studio (docs/games.md "Phase 2"), whose config the
935
+ * request's `config` must name (the kind's settings are the hook's constants: the timer and the
936
+ * minimum buy, the epoch, the minimum streak and weight; `ConfigInspection.game` shows them).
937
+ */
938
+ export type GameRequest = LotteryRequest | JackpotRequest | StreakRequest;
939
+ /** A jackpot coin's game as the launch request names it (`create_game_v2`): the pot's part, the minimum pot and what a settle pays; the timer and the minimum buy are the hook's. */
940
+ export interface JackpotRequest {
941
+ kind: 'jackpot';
942
+ potBps: number;
943
+ /** A round is paid only while the pot holds at least this, lamports: 0.1 to 1,000 SOL (a round settled below it pays nothing). */
944
+ minPotLamports: Amount;
945
+ /** The part of the pot a settle pays the last buyer, basis points: 10% to 100%. */
946
+ prizeBps: number;
947
+ }
948
+ /** A streak coin's game as the launch request names it (`create_game_v2`): the pot's part, the minimum pot, what an epoch shares and the least a close leaves for claims; the epoch, the minimum streak and weight are the hook's. */
949
+ export interface StreakRequest {
950
+ kind: 'streak';
951
+ potBps: number;
952
+ /** An epoch is closed only while the pot holds at least this, lamports: 0.1 to 1,000 SOL. */
953
+ minPotLamports: Amount;
954
+ /** The part of the pot an epoch shares among its holders, basis points: 10% to 100%. */
955
+ prizeBps: number;
956
+ /** The least a close leaves for claims, seconds: 5 minutes to a day, at most half an epoch. */
957
+ claimWindowSecs: number;
958
+ }
586
959
  /**
587
960
  * A lottery coin's game as the launch request names it (docs/games.md "The companion's game"):
588
961
  * every setting `create_game` fixes before the launch. Bounds: `LOTTERY_LIMITS` (`lotteryProblem`).
@@ -602,19 +975,28 @@ export interface LotteryRequest {
602
975
  /** Attempts a draw makes before it rolls over, 1 to 16; all of them within half a round. */
603
976
  maxAttempts: number;
604
977
  }
605
- /** A lottery coin's settings as its token page shows them (`CompanionSummary.game`): fixed at the launch, and the hook's terms. */
978
+ /** A game coin's settings as its token page shows them (`CompanionSummary.game`): fixed at the launch, and the hook's terms. A jackpot's and a streak's kind settings (phase 2) are the hook's. */
606
979
  export interface GameSummary {
607
- kind: 'lottery';
980
+ kind: GameKindName;
608
981
  /** The game's account, `PDA(["game", mint])` under the companion program. */
609
982
  address: Address;
610
- /** The coin's token hook, which keeps the tickets (the lottery hook). */
983
+ /** The coin's token hook, which keeps the tickets (the lottery hook, or a game hook made in Studio). */
611
984
  hook: Address;
985
+ /** A lottery's round, a streak's epoch; 0 for a jackpot. */
612
986
  roundSecs: number;
613
987
  potBps: number;
614
988
  minPot: Amount;
615
989
  prizeBps: number;
990
+ /** A lottery's claim attempt window, the least a streak's close leaves for claims; 0 for a jackpot. */
616
991
  claimWindowSecs: number;
992
+ /** A lottery's attempts per draw; 0 otherwise. */
617
993
  maxAttempts: number;
994
+ /** Jackpot: a round ends this long after its last qualifying buy, and the least a qualifying buy delivers (base units). Absent or 0 for the other kinds. */
995
+ timerSecs?: number;
996
+ minTokens?: Amount;
997
+ /** Streak: by an epoch's end a holding must have sent nothing for this long, and the least weight that shares (base units). Absent or 0 for the other kinds. */
998
+ minStreakSecs?: number;
999
+ minWeight?: Amount;
618
1000
  /** The most the pot may hold while the hook is not audited (lamports); null for an audited hook. */
619
1001
  potCap: Amount | null;
620
1002
  audited: boolean;
@@ -660,8 +1042,100 @@ export interface GameYou {
660
1042
  odds: number | null;
661
1043
  /** Its tickets in the round before (the one a draw may be for now). */
662
1044
  previousTickets: Amount;
1045
+ /** A jackpot (phase 2): the wallet's place in it. Absent for the other kinds. */
1046
+ jackpot?: JackpotYou | null;
1047
+ /** A streak (phase 2): the wallet's weight and share. Absent for the other kinds. */
1048
+ streak?: StreakYou | null;
1049
+ }
1050
+ /** The caller's place in a jackpot (`GameYou.jackpot`). */
1051
+ export interface JackpotYou {
1052
+ /** The number of the wallet's first qualifying buy since it last sent anything; '0' after any send (the mark). */
1053
+ mark: Amount;
1054
+ /** The wallet is the current round's last qualifying buyer. */
1055
+ lastBuyer: boolean;
1056
+ /** Among the rounds over and not settled, those this wallet would be paid for if settled now (it still holds what it bought). */
1057
+ wins: number;
1058
+ }
1059
+ /** The caller's place in a streak (`GameYou.streak`). */
1060
+ export interface StreakYou {
1061
+ /** The wallet's weight in the current epoch, base units ('0' until registered: `enter` registers it, a trade writes it). */
1062
+ weight: Amount;
1063
+ /** Whether a holding that sends nothing until the epoch's end will share (it has held long enough, at least the minimum weight). */
1064
+ qualifies: boolean;
1065
+ /** The claim epoch (the one open for claims): the wallet's weight in it and the share it can claim now, lamports; '0' after a claim or a send. */
1066
+ claimWeight: Amount;
1067
+ claimShare: Amount;
1068
+ /** The wallet's receipt of the claim epoch exists: its share was paid. */
1069
+ claimed: boolean;
1070
+ }
1071
+ /** A jackpot round as the status lists it (`JackpotStatus.open`, `JackpotStatus.rounds`): its number, buyer, the amount bought and when, and what became of it. */
1072
+ export interface JackpotRound {
1073
+ /** The round's number: that of its last qualifying buy. */
1074
+ number: number;
1075
+ buyer: Address;
1076
+ amount: Amount;
1077
+ /** When its last qualifying buy landed (its timer ran out `timerSecs` later). */
1078
+ boughtAt: number;
1079
+ /** `open`: over, not settled yet; `paid`; `unfunded`: closed paying nothing (the pot below its minimum); `forfeited`: the buyer sold or sent, or can't be paid. */
1080
+ status: 'open' | 'paid' | 'unfunded' | 'forfeited';
1081
+ prize: Amount | null;
1082
+ reason: 'notHeld' | 'unpayable' | 'stale' | null;
1083
+ signature: string | null;
1084
+ at: number | null;
1085
+ }
1086
+ /** A jackpot coin's live state (`GameStatus.jackpot`, docs/games.md "The jackpot"). */
1087
+ export interface JackpotStatus {
1088
+ /** The current round's last qualifying buyer, what they bought and when; null before the first qualifying buy. */
1089
+ lastBuyer: Address | null;
1090
+ lastAmount: Amount;
1091
+ lastBuyAt: number | null;
1092
+ /** When the current round's timer runs out (the last buyer is paid if they still hold); null without a buy. */
1093
+ timerEndsAt: number | null;
1094
+ /** Qualifying buys so far (the current round's number), and the last round settled. */
1095
+ buys: number;
1096
+ paidBuys: number;
1097
+ /** Buys count only while the coin is on its curve: once graduated, the jackpot ends (the round under way is still paid). */
1098
+ onCurve: boolean;
1099
+ /** Rounds over and not settled yet, oldest first (a keeper settles them within seconds). */
1100
+ open: JackpotRound[];
1101
+ /** Rounds settled, as the indexer saw them, newest first. */
1102
+ rounds: JackpotRound[];
1103
+ }
1104
+ /** A streak epoch as the status lists it (`StreakStatus.epochs`): what the indexer saw of it. */
1105
+ export interface StreakEpoch {
1106
+ epoch: number;
1107
+ epochEndsAt: number;
1108
+ /** `closed`: its pot fixed, claims open; `ended`: claims over; `rolledOver`: no pot (no weight, or closed too late). */
1109
+ status: 'closed' | 'ended' | 'rolledOver';
1110
+ /** Its weight total and its pot, lamports. */
1111
+ total: Amount;
1112
+ pot: Amount;
1113
+ /** Paid out so far, lamports, and how many claims. */
1114
+ paid: Amount;
1115
+ claims: number;
1116
+ signature: string | null;
1117
+ at: number | null;
663
1118
  }
664
- /** A lottery coin's live state (`CompanionStatus.game`, docs/games.md): the pot, the round, the draw, the caller's tickets and the draw history. */
1119
+ /** A streak coin's live state (`GameStatus.streak`, docs/games.md "The streak"). */
1120
+ export interface StreakStatus {
1121
+ /** The claim epoch: the one whose claims are open, its pot, total, what it paid so far and when its claims end; null while none is open. */
1122
+ claim: {
1123
+ epoch: number;
1124
+ pot: Amount;
1125
+ total: Amount;
1126
+ paid: Amount;
1127
+ claimsEndAt: number;
1128
+ } | null;
1129
+ /** The epoch before the current one: over, not closed yet (a keeper closes it); null once closed or rolled over. */
1130
+ closing: {
1131
+ epoch: number;
1132
+ total: Amount;
1133
+ closeBy: number;
1134
+ } | null;
1135
+ /** Epochs closed, ended or rolled over, as the indexer saw them, newest first. */
1136
+ epochs: StreakEpoch[];
1137
+ }
1138
+ /** A game coin's live state (`CompanionStatus.game`, docs/games.md): the pot, the round (a streak's epoch), the caller's place in it and the history. A lottery's draw and draws; a jackpot's and a streak's under their own names. */
665
1139
  export interface GameStatus extends GameSummary {
666
1140
  /** Bridged SOL the pot holds, lamports. */
667
1141
  pot: Amount;
@@ -689,6 +1163,21 @@ export interface GameStatus extends GameSummary {
689
1163
  lastWinner: Address | null;
690
1164
  you: GameYou | null;
691
1165
  draws: GameDraw[];
1166
+ /** A jackpot's live state (phase 2); absent or null for the other kinds. */
1167
+ jackpot?: JackpotStatus | null;
1168
+ /** A streak's live state (phase 2); absent or null for the other kinds. */
1169
+ streak?: StreakStatus | null;
1170
+ }
1171
+ /** `POST /v1/game/claim/prepare`: a streak holder's own `claim_share` of the claim epoch (docs/games.md "The streak"): paid to the wallet, which pays its receipt's rent (back once the epoch's claims end, `close_receipt`). */
1172
+ export interface GameClaimRequest {
1173
+ wallet: Address;
1174
+ mint: Address;
1175
+ }
1176
+ export interface GameClaimResponse {
1177
+ transactions: PreparedTx[];
1178
+ /** The epoch claimed and the share it pays, lamports (before the sender's bounty, which is the wallet's own here). */
1179
+ epoch: number;
1180
+ share: Amount;
692
1181
  }
693
1182
  /** `POST /v1/game/enter/prepare`: a holder's own `enter` (docs/games.md): their whole balance registered as tickets for the current round, when the holding was not written this round yet. */
694
1183
  export interface GameEnterRequest {
@@ -711,6 +1200,24 @@ export interface CompanionSplitBps {
711
1200
  /** Paid to the launcher (the beneficiary), in SOL. */
712
1201
  beneficiaryBps: number;
713
1202
  }
1203
+ /**
1204
+ * A launch's companion as a list names it (2026-10-12): what takes its creator fee, fixed at launch, without
1205
+ * the live figures (`CompanionSummary` has those), so a card can say "Snowball 2%" without reading the chain.
1206
+ */
1207
+ export interface CompanionTag {
1208
+ split: CompanionSplitBps;
1209
+ /** The game it runs and the pot's part of every fee claim; null without a game. */
1210
+ game: {
1211
+ kind: GameKindName;
1212
+ potBps: number;
1213
+ } | null;
1214
+ /** A Snowball: its pot makes a market in the token (its part of the fee is what the split leaves). */
1215
+ snowball: boolean;
1216
+ /** A custom companion (2026-10-12): a Workshop script spends its pot. Absent from tags stored before scripts. */
1217
+ script?: boolean;
1218
+ /** 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. */
1219
+ lossCover?: boolean;
1220
+ }
714
1221
  /** A launch's companion as its token page shows it (`LaunchDetail.companion`): lamports and token base units as strings. */
715
1222
  export interface CompanionSummary {
716
1223
  /** The companion's account, `PDA(["companion", mint])` under the companion program. */
@@ -747,6 +1254,12 @@ export interface CompanionSummary {
747
1254
  nextBuybackAt: number | null;
748
1255
  /** The lottery this companion runs (docs/games.md): its settings and the hook's terms; null for a companion without a game. */
749
1256
  game: GameSummary | null;
1257
+ /** A Snowball's market maker (2026-10-12); null for any other companion. */
1258
+ snowball: SnowballSummary | null;
1259
+ /** A custom companion's script (2026-10-12, docs/scripts.md); null for any other companion; absent from older servers. */
1260
+ script?: ScriptSummary | null;
1261
+ /** 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. */
1262
+ lossCover?: LossCoverSummary | null;
750
1263
  }
751
1264
  /**
752
1265
  * `GET /v1/companion/:mint`: a mint's companion as a launch that may not have finished needs it.
@@ -762,6 +1275,10 @@ export interface CompanionStatus {
762
1275
  refundable: Amount | null;
763
1276
  /** 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). */
764
1277
  game?: GameStatus | null;
1278
+ /** A custom companion's script, once launched (docs/scripts.md); null for any other companion (absent from older servers, and before the launch). */
1279
+ script?: ScriptSummary | null;
1280
+ /** A Lossback coin's figures, once launched (docs/loss-cover.md); null for any other companion (absent from older servers, and before the launch). */
1281
+ lossCover?: LossCoverSummary | null;
765
1282
  }
766
1283
  /** `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. */
767
1284
  export interface CompanionRefundRequest {
@@ -982,6 +1499,140 @@ export interface LiquidityPrepareResponse {
982
1499
  transactions: PreparedTx[];
983
1500
  quote: LiquidityQuote;
984
1501
  }
1502
+ /** Which of a mint's four authorities (`set_authority`'s kinds). */
1503
+ export type MintAuthorityKind = 'mint' | 'freeze' | 'hook' | 'metadata';
1504
+ /** One fact of a mint's risk label (docs/dex.md §6.2), in the words every surface uses. */
1505
+ export interface MintRiskReason {
1506
+ kind: 'hook_missing' | 'hook_authority' | 'freeze_authority' | 'mint_authority' | 'hook' | 'metadata_authority' | 'fixed';
1507
+ severity: 'low' | 'medium' | 'high';
1508
+ words: string;
1509
+ }
1510
+ /** A mint's risk label: the highest severity, its first sentence, every reason, and the authorities still held (and by whom). */
1511
+ export interface MintRisk {
1512
+ severity: 'low' | 'medium' | 'high';
1513
+ words: string;
1514
+ reasons: MintRiskReason[];
1515
+ /** The authorities still set on the mint, each with its key. */
1516
+ held: {
1517
+ kind: MintAuthorityKind;
1518
+ authority: Address;
1519
+ }[];
1520
+ }
1521
+ /** The base token of a pool to be created, as the mint account has it. */
1522
+ export interface PoolCreateToken {
1523
+ mint: Address;
1524
+ symbol: string;
1525
+ name: string;
1526
+ decimals: number;
1527
+ image: string | null;
1528
+ supply: Amount;
1529
+ /** 0 when unlimited. */
1530
+ maxSupply: Amount;
1531
+ creator: Address;
1532
+ hookProgram: Address | null;
1533
+ /** How the site names it (from addresses, never from names): a launch of the launchpad, a bridged asset, or a free mint. */
1534
+ identity: 'launch' | 'bridged' | 'free';
1535
+ }
1536
+ /** A pool of the same pair that exists already: the depth, the price and the tier. */
1537
+ export interface ExistingPool {
1538
+ pool: Address;
1539
+ lpFeeBps: number;
1540
+ hookProgram: Address | null;
1541
+ /** The launchpad made it: its launch pool. */
1542
+ launch: boolean;
1543
+ curve: boolean;
1544
+ baseReserve: Amount;
1545
+ quoteReserve: Amount;
1546
+ /** Whole quote per whole token; null while the pool has no reserves. */
1547
+ priceQuote: number | null;
1548
+ tvlUsd: number | null;
1549
+ }
1550
+ export interface PoolCreateQuoteRequest {
1551
+ baseMint: Address;
1552
+ /** One of `POOL_FEE_TIERS_BPS`. */
1553
+ lpFeeBps: number;
1554
+ /** The wallet, for its balances; the quote stands without one. */
1555
+ owner?: Address;
1556
+ /** Base units of the token to deposit. */
1557
+ baseAmount?: Amount;
1558
+ /** Lamports of SOL (bridged in the same transaction) to deposit. */
1559
+ quoteAmount?: Amount;
1560
+ }
1561
+ /** The first deposit as quoted: the price it sets, the LP it mints and the FDV it implies. */
1562
+ export interface PoolCreateDeposit {
1563
+ baseAmount: Amount;
1564
+ quoteAmount: Amount;
1565
+ /** `isqrt(base · quote) − 1,000`, 9 decimals. */
1566
+ lpAmount: Amount;
1567
+ /** Whole SOL per whole token. */
1568
+ priceQuote: number;
1569
+ /** Fully diluted value in lamports (the price times `maxSupply`, or `supply` when unlimited), as a decimal string. */
1570
+ fdvLamports: Amount;
1571
+ fdvUsd: number | null;
1572
+ }
1573
+ export interface PoolCreateQuote {
1574
+ token: PoolCreateToken;
1575
+ quoteMint: Address;
1576
+ quoteSymbol: string;
1577
+ quoteDecimals: number;
1578
+ lpFeeBps: number;
1579
+ /** The DEX config's flat protocol rate of the quote side, which the new pool copies at creation. */
1580
+ protocolFeeBps: number;
1581
+ /** The pool this pair, tier and no hook would live at. */
1582
+ pool: Address;
1583
+ lpMint: Address;
1584
+ /** That pool, when it exists already (the form then offers to add liquidity instead). */
1585
+ exists: ExistingPool | null;
1586
+ /** Every other pool of the pair (the launch pool, other tiers, hooked ones), deepest first. */
1587
+ otherPools: ExistingPool[];
1588
+ /** The wallet's balances, with an owner. */
1589
+ balances: {
1590
+ lamports: Amount;
1591
+ base: Amount;
1592
+ bridgedSol: Amount;
1593
+ } | null;
1594
+ deposit: PoolCreateDeposit | null;
1595
+ risk: MintRisk;
1596
+ /** Rent the creator pays for the new accounts (the pool, the LP mint, two vaults, the LP holding, and the quote holding when missing). */
1597
+ rentLamports: Amount;
1598
+ solUsd: number | null;
1599
+ }
1600
+ export interface PoolCreatePrepareRequest {
1601
+ owner: Address;
1602
+ baseMint: Address;
1603
+ lpFeeBps: number;
1604
+ baseAmount: Amount;
1605
+ quoteAmount: Amount;
1606
+ /** Burn the LP in a second transaction, a permanent lock (docs/dex.md §5.1). */
1607
+ burnLp?: boolean;
1608
+ }
1609
+ export interface PoolCreatePrepareResponse {
1610
+ transactions: PreparedTx[];
1611
+ quote: PoolCreateQuote;
1612
+ pool: Address;
1613
+ lpMint: Address;
1614
+ }
1615
+ /** Burn LP of a pool the wallet holds: all of it, or `amount` (9 decimals). */
1616
+ export interface LpBurnPrepareRequest {
1617
+ owner: Address;
1618
+ pool: Address;
1619
+ amount?: Amount;
1620
+ }
1621
+ export interface LpBurnPrepareResponse {
1622
+ transactions: PreparedTx[];
1623
+ /** LP burned, 9 decimals. */
1624
+ amount: Amount;
1625
+ }
1626
+ /** Revoke authorities the wallet holds on a mint, for ever (`set_authority(kind, None)` for each). */
1627
+ export interface AuthorityPrepareRequest {
1628
+ owner: Address;
1629
+ mint: Address;
1630
+ kinds: MintAuthorityKind[];
1631
+ }
1632
+ export interface AuthorityPrepareResponse {
1633
+ transactions: PreparedTx[];
1634
+ kinds: MintAuthorityKind[];
1635
+ }
985
1636
  export interface ApiErrorBody {
986
1637
  error: string;
987
1638
  code?: string;
@@ -1247,3 +1898,65 @@ export interface HookInspection {
1247
1898
  /** Why it can't be launched with yet, one sentence each. */
1248
1899
  problems: string[];
1249
1900
  }
1901
+ /** Trading wallets an account may have registered at once. */
1902
+ export declare const MAX_TRADING_WALLETS = 5;
1903
+ /** The header the account session travels in, browser → site proxy → backend. The same token serves Studio (`STUDIO_SESSION_HEADER`). */
1904
+ export declare const ACCOUNT_SESSION_HEADER = "x-studio-session";
1905
+ /** The message a wallet signs to sign in to Bordrless: no transaction, nothing moves. */
1906
+ export declare function accountSignInMessage(wallet: Address, nonce: string, issuedAt: string): string;
1907
+ /** The message a trading wallet signs to be registered under an account: proof the key exists and is held by whoever holds the account. */
1908
+ export declare function tradingWalletMessage(account: Address, publicKey: Address): string;
1909
+ export interface AccountSessionRequest {
1910
+ wallet: Address;
1911
+ /** The exact message signed (`accountSignInMessage`). */
1912
+ message: string;
1913
+ /** Base58 ed25519 signature of the message's UTF-8 bytes. */
1914
+ signature: string;
1915
+ }
1916
+ export interface AccountSessionResponse {
1917
+ token: string;
1918
+ wallet: Address;
1919
+ /** Unix seconds. */
1920
+ expiresAt: number;
1921
+ }
1922
+ export interface AccountWallet {
1923
+ publicKey: Address;
1924
+ label: string;
1925
+ /** Unix seconds. */
1926
+ createdAt: number;
1927
+ revokedAt: number | null;
1928
+ }
1929
+ export interface AccountWallets {
1930
+ account: Address;
1931
+ /** Active registrations, oldest first. */
1932
+ wallets: AccountWallet[];
1933
+ max: number;
1934
+ }
1935
+ export interface AccountWalletRegisterRequest {
1936
+ publicKey: Address;
1937
+ /** At most 32 characters. */
1938
+ label: string;
1939
+ /** Base58 ed25519 signature by `publicKey` of `tradingWalletMessage(account, publicKey)`. */
1940
+ signature: string;
1941
+ }
1942
+ /** A plain SOL transfer out of a registered trading wallet (to the signup wallet, usually). */
1943
+ export interface AccountWithdrawPrepareRequest {
1944
+ /** The trading wallet that pays and signs. */
1945
+ wallet: Address;
1946
+ to: Address;
1947
+ lamports: Amount;
1948
+ }
1949
+ export interface AccountWithdrawPrepareResponse {
1950
+ transactions: PreparedTx[];
1951
+ /** The network fee the transfer pays, lamports. */
1952
+ feeLamports: Amount;
1953
+ }
1954
+ export interface AccountWithdrawSendRequest {
1955
+ /** Base64 of the signed transaction from `AccountWithdrawPrepareResponse`. */
1956
+ transaction: string;
1957
+ }
1958
+ export interface AccountWithdrawSendResponse {
1959
+ signature: string;
1960
+ state: 'confirmed' | 'failed' | 'expired' | 'pending';
1961
+ error: string | null;
1962
+ }