@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/README.md +8 -3
- package/dist/api.d.ts +584 -5
- package/dist/api.js +0 -5
- package/dist/explorer.d.ts +21 -0
- package/dist/explorer.js +94 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/keeper.d.ts +139 -0
- package/dist/keeper.js +399 -0
- package/dist/policy.d.ts +207 -27
- package/dist/policy.js +419 -34
- package/dist/programs.d.ts +79 -0
- package/dist/programs.js +84 -0
- package/dist/rules.d.ts +353 -0
- package/dist/rules.js +949 -0
- package/dist/studio.d.ts +66 -2
- package/dist/studio.js +4 -2
- package/dist/workshop.d.ts +380 -0
- package/dist/workshop.js +28 -0
- package/package.json +1 -1
package/dist/studio.d.ts
CHANGED
|
@@ -25,8 +25,13 @@ export interface StudioFile {
|
|
|
25
25
|
* A hook project whose state starts with the game ticket standard's header is a game hook
|
|
26
26
|
* (docs/games.md "Phase 2"): read from its source (`detectGameSettings`), never chosen, and its
|
|
27
27
|
* config launches a jackpot, streak or lottery coin through the companion.
|
|
28
|
+
*
|
|
29
|
+
* `script` (2026-10-12, docs/scripts.md): a Workshop companion's script, the program a companion
|
|
30
|
+
* calls to spend its pot. Only the Workshop makes one (`POST /v1/workshop/submit` with kind
|
|
31
|
+
* companion); it goes through the same pipeline with a script's own checks, review and build (no
|
|
32
|
+
* trading test), is deployed the same way, and is approved on chain instead of listed as a config.
|
|
28
33
|
*/
|
|
29
|
-
export type StudioKind = 'config' | 'hook';
|
|
34
|
+
export type StudioKind = 'config' | 'hook' | 'script';
|
|
30
35
|
/** The kinds of game a game hook keeps the score of (the companion's `GameKind`). */
|
|
31
36
|
export type StudioGameKind = 'lottery' | 'jackpot' | 'streak';
|
|
32
37
|
export declare const STUDIO_GAME_KINDS: readonly StudioGameKind[];
|
|
@@ -303,6 +308,63 @@ export interface StudioSimGame {
|
|
|
303
308
|
/** The largest difference between a wallet's share of the payouts and its share of what it held, in bps, over the fairness run; null when it did not run. */
|
|
304
309
|
fairnessMaxBps: number | null;
|
|
305
310
|
}
|
|
311
|
+
/**
|
|
312
|
+
* `POST /v1/studio/verify` (docs/phase3a-handover.md item 6; the open CLI sends it without the
|
|
313
|
+
* site's key): a program checked against Studio's build record of it and the code on chain. `files`
|
|
314
|
+
* is the caller's copy of the source (`src/**.rs`, as a Studio project keeps them), hashed and
|
|
315
|
+
* compared with the source Studio built; `commit` the template commit the caller built against.
|
|
316
|
+
* `source` is the CLI's directory name, kept for the log only.
|
|
317
|
+
*/
|
|
318
|
+
export interface StudioVerifyRequest {
|
|
319
|
+
kind?: 'hook' | 'strategy';
|
|
320
|
+
program: Address;
|
|
321
|
+
commit?: string;
|
|
322
|
+
source?: string;
|
|
323
|
+
files?: StudioFile[];
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* The verdict: `verified` when the code on chain is Studio's build of the source Studio holds (and,
|
|
327
|
+
* when sent, the caller's source and commit are that build's); `mismatch` when something Studio
|
|
328
|
+
* holds differs from the chain or from what the caller sent; `unverifiable` when nothing can be
|
|
329
|
+
* said: no Studio build record for this program, or no code on chain. `rebuilt` is false: this route
|
|
330
|
+
* compares records, it does not yet rebuild the source at the commit (the handover's full
|
|
331
|
+
* semantics), so a program Studio never built is never `verified` here.
|
|
332
|
+
*/
|
|
333
|
+
export interface StudioVerifyResponse {
|
|
334
|
+
program: Address;
|
|
335
|
+
verdict: 'verified' | 'mismatch' | 'unverifiable';
|
|
336
|
+
/** Why, in sentences the CLI prints. */
|
|
337
|
+
reasons: string[];
|
|
338
|
+
/** `solana-verify`'s executable hash of the code on chain; null when the program is not deployed through the upgradeable loader. */
|
|
339
|
+
onChainHash: string | null;
|
|
340
|
+
/** Studio's build record of this program id, when there is one. */
|
|
341
|
+
build: {
|
|
342
|
+
hash: string;
|
|
343
|
+
sourceHash: string;
|
|
344
|
+
templateCommit: string | null;
|
|
345
|
+
at: number;
|
|
346
|
+
project: string;
|
|
347
|
+
stage: string;
|
|
348
|
+
} | null;
|
|
349
|
+
/** sha256 of the `files` sent (null without files). */
|
|
350
|
+
sourceHash: string | null;
|
|
351
|
+
/** Whether the source sent is the source Studio built (null without files or without a build). */
|
|
352
|
+
sourceMatchesBuild: boolean | null;
|
|
353
|
+
/** Whether the commit sent is the template commit the build recorded (null without a commit, a build, or a recorded commit). */
|
|
354
|
+
commitMatchesBuild: boolean | null;
|
|
355
|
+
/** Studio's on-chain `HookAttestation` of the program, when there is one. */
|
|
356
|
+
attestation: {
|
|
357
|
+
buildHash: string;
|
|
358
|
+
sourceHash: string;
|
|
359
|
+
templateCommit: string;
|
|
360
|
+
kind: string;
|
|
361
|
+
review: 'pass' | 'warn';
|
|
362
|
+
revoked: boolean;
|
|
363
|
+
attestedAt: number;
|
|
364
|
+
matchesChain: boolean;
|
|
365
|
+
} | null;
|
|
366
|
+
rebuilt: false;
|
|
367
|
+
}
|
|
306
368
|
/** `POST /v1/studio/projects/:id/deploy/quote`: what deploying the built hook costs, in lamports. */
|
|
307
369
|
export interface StudioDeployQuote {
|
|
308
370
|
/** Rent of the program's data account (the binary plus room to upgrade: `maxDataLen`). */
|
|
@@ -470,7 +532,9 @@ export declare const MAX_AUTHOR_SHARE_BPS = 5000;
|
|
|
470
532
|
* The only share Studio lists with: a listed config's author gets half the creator fee of every
|
|
471
533
|
* launch someone else makes from it (nothing when the config has no creator fee). It is not the
|
|
472
534
|
* author's to choose. A config listed straight through the SDK may carry less, so the marketplace
|
|
473
|
-
* always shows the share that is on chain.
|
|
535
|
+
* always shows the share that is on chain. A Workshop builder may take nothing instead
|
|
536
|
+
* (`WORKSHOP_AUTHOR_SHARES_BPS`): its config is then made with `create_config` (author share 0) and
|
|
537
|
+
* still shown on the marketplace, with 0% to its builder.
|
|
474
538
|
*/
|
|
475
539
|
export declare const AUTHOR_SHARE_BPS = 5000;
|
|
476
540
|
/**
|
package/dist/studio.js
CHANGED
|
@@ -17,7 +17,7 @@ export function gameDraftDefaults(kind) {
|
|
|
17
17
|
}
|
|
18
18
|
/** The message a wallet signs to use Studio: no transaction, nothing moves. */
|
|
19
19
|
export function studioSignInMessage(wallet, nonce, issuedAt) {
|
|
20
|
-
return ['Sign in to Bordrless
|
|
20
|
+
return ['Sign in to the Bordrless Workshop', '', 'This signature proves you own this wallet. It does not move funds or approve any transaction.', '', `Wallet: ${wallet}`, `Nonce: ${nonce}`, `Issued: ${issuedAt}`].join('\n');
|
|
21
21
|
}
|
|
22
22
|
/** The header the session token travels in, browser → site proxy → backend. */
|
|
23
23
|
export const STUDIO_SESSION_HEADER = 'x-studio-session';
|
|
@@ -62,7 +62,9 @@ export const MAX_AUTHOR_SHARE_BPS = 5_000;
|
|
|
62
62
|
* The only share Studio lists with: a listed config's author gets half the creator fee of every
|
|
63
63
|
* launch someone else makes from it (nothing when the config has no creator fee). It is not the
|
|
64
64
|
* author's to choose. A config listed straight through the SDK may carry less, so the marketplace
|
|
65
|
-
* always shows the share that is on chain.
|
|
65
|
+
* always shows the share that is on chain. A Workshop builder may take nothing instead
|
|
66
|
+
* (`WORKSHOP_AUTHOR_SHARES_BPS`): its config is then made with `create_config` (author share 0) and
|
|
67
|
+
* still shown on the marketplace, with 0% to its builder.
|
|
66
68
|
*/
|
|
67
69
|
export const AUTHOR_SHARE_BPS = 5_000;
|
|
68
70
|
/**
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Workshop (2026-10-12): hooks and companions anyone writes with the SDK and their own agent.
|
|
3
|
+
* The builder submits the source; Bordrless does the rest on its own machines (docs/workshop.md):
|
|
4
|
+
*
|
|
5
|
+
* 1. **Checks**, automatic, on Bordrless's backend and its sandboxed builder: the template's static
|
|
6
|
+
* rules, a security review by AI (two independent runs, the worse kept) looking for anything
|
|
7
|
+
* malicious, the build, the trading test (a hook), and the AI's plain reading (what it does, the
|
|
8
|
+
* most it takes, a description).
|
|
9
|
+
* 2. **Approval** by Bordrless.
|
|
10
|
+
* 3. **Deploy**: the builder pays what deploying it costs (its rent, the fees and Bordrless's fee,
|
|
11
|
+
* quoted first; Bordrless's fee goes to the revenue wallet) and Bordrless deploys it with
|
|
12
|
+
* Bordrless's upgrade key. The builder never holds the upgrade authority.
|
|
13
|
+
* 4. **Credit**: a hook's builder makes its launch config, listed, and earns `AUTHOR_SHARE_BPS` (half)
|
|
14
|
+
* of the creator fee of every launch someone else makes with it, fixed on chain. A companion's
|
|
15
|
+
* builder is paid the same half by the companion program. A builder may take nothing instead
|
|
16
|
+
* (`authorShareBps` 0, the owner, 2026-10-13): a hook's config is then made unlisted on chain
|
|
17
|
+
* (`create_config`, no author share) and still shown on the shelves and the marketplace as theirs;
|
|
18
|
+
* a companion's (or a pair's) script is approved on chain naming no author (the default key).
|
|
19
|
+
*
|
|
20
|
+
* Built on Studio's backend pipeline (studio_projects: review, build, trading test, deploy,
|
|
21
|
+
* config); Studio's own pages are gone. Companions wait in a queue until the companion program's
|
|
22
|
+
* script upgrade and the builder's script template are live (`queued`).
|
|
23
|
+
*
|
|
24
|
+
* **Pairs** (the owner, 2026-10-12: a hook and its companion are not separate anywhere a builder or
|
|
25
|
+
* a launcher sees them). A `pair` is a trade hook plus the companion script that runs with it (the
|
|
26
|
+
* hook keeps the score in the holdings, the script holds the pot and pays), submitted as one item
|
|
27
|
+
* with both sources (`files`, `scriptFiles`), checked as two Studio projects, approved once (both
|
|
28
|
+
* builds bound), deployed with one payment, and listed as one config that requires its companion:
|
|
29
|
+
* `ConfigInspection.requiredCompanion` says so, and a launch of the config without the pair's
|
|
30
|
+
* script, or of the script from another config, is refused (`companion_required`,
|
|
31
|
+
* `config_required`). A pair's `program` is its hook's; `scriptProgram` its script's.
|
|
32
|
+
*
|
|
33
|
+
* **The reading lane** (the owner, 2026-10-12; docs/workshop.md "The reading lane"). A builder who
|
|
34
|
+
* deployed their own hook or companion (the self-serve lane: immutable or not, never under
|
|
35
|
+
* Bordrless's key) submits the source with the program's address (`WorkshopSubmitRequest.program`).
|
|
36
|
+
* The item is `lane: 'reading'`: the same fee, the same checks, and then the build's executable hash
|
|
37
|
+
* is compared with the code on chain. Equal, the item is `matched` and Bordrless's reading and
|
|
38
|
+
* verdict show wherever the program appears (the launch page's config readout, the token page),
|
|
39
|
+
* while the code on chain stays that build. Nothing is deployed, no key of Bordrless's is involved,
|
|
40
|
+
* no author share, nothing on the Workshop's shelves; the item's page is public once matched.
|
|
41
|
+
*/
|
|
42
|
+
import type { Address, PreparedTx } from './api.ts';
|
|
43
|
+
import { type StudioFile } from './studio.ts';
|
|
44
|
+
export type WorkshopKind = 'hook' | 'companion' | 'pair';
|
|
45
|
+
export declare const WORKSHOP_KINDS: readonly WorkshopKind[];
|
|
46
|
+
/**
|
|
47
|
+
* Which lane an item is in: `workshop` (Bordrless checks, approves and deploys it under its own key)
|
|
48
|
+
* or `reading` (the builder deployed it themselves; Bordrless reads and checks the source and, when
|
|
49
|
+
* the build matches the program on chain, its words show wherever the program is used) or `rules`
|
|
50
|
+
* (docs/rules-lane.md §4: a composed hook, listed by its config; its program is the rules engine,
|
|
51
|
+
* its words are read from the rule set bound to the config, approved at once with no checks, no
|
|
52
|
+
* build, no trading test and no fee). Absent from older servers: read as `workshop`.
|
|
53
|
+
*/
|
|
54
|
+
export type WorkshopLane = 'workshop' | 'reading' | 'rules';
|
|
55
|
+
export declare const WORKSHOP_LANES: readonly WorkshopLane[];
|
|
56
|
+
/**
|
|
57
|
+
* Where a submission stands: `unpaid` (taken; nothing runs until its builder pays the submission
|
|
58
|
+
* fee, `WorkshopFee`), `checking` (the automatic checks are running), `queued` (a companion, until
|
|
59
|
+
* the script upgrade is live), `pending` (passed, waiting for Bordrless's approval), `approved` (its
|
|
60
|
+
* builder can pay to deploy it), `rejected` (by the checks or by Bordrless, with the reason),
|
|
61
|
+
* `revoked` (taken down after approval), `matched` (a reading-lane item: the checks passed and the
|
|
62
|
+
* build equals the code on chain, so its reading is attached; terminal). A reading-lane item is
|
|
63
|
+
* never `pending` or `approved`: there is nothing to approve or deploy.
|
|
64
|
+
*/
|
|
65
|
+
export type WorkshopStatus = 'unpaid' | 'checking' | 'queued' | 'pending' | 'approved' | 'rejected' | 'revoked' | 'matched';
|
|
66
|
+
/**
|
|
67
|
+
* The submission fee (the owner, 2026-10-12): every submission costs a fixed amount of SOL, paid by
|
|
68
|
+
* its builder to Bordrless's treasury before its checks run (the API's `WORKSHOP_SUBMIT_LAMPORTS`,
|
|
69
|
+
* 0.1 SOL unless set; 0 makes submissions free). It pays for the review by AI, the build and the
|
|
70
|
+
* trading test, and for the programs Bordrless deploys and keeps. It is not refunded, approved or
|
|
71
|
+
* not. Fixes to a submission that is not approved yet cost nothing more.
|
|
72
|
+
*/
|
|
73
|
+
export interface WorkshopFee {
|
|
74
|
+
/** Lamports, as a decimal string: what this submission was quoted when it was taken. */
|
|
75
|
+
lamports: string;
|
|
76
|
+
/** Bordrless's treasury. */
|
|
77
|
+
payTo: Address;
|
|
78
|
+
/** The memo the payment carries, which makes it this submission's. */
|
|
79
|
+
memo: string;
|
|
80
|
+
/** The payment's transaction signature once Bordrless saw it on chain; null while unpaid. */
|
|
81
|
+
paid: string | null;
|
|
82
|
+
}
|
|
83
|
+
/** `GET /v1/workshop/fee`: what a submission costs now, for the pages that say so before anything is sent. */
|
|
84
|
+
export interface WorkshopFeeResponse {
|
|
85
|
+
lamports: string;
|
|
86
|
+
payTo: Address;
|
|
87
|
+
}
|
|
88
|
+
/** `POST /v1/workshop/:id/fee/quote`, as its builder: the fee and the one payment to sign (it lives about a minute). */
|
|
89
|
+
export interface WorkshopFeeQuote extends WorkshopFeeResponse {
|
|
90
|
+
memo: string;
|
|
91
|
+
transactions: PreparedTx[];
|
|
92
|
+
/** Unix seconds. */
|
|
93
|
+
expiresAt: number;
|
|
94
|
+
}
|
|
95
|
+
/** `POST /v1/workshop/:id/pay`: the fee's payment, checked on chain; the checks start. */
|
|
96
|
+
export interface WorkshopPayRequest {
|
|
97
|
+
paymentSignature: string;
|
|
98
|
+
}
|
|
99
|
+
/** What a submission may hold: the Rust sources of Bordrless's template (its Cargo.toml and crates are Bordrless's). */
|
|
100
|
+
export declare const WORKSHOP_LIMITS: {
|
|
101
|
+
/** Source files, and their bytes in all (the builder's limits). */
|
|
102
|
+
readonly files: 8;
|
|
103
|
+
readonly bytes: 120000;
|
|
104
|
+
/** The name, in characters. */
|
|
105
|
+
readonly name: 32;
|
|
106
|
+
/** The builder's own words. */
|
|
107
|
+
readonly notes: 600;
|
|
108
|
+
/** Submissions one wallet may make in a day. */
|
|
109
|
+
readonly perDay: 6;
|
|
110
|
+
};
|
|
111
|
+
/** A submission's file path: a Rust source under src/, lower-case names (the builder's rule). */
|
|
112
|
+
export declare const WORKSHOP_PATH: RegExp;
|
|
113
|
+
export declare const workshopPathOk: (path: string) => boolean;
|
|
114
|
+
/** The longest each part of the AI's reading may be. */
|
|
115
|
+
export declare const WORKSHOP_READING_LIMITS: {
|
|
116
|
+
readonly title: 48;
|
|
117
|
+
readonly does: 160;
|
|
118
|
+
readonly totalText: 80;
|
|
119
|
+
readonly description: 600;
|
|
120
|
+
readonly watch: 5;
|
|
121
|
+
readonly watchText: 140;
|
|
122
|
+
};
|
|
123
|
+
export type WorkshopWatchSeverity = 'high' | 'medium' | 'low';
|
|
124
|
+
/**
|
|
125
|
+
* What Bordrless's AI wrote about a submission from its source: a title, what it does in one
|
|
126
|
+
* sentence, the most it takes (`total`: for a hook, the largest cut of one trade in basis points of
|
|
127
|
+
* its amount, null when the code reads it from an account it doesn't bound; for a companion, the most
|
|
128
|
+
* of its pot one step spends), a plain description, and what a launcher should watch for. Read by
|
|
129
|
+
* AI from the code, not an audit.
|
|
130
|
+
*/
|
|
131
|
+
export interface WorkshopReading {
|
|
132
|
+
title: string;
|
|
133
|
+
does: string;
|
|
134
|
+
total: {
|
|
135
|
+
bps: number | null;
|
|
136
|
+
text: string;
|
|
137
|
+
};
|
|
138
|
+
description: string;
|
|
139
|
+
watch: {
|
|
140
|
+
severity: WorkshopWatchSeverity;
|
|
141
|
+
text: string;
|
|
142
|
+
}[];
|
|
143
|
+
/** Unix seconds. */
|
|
144
|
+
at: number;
|
|
145
|
+
}
|
|
146
|
+
/** One automatic check, as the item's page shows it. */
|
|
147
|
+
export interface WorkshopCheck {
|
|
148
|
+
id: 'rules' | 'review' | 'build' | 'test' | 'reading';
|
|
149
|
+
label: string;
|
|
150
|
+
state: 'waiting' | 'running' | 'passed' | 'warned' | 'failed' | 'skipped';
|
|
151
|
+
/** One plain sentence: what it found, or why it failed. */
|
|
152
|
+
detail: string | null;
|
|
153
|
+
}
|
|
154
|
+
/** A finding of the security review. */
|
|
155
|
+
export interface WorkshopFinding {
|
|
156
|
+
severity: 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
157
|
+
title: string;
|
|
158
|
+
detail: string;
|
|
159
|
+
}
|
|
160
|
+
/** Where its deploy stands: Studio's deploy states, or null before it is paid for. */
|
|
161
|
+
export type WorkshopDeployState = 'awaiting_payment' | 'paid' | 'writing' | 'deploying' | 'handing_over' | 'deployed' | 'failed' | 'refunded';
|
|
162
|
+
/** A Workshop item as a card shows it. */
|
|
163
|
+
export interface WorkshopItem {
|
|
164
|
+
/** Its id (a uuid): its page is /workshop/<id>. */
|
|
165
|
+
id: string;
|
|
166
|
+
kind: WorkshopKind;
|
|
167
|
+
name: string;
|
|
168
|
+
author: Address;
|
|
169
|
+
status: WorkshopStatus;
|
|
170
|
+
reading: WorkshopReading | null;
|
|
171
|
+
readingState: 'waiting' | 'done' | 'failed';
|
|
172
|
+
/** Its program: reserved once built, live once deployed (`deployed`). A pair's is its hook's. */
|
|
173
|
+
program: Address | null;
|
|
174
|
+
/** Live on chain: for a pair, both halves. */
|
|
175
|
+
deployed: boolean;
|
|
176
|
+
/**
|
|
177
|
+
* The script half's program: a pair's companion script (reserved once built, live once
|
|
178
|
+
* `scriptDeployed`), a companion's own (`program` again); null for a hook. Absent from older servers.
|
|
179
|
+
*/
|
|
180
|
+
scriptProgram?: Address | null;
|
|
181
|
+
/** Whether the script half is deployed (a pair's script; a companion's own program); false for a hook. Absent from older servers. */
|
|
182
|
+
scriptDeployed?: boolean;
|
|
183
|
+
/** A hook's listed launch config, once its builder made it (what the launch page launches from). */
|
|
184
|
+
config: Address | null;
|
|
185
|
+
/** The largest cut of one transfer the trading test measured (a hook), basis points. */
|
|
186
|
+
measuredCutBps: number | null;
|
|
187
|
+
launches: number;
|
|
188
|
+
/** Unix seconds. */
|
|
189
|
+
submittedAt: number;
|
|
190
|
+
approvedAt: number | null;
|
|
191
|
+
/**
|
|
192
|
+
* A companion, or a pair's script (docs/scripts.md): whether the companion program's on-chain
|
|
193
|
+
* approval of its deployed code holds now (`pnpm admin workshop approve-script`), which a launch
|
|
194
|
+
* with it needs; false until it is written, or once the code changed or the approval was revoked.
|
|
195
|
+
* Null for a hook; absent from older servers.
|
|
196
|
+
*/
|
|
197
|
+
scriptApproved?: boolean | null;
|
|
198
|
+
/** Its lane (`WorkshopLane`); absent from older servers: `workshop`. A reading-lane item's `program` is the builder's own, from the start; a rules-lane item's is the rules engine and its `config` the composed config it was listed by. */
|
|
199
|
+
lane?: WorkshopLane;
|
|
200
|
+
/**
|
|
201
|
+
* A reading-lane item: whether its build's executable hash equals the code on chain (true:
|
|
202
|
+
* `matched`; false: `rejected` with the mismatch in `reviewNote`); null until its checks finish.
|
|
203
|
+
* Null for a Workshop-lane item; absent from older servers.
|
|
204
|
+
*/
|
|
205
|
+
matched?: boolean | null;
|
|
206
|
+
/**
|
|
207
|
+
* What its builder takes of the creator fee of every launch someone else makes with it, bps of the
|
|
208
|
+
* fee (`WORKSHOP_AUTHOR_SHARES_BPS`): `AUTHOR_SHARE_BPS` (half), or 0 when they chose to take
|
|
209
|
+
* nothing (a hook's config made unlisted on chain, a script approved naming no author). Recorded at
|
|
210
|
+
* the submission; a hook's is chosen again at its config step, until the config is made. 0 for a
|
|
211
|
+
* reading-lane item (it pays nobody). Absent from older servers: `AUTHOR_SHARE_BPS`.
|
|
212
|
+
*/
|
|
213
|
+
authorShareBps?: number;
|
|
214
|
+
}
|
|
215
|
+
/** What a reading-lane item's match compared, and who can change the program (`WorkshopDetail.match`). */
|
|
216
|
+
export interface WorkshopMatch {
|
|
217
|
+
/** The executable hash of the code on chain (hex): the one compared once the checks finished, else as read now; null when the program could not be read. */
|
|
218
|
+
chainHash: string | null;
|
|
219
|
+
/** The executable hash of Bordrless's build of the source; null before it is built. */
|
|
220
|
+
buildHash: string | null;
|
|
221
|
+
/** The program's upgrade authority; null when it has none (immutable), or when it could not be read (`immutable` tells which). */
|
|
222
|
+
upgradeAuthority: Address | null;
|
|
223
|
+
/** True: nobody can change its code. False: `upgradeAuthority` can. Null: not read. */
|
|
224
|
+
immutable: boolean | null;
|
|
225
|
+
}
|
|
226
|
+
/** A half's security review, as the item's page shows it. */
|
|
227
|
+
export interface WorkshopReviewSummary {
|
|
228
|
+
verdict: 'pass' | 'warn' | 'fail';
|
|
229
|
+
summary: string;
|
|
230
|
+
findings: WorkshopFinding[];
|
|
231
|
+
}
|
|
232
|
+
/** A half's build: the executable hash Bordrless approves and deploys, its size, the template commit. */
|
|
233
|
+
export interface WorkshopBuildSummary {
|
|
234
|
+
hash: string;
|
|
235
|
+
bytes: number;
|
|
236
|
+
templateCommit: string | null;
|
|
237
|
+
}
|
|
238
|
+
/** Where a half's deploy stands. */
|
|
239
|
+
export interface WorkshopDeploySummary {
|
|
240
|
+
state: WorkshopDeployState;
|
|
241
|
+
upgradeAuthority: Address | null;
|
|
242
|
+
error: string | null;
|
|
243
|
+
}
|
|
244
|
+
/** One item in full. */
|
|
245
|
+
export interface WorkshopDetail extends WorkshopItem {
|
|
246
|
+
/** The executable hash of the build Bordrless approved (what its deploy and, for a companion, its on-chain approval are bound to; a pair's hook's); null before approval. Absent from older servers. */
|
|
247
|
+
approvedHash?: string | null;
|
|
248
|
+
/** A pair: the executable hash of the companion script's build Bordrless approved (what its deploy and its on-chain approval are bound to); null before approval, and for a hook or a companion. Absent from older servers. */
|
|
249
|
+
approvedScriptHash?: string | null;
|
|
250
|
+
notes: string;
|
|
251
|
+
/** Its source: a hook's, a companion's, or a pair's hook's. */
|
|
252
|
+
files: StudioFile[];
|
|
253
|
+
/** A pair's companion script source; empty for a hook or a companion. Absent from older servers. */
|
|
254
|
+
scriptFiles?: StudioFile[];
|
|
255
|
+
/** A hook's callbacks (`TOKEN_HOOK_FLAGS`), read from its source (a pair's hook's); 0 for a companion. */
|
|
256
|
+
hookFlags: number;
|
|
257
|
+
/** The checks: a hook's or a companion's, or a pair's hook half's (its rules, review, build, trading test) with the reading, which is one for the item. */
|
|
258
|
+
checks: WorkshopCheck[];
|
|
259
|
+
/** A pair's companion script half: its rules, review and build (no trading test; the reading is in `checks`). Empty for a hook or a companion. Absent from older servers. */
|
|
260
|
+
scriptChecks?: WorkshopCheck[];
|
|
261
|
+
review: WorkshopReviewSummary | null;
|
|
262
|
+
/** A pair's companion script review. Absent from older servers. */
|
|
263
|
+
scriptReview?: WorkshopReviewSummary | null;
|
|
264
|
+
test: {
|
|
265
|
+
pass: boolean;
|
|
266
|
+
reasons: string[];
|
|
267
|
+
cutMaxBps: number | null;
|
|
268
|
+
notes: string[];
|
|
269
|
+
} | null;
|
|
270
|
+
build: WorkshopBuildSummary | null;
|
|
271
|
+
/** A pair's companion script build. Absent from older servers. */
|
|
272
|
+
scriptBuild?: WorkshopBuildSummary | null;
|
|
273
|
+
deploy: WorkshopDeploySummary | null;
|
|
274
|
+
/** A pair's companion script deploy. Absent from older servers. */
|
|
275
|
+
scriptDeploy?: WorkshopDeploySummary | null;
|
|
276
|
+
/** A listed config's creator fee, once made. */
|
|
277
|
+
creatorFeeBps: number | null;
|
|
278
|
+
/** Bordrless's note on a rejection or a revocation, or why the checks stopped it. */
|
|
279
|
+
reviewNote: string | null;
|
|
280
|
+
/** The submission fee it was quoted and whether it is paid; null when it was taken free. Absent from older servers. */
|
|
281
|
+
fee?: WorkshopFee | null;
|
|
282
|
+
/** Who approved it: the checks ('auto', a clean pass) or the operator; null before approval. Absent from older servers. */
|
|
283
|
+
approvedBy?: 'auto' | 'operator' | null;
|
|
284
|
+
/** A reading-lane item: the hashes compared and who can change the program; null for a Workshop-lane item. Absent from older servers. */
|
|
285
|
+
match?: WorkshopMatch | null;
|
|
286
|
+
}
|
|
287
|
+
export interface WorkshopListResponse {
|
|
288
|
+
items: WorkshopItem[];
|
|
289
|
+
total: number;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* `POST /v1/workshop/submit`, as the signed-in wallet (the Studio session header). A pair sends both
|
|
293
|
+
* halves: `files` (the hook's `src/**`) and `scriptFiles` (the companion script's), each within
|
|
294
|
+
* `WORKSHOP_LIMITS`; both are refused if either breaks its template's path rules. A pair's hook may
|
|
295
|
+
* be a game hook (its state starts with `GameHeader`: the pair's script reads the score); a lone
|
|
296
|
+
* hook may not (`game_hook`).
|
|
297
|
+
*
|
|
298
|
+
* With `program`, the submission is a reading-lane one (`WorkshopLane`): the builder deployed that
|
|
299
|
+
* program themselves, and Bordrless reads and checks the source and compares its build with the
|
|
300
|
+
* code on chain. A hook or a companion only: a pair is refused (`reading_lane_pairs`, 400). The
|
|
301
|
+
* program must be deployed through the upgradeable loader (`program_not_deployed`, 400); one with a
|
|
302
|
+
* submission already is refused (`program_taken`, 409: send a fix to that one).
|
|
303
|
+
*/
|
|
304
|
+
export interface WorkshopSubmitRequest {
|
|
305
|
+
kind: WorkshopKind;
|
|
306
|
+
name: string;
|
|
307
|
+
notes: string;
|
|
308
|
+
files: StudioFile[];
|
|
309
|
+
/** A pair's companion script source; ignored for a hook or a companion. */
|
|
310
|
+
scriptFiles?: StudioFile[];
|
|
311
|
+
/** The program's address when the builder deployed it themselves (the reading lane). */
|
|
312
|
+
program?: Address;
|
|
313
|
+
/** What its builder takes (`WORKSHOP_AUTHOR_SHARES_BPS`): `AUTHOR_SHARE_BPS` when absent, 0 to take nothing. A companion's or a pair's script is approved on chain with it; a hook's is its config step's first choice. */
|
|
314
|
+
authorShareBps?: number;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* `POST /v1/workshop/:id/files`: a fix of a submission not approved yet (its checks run again). A
|
|
318
|
+
* hook or a companion sends `files`; a pair sends `files` (its hook), `scriptFiles` (its companion
|
|
319
|
+
* script), or both.
|
|
320
|
+
*/
|
|
321
|
+
export interface WorkshopFilesRequest {
|
|
322
|
+
files?: StudioFile[];
|
|
323
|
+
scriptFiles?: StudioFile[];
|
|
324
|
+
}
|
|
325
|
+
/** One program's deploy cost, lamports as decimal strings: rent (the binary with room to upgrade), the transaction fees, Bordrless's fee, the total. */
|
|
326
|
+
export interface WorkshopDeployCost {
|
|
327
|
+
rent: string;
|
|
328
|
+
fees: string;
|
|
329
|
+
service: string;
|
|
330
|
+
total: string;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* `POST /v1/workshop/:id/deploy/quote`: what deploying it costs, and the payment to sign. A pair's
|
|
334
|
+
* quote covers both programs: `rent`, `fees`, `service` and `total` are the sums, `parts` each
|
|
335
|
+
* half's, and the one transaction pays both (two transfers to the deployer and two memos, one per
|
|
336
|
+
* program); `WorkshopDeployRequest` then carries its one signature.
|
|
337
|
+
*/
|
|
338
|
+
export interface WorkshopDeployQuote extends WorkshopDeployCost {
|
|
339
|
+
payTo: Address;
|
|
340
|
+
transactions: PreparedTx[];
|
|
341
|
+
/** Unix seconds. */
|
|
342
|
+
expiresAt: number;
|
|
343
|
+
/** A pair: each half's cost; null for a hook or a companion. Absent from older servers. */
|
|
344
|
+
parts?: {
|
|
345
|
+
hook: WorkshopDeployCost;
|
|
346
|
+
script: WorkshopDeployCost;
|
|
347
|
+
} | null;
|
|
348
|
+
}
|
|
349
|
+
/** `POST /v1/workshop/:id/deploy`: the confirmed payment. */
|
|
350
|
+
export interface WorkshopDeployRequest {
|
|
351
|
+
paymentSignature: string;
|
|
352
|
+
}
|
|
353
|
+
/** The creator fees a hook's builder may list its config with (they earn `AUTHOR_SHARE_BPS` of it). */
|
|
354
|
+
export declare const WORKSHOP_CONFIG_FEES_BPS: readonly number[];
|
|
355
|
+
/**
|
|
356
|
+
* What a Workshop builder may take of the creator fee of others' launches (the owner, 2026-10-13):
|
|
357
|
+
* `AUTHOR_SHARE_BPS` (half, the default), or nothing. Nothing in between: the shelves read "50%" or
|
|
358
|
+
* "0%" to the builder, and the backend refuses any other share (`author_share`).
|
|
359
|
+
*/
|
|
360
|
+
export declare const WORKSHOP_AUTHOR_SHARES_BPS: readonly number[];
|
|
361
|
+
/** `POST /v1/workshop/:id/config/prepare`: the builder's listed launch config on their deployed hook (a pair's: on its hook, requiring its script). */
|
|
362
|
+
export interface WorkshopConfigPrepareRequest {
|
|
363
|
+
creatorFeeBps: number;
|
|
364
|
+
/**
|
|
365
|
+
* A hook's: what its builder takes (`WORKSHOP_AUTHOR_SHARES_BPS`); the item's recorded choice when
|
|
366
|
+
* absent. 0 makes the config with `create_config` (no author share), still on the shelves and the
|
|
367
|
+
* marketplace. A pair's config never pays an author (its builder is paid by its script's approval):
|
|
368
|
+
* a pair refuses a share other than the one it was submitted with (`author_share_fixed`).
|
|
369
|
+
*/
|
|
370
|
+
authorShareBps?: number;
|
|
371
|
+
/** The address of a keypair the browser made; it signs after the wallet. */
|
|
372
|
+
config: Address;
|
|
373
|
+
}
|
|
374
|
+
export interface WorkshopConfigPrepareResponse {
|
|
375
|
+
config: Address;
|
|
376
|
+
transactions: PreparedTx[];
|
|
377
|
+
}
|
|
378
|
+
export interface WorkshopConfigConfirmRequest {
|
|
379
|
+
config: Address;
|
|
380
|
+
}
|
package/dist/workshop.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AUTHOR_SHARE_BPS } from "./studio.js";
|
|
2
|
+
export const WORKSHOP_KINDS = ['hook', 'companion', 'pair'];
|
|
3
|
+
export const WORKSHOP_LANES = ['workshop', 'reading', 'rules'];
|
|
4
|
+
/** What a submission may hold: the Rust sources of Bordrless's template (its Cargo.toml and crates are Bordrless's). */
|
|
5
|
+
export const WORKSHOP_LIMITS = {
|
|
6
|
+
/** Source files, and their bytes in all (the builder's limits). */
|
|
7
|
+
files: 8,
|
|
8
|
+
bytes: 120_000,
|
|
9
|
+
/** The name, in characters. */
|
|
10
|
+
name: 32,
|
|
11
|
+
/** The builder's own words. */
|
|
12
|
+
notes: 600,
|
|
13
|
+
/** Submissions one wallet may make in a day. */
|
|
14
|
+
perDay: 6,
|
|
15
|
+
};
|
|
16
|
+
/** A submission's file path: a Rust source under src/, lower-case names (the builder's rule). */
|
|
17
|
+
export const WORKSHOP_PATH = /^src\/[a-z0-9_]+(\/[a-z0-9_]+)*\.rs$/;
|
|
18
|
+
export const workshopPathOk = (path) => WORKSHOP_PATH.test(path);
|
|
19
|
+
/** The longest each part of the AI's reading may be. */
|
|
20
|
+
export const WORKSHOP_READING_LIMITS = { title: 48, does: 160, totalText: 80, description: 600, watch: 5, watchText: 140 };
|
|
21
|
+
/** The creator fees a hook's builder may list its config with (they earn `AUTHOR_SHARE_BPS` of it). */
|
|
22
|
+
export const WORKSHOP_CONFIG_FEES_BPS = [50, 100, 200];
|
|
23
|
+
/**
|
|
24
|
+
* What a Workshop builder may take of the creator fee of others' launches (the owner, 2026-10-13):
|
|
25
|
+
* `AUTHOR_SHARE_BPS` (half, the default), or nothing. Nothing in between: the shelves read "50%" or
|
|
26
|
+
* "0%" to the builder, and the backend refuses any other share (`author_share`).
|
|
27
|
+
*/
|
|
28
|
+
export const WORKSHOP_AUTHOR_SHARES_BPS = [AUTHOR_SHARE_BPS, 0];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bordrless/shared",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Bordrless policy (the same math as crates/bordrless-core), program addresses and the API types shared by the server and the site. No Solana dependencies.",
|
|
6
6
|
"license": "Apache-2.0",
|