@bordrless/shared 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.d.ts CHANGED
@@ -145,6 +145,10 @@ export interface ConfigInspection {
145
145
  registryReady: boolean | null;
146
146
  /** The hook is Half-Life: the launch prepares it for the mint and lights its furnace itself. */
147
147
  halfLife?: boolean;
148
+ /** A listed config's author share of the creator fee (bps of it), paid on a launch by anyone but its author; 0 for a plain config. */
149
+ authorShareBps: number;
150
+ /** The hook was built and deployed by Studio: the launch prepares it for the mint itself (its standard `prepare`). */
151
+ studioHook?: boolean;
148
152
  }
149
153
  /** Live figures of a launch's token rules; each null when the launch lacks the rule or it is not tracked. */
150
154
  export interface RuleStats {
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './api.ts';
2
2
  export * from './policy.ts';
3
3
  export * from './programs.ts';
4
+ export * from './studio.ts';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./api.js";
2
2
  export * from "./policy.js";
3
3
  export * from "./programs.js";
4
+ export * from "./studio.js";
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Studio and the config marketplace: the shapes the site and the backend exchange.
3
+ *
4
+ * Studio is where anyone designs a launch config, and optionally a token hook of their own, with an
5
+ * assistant that knows the Bordrless programs; has it reviewed; pays the rent for Bordrless to build
6
+ * and deploy the hook (Bordrless keeps its upgrade authority: the creator never holds it); makes the
7
+ * config; and may list it on the marketplace, where every launch someone else makes from it pays
8
+ * them half its creator fee, if it has one (`AUTHOR_SHARE_BPS`, `create_listed_config`,
9
+ * docs/hooks-v2.md §5.7). That half is all a creator gets from listing.
10
+ *
11
+ * A Studio hook is written against one template (`STUDIO_TEMPLATE`): an Anchor program with a fixed
12
+ * `Cargo.toml` and the standard `prepare` (`STUDIO_PREPARE`), so the site can prepare any Studio hook
13
+ * for a new mint without knowing its code. The backend refuses source that leaves the template's
14
+ * limits (`StaticCheck`) before it is built, reviewed or paid for.
15
+ */
16
+ import type { Address, PreparedTx } from './api.ts';
17
+ /** One source file of a hook. Only `src/**.rs` files; `Cargo.toml` is the template's and never sent. */
18
+ export interface StudioFile {
19
+ /** Relative path, e.g. `src/lib.rs`. */
20
+ path: string;
21
+ content: string;
22
+ }
23
+ /** What a project becomes: a config of existing rules alone, or a config with its own hook program. */
24
+ export type StudioKind = 'config' | 'hook';
25
+ /** The launch config a project makes (the arguments of `create_config` / `create_listed_config`). */
26
+ export interface StudioConfigDraft {
27
+ /** At most 32 bytes. */
28
+ label: string;
29
+ creatorFeeBps: number;
30
+ burnBuyBps: number;
31
+ burnSellBps: number;
32
+ /** Kit rules, for a `config` project only (a hook of one's own excludes them). */
33
+ holderFeeBuyBps: number;
34
+ holderFeeSellBps: number;
35
+ maxWalletBps: number;
36
+ creatorLockDays: number;
37
+ earlyWindowSecs: number;
38
+ earlyLockSecs: number;
39
+ /** `TOKEN_HOOK_FLAGS` the hook runs on, for a `hook` project; 0 for a `config` project. */
40
+ hookFlags: number;
41
+ /** List it on the marketplace (made with `create_listed_config`). */
42
+ listed: boolean;
43
+ /**
44
+ * The author's share of the creator fee on others' launches, bps of it. Not the author's to choose:
45
+ * the backend holds it at `AUTHOR_SHARE_BPS` when listed and 0 when not, whatever is sent.
46
+ */
47
+ authorShareBps: number;
48
+ }
49
+ /** Where a project stands, in the order the Studio walks it. */
50
+ export type StudioStage = 'draft' | 'reviewed' | 'built' | 'paid' | 'deploying' | 'deployed' | 'configured' | 'listed';
51
+ export interface StudioProjectSummary {
52
+ id: string;
53
+ owner: Address;
54
+ name: string;
55
+ kind: StudioKind;
56
+ stage: StudioStage;
57
+ /** The deployed hook, once deployed. */
58
+ programId: Address | null;
59
+ /** The config made from it, once made. */
60
+ config: Address | null;
61
+ updatedAt: number;
62
+ }
63
+ export interface StudioProject extends StudioProjectSummary {
64
+ /** A one-paragraph description, shown on the marketplace when listed. */
65
+ description: string;
66
+ files: StudioFile[];
67
+ draft: StudioConfigDraft;
68
+ /** The last review of the current source; null when the source changed since. */
69
+ review: StudioReview | null;
70
+ /** The last build of the current source; null when the source changed since. */
71
+ build: StudioBuild | null;
72
+ deploy: StudioDeploy | null;
73
+ createdAt: number;
74
+ }
75
+ export interface StudioProjectCreateRequest {
76
+ name: string;
77
+ kind: StudioKind;
78
+ /** Start from a template (`STUDIO_STARTERS`), or blank. */
79
+ starter?: string;
80
+ }
81
+ /** A save: any of the fields; files replace the whole set. Changing files drops the review and the build. */
82
+ export interface StudioProjectUpdateRequest {
83
+ name?: string;
84
+ description?: string;
85
+ files?: StudioFile[];
86
+ draft?: Partial<StudioConfigDraft>;
87
+ }
88
+ /** `POST /v1/studio/session`: the wallet signs `message` (from `studioSignInMessage`), the backend answers a session token. */
89
+ export interface StudioSessionRequest {
90
+ wallet: Address;
91
+ /** The exact message signed. */
92
+ message: string;
93
+ /** Base58 ed25519 signature of the message's UTF-8 bytes. */
94
+ signature: string;
95
+ }
96
+ export interface StudioSessionResponse {
97
+ token: string;
98
+ wallet: Address;
99
+ expiresAt: number;
100
+ /** What the assistant still allows this wallet today. */
101
+ quota: StudioQuota;
102
+ }
103
+ export interface StudioQuota {
104
+ /** Assistant messages left today (UTC). */
105
+ messagesLeft: number;
106
+ messagesPerDay: number;
107
+ /** The assistant is off for everyone (no key, or today's budget spent). */
108
+ assistantOff: boolean;
109
+ }
110
+ /** The message a wallet signs to use Studio: no transaction, nothing moves. */
111
+ export declare function studioSignInMessage(wallet: Address, nonce: string, issuedAt: string): string;
112
+ /** The header the session token travels in, browser → site proxy → backend. */
113
+ export declare const STUDIO_SESSION_HEADER = "x-studio-session";
114
+ export interface StudioMessage {
115
+ id: string;
116
+ role: 'user' | 'assistant';
117
+ /** Markdown. An assistant message may carry proposals (below) as fenced blocks. */
118
+ content: string;
119
+ at: number;
120
+ /** For an assistant message: the changes it proposes, parsed from its fenced blocks. */
121
+ proposal: StudioProposal | null;
122
+ }
123
+ /**
124
+ * What an assistant reply proposes: whole files (```rust file=src/lib.rs fences) and config
125
+ * fields (a ```json studio-config fence). The Studio shows them as a diff to apply or dismiss.
126
+ */
127
+ export interface StudioProposal {
128
+ files: StudioFile[];
129
+ draft: Partial<StudioConfigDraft> | null;
130
+ /** Applied by the user (the project's files or draft were replaced by it). */
131
+ applied: boolean;
132
+ }
133
+ /** `POST /v1/studio/projects/:id/chat`: one user message; the reply is produced in the background. */
134
+ export interface StudioChatRequest {
135
+ content: string;
136
+ }
137
+ export interface StudioChatResponse {
138
+ job: string;
139
+ /** The user's message as stored. */
140
+ message: StudioMessage;
141
+ quota: StudioQuota;
142
+ }
143
+ /** `GET /v1/studio/chat/:job`: the reply so far; poll until `state` is not `running`. */
144
+ export interface StudioChatJob {
145
+ job: string;
146
+ state: 'running' | 'done' | 'failed';
147
+ /** The reply's text so far (all of it once done). */
148
+ text: string;
149
+ /** Once done: the stored message, its proposal parsed. */
150
+ message: StudioMessage | null;
151
+ error: string | null;
152
+ }
153
+ /** One of the template's limits, checked on the source before anything else (no model involved). */
154
+ export interface StaticCheck {
155
+ id: string;
156
+ ok: boolean;
157
+ /** What is checked, in words. */
158
+ label: string;
159
+ /** Where it failed: `src/lib.rs:42` and the offending text. */
160
+ detail: string | null;
161
+ }
162
+ export type FindingSeverity = 'critical' | 'high' | 'medium' | 'low' | 'info';
163
+ export interface ReviewFinding {
164
+ severity: FindingSeverity;
165
+ title: string;
166
+ detail: string;
167
+ /** `src/lib.rs:42`, when it points at a line. */
168
+ location: string | null;
169
+ }
170
+ /** `POST /v1/studio/projects/:id/review`: the static checks, then the assistant's security review. */
171
+ export interface StudioReview {
172
+ /** `fail`: a static check failed or a critical/high finding; deploy is refused. */
173
+ verdict: 'pass' | 'warn' | 'fail';
174
+ checks: StaticCheck[];
175
+ findings: ReviewFinding[];
176
+ /** A short paragraph: what the hook does, as the reviewer read it. */
177
+ summary: string;
178
+ /** sha256 of the source reviewed. */
179
+ sourceHash: string;
180
+ at: number;
181
+ }
182
+ /** `POST /v1/studio/projects/:id/build`: compiled by the build worker in the verifiable-build image. */
183
+ export interface StudioBuild {
184
+ state: 'queued' | 'building' | 'ok' | 'failed';
185
+ /** The program id the source was built for (its `declare_id!`), reserved for this project. */
186
+ programId: Address;
187
+ /** sha256 of the program binary (what `solana-verify get-executable-hash` prints). */
188
+ hash: string | null;
189
+ bytes: number | null;
190
+ /** The compiler's output, its tail. */
191
+ log: string;
192
+ sourceHash: string;
193
+ at: number;
194
+ }
195
+ /** `POST /v1/studio/projects/:id/deploy/quote`: what deploying the built hook costs, in lamports. */
196
+ export interface StudioDeployQuote {
197
+ /** Rent of the program's data account (the binary plus room to upgrade: `maxDataLen`). */
198
+ programDataRent: string;
199
+ /** Rent of the program account. */
200
+ programRent: string;
201
+ /** Transaction fees of writing and deploying it. */
202
+ fees: string;
203
+ /** Bordrless's service fee. */
204
+ service: string;
205
+ total: string;
206
+ maxDataLen: number;
207
+ /** The wallet the payment goes to (Studio's deployer). */
208
+ payTo: Address;
209
+ /** The payment transaction: a plain SOL transfer of `total` with a memo naming this deploy. */
210
+ transactions: PreparedTx[];
211
+ /** The quote holds until then (unix seconds). */
212
+ expiresAt: number;
213
+ }
214
+ /**
215
+ * The upgrade authority is not part of the request: Bordrless keeps it on every hook Studio deploys
216
+ * (`StudioDeploy.upgradeAuthority`). The creator never holds it, and Studio never makes a program
217
+ * final. The backend ignores an `authority` an older site still sends.
218
+ */
219
+ export interface StudioDeployRequest {
220
+ /** The confirmed payment transaction. */
221
+ paymentSignature: string;
222
+ }
223
+ /** `handing_over`: the program is deployed and its upgrade authority goes from Studio's deployer to Bordrless's upgrade key. */
224
+ export type StudioDeployState = 'awaiting_payment' | 'paid' | 'writing' | 'deploying' | 'handing_over' | 'deployed' | 'failed' | 'refunded';
225
+ export interface StudioDeploy {
226
+ state: StudioDeployState;
227
+ programId: Address;
228
+ /** Lamports paid, and the payment. */
229
+ paid: string | null;
230
+ paymentSignature: string | null;
231
+ /** Bytes written of the binary, while writing. */
232
+ written: number;
233
+ bytes: number;
234
+ deploySignature: string | null;
235
+ /**
236
+ * Who holds its upgrade authority once deployed: Bordrless's upgrade key (the backend's
237
+ * STUDIO_UPGRADE_AUTHORITY, `STUDIO_UPGRADE_AUTHORITY` above by default), never the creator; null until
238
+ * the deploy finishes.
239
+ */
240
+ upgradeAuthority: Address | null;
241
+ error: string | null;
242
+ refundSignature: string | null;
243
+ at: number;
244
+ }
245
+ /** `POST /v1/studio/projects/:id/config/prepare`: `create_config` or `create_listed_config` for the draft. */
246
+ export interface StudioConfigPrepareRequest {
247
+ /** A fresh keypair's address the browser made; it signs after the wallet. */
248
+ config: Address;
249
+ }
250
+ export interface StudioConfigPrepareResponse {
251
+ config: Address;
252
+ transactions: PreparedTx[];
253
+ }
254
+ export interface MarketplaceListing {
255
+ config: Address;
256
+ author: Address;
257
+ /** The config's on-chain label. */
258
+ label: string;
259
+ /** The author's title and description (from Studio), or the label alone. */
260
+ title: string;
261
+ description: string;
262
+ authorShareBps: number;
263
+ creatorFeeBps: number;
264
+ burnBuyBps: number;
265
+ burnSellBps: number;
266
+ holderFeeBuyBps: number;
267
+ holderFeeSellBps: number;
268
+ maxWalletBps: number;
269
+ customHook: Address | null;
270
+ customHookFlags: number;
271
+ /** The hook was built and deployed by Studio from source anyone can read. */
272
+ studioSource: boolean;
273
+ /** Who can upgrade the hook now (null: final, or no hook). */
274
+ hookUpgradeAuthority: Address | null;
275
+ /** The source passed review when it was deployed. */
276
+ reviewVerdict: 'pass' | 'warn' | null;
277
+ launches: number;
278
+ /** Paid to the author so far, lamports. */
279
+ authorEarned: string;
280
+ volumeUsd: number | null;
281
+ createdAt: number;
282
+ }
283
+ export interface MarketplaceListResponse {
284
+ listings: MarketplaceListing[];
285
+ total: number;
286
+ }
287
+ export interface MarketplaceDetail extends MarketplaceListing {
288
+ /** The hook's source when Studio built it. */
289
+ files: StudioFile[] | null;
290
+ buildHash: string | null;
291
+ review: StudioReview | null;
292
+ /** Launches made from it, newest first. */
293
+ recentLaunches: {
294
+ mint: Address;
295
+ symbol: string;
296
+ name: string;
297
+ image: string | null;
298
+ createdAt: number;
299
+ }[];
300
+ }
301
+ /** `POST /v1/author/prepare`: a config author's claims of their share, on up to four launches a transaction, paid as SOL. */
302
+ export interface AuthorPrepareRequest {
303
+ author: Address;
304
+ /** The launches to claim on; all with something to claim when absent. */
305
+ mints?: Address[];
306
+ }
307
+ export interface AuthorEarnings {
308
+ author: Address;
309
+ /** Waiting to be claimed on each launch: the author's part of what the launch holds. */
310
+ launches: {
311
+ mint: Address;
312
+ symbol: string;
313
+ config: Address;
314
+ claimable: string;
315
+ paid: string;
316
+ }[];
317
+ claimable: string;
318
+ paid: string;
319
+ }
320
+ /** Bordrless Studio's upgrade key: the upgrade authority of every hook Studio deploys (STUDIO_UPGRADE_AUTHORITY defaults to it). */
321
+ export declare const STUDIO_UPGRADE_AUTHORITY = "CS1NRyXNCPxEUP4CRoa26cHQSeSJCxXh5SPijwFhDW6W";
322
+ /** The protocol's own upgrade authority (Half-Life, tax_hook). */
323
+ export declare const PROTOCOL_UPGRADE_AUTHORITY = "5xsibKwtiN6ruxsYrEyWVpV3KcwuzSPbQd1n28a7spEd";
324
+ /**
325
+ * `bordrless_launch::constants::HOOK_UPGRADE_AUTHORITIES`: besides no one at all, the only keys that
326
+ * may hold a custom hook's upgrade authority for `create_config` to accept it (docs/hooks-v2.md §5.8).
327
+ */
328
+ export declare const HOOK_UPGRADE_AUTHORITIES: readonly string[];
329
+ /** `bordrless_launch::constants::MAX_AUTHOR_SHARE_BPS`: half the creator fee, the most the program lets a listed config pay its author. */
330
+ export declare const MAX_AUTHOR_SHARE_BPS = 5000;
331
+ /**
332
+ * The only share Studio lists with: a listed config's author gets half the creator fee of every
333
+ * launch someone else makes from it (nothing when the config has no creator fee). It is not the
334
+ * author's to choose. A config listed straight through the SDK may carry less, so the marketplace
335
+ * always shows the share that is on chain.
336
+ */
337
+ export declare const AUTHOR_SHARE_BPS = 5000;
338
+ /**
339
+ * The standard `prepare` of a Studio hook: `prepare()` (no arguments) with the accounts
340
+ * `[payer (signer, writable), mint, state = PDA(["state", mint], hook) (writable), registry =
341
+ * PDA(["bordrless-hook-accounts", mint], hook) (writable), system program]`. It creates the hook's
342
+ * state for the mint and writes its registry; anyone may send it, once per mint.
343
+ */
344
+ export declare const STUDIO_PREPARE: {
345
+ readonly instruction: "prepare";
346
+ readonly stateSeed: "state";
347
+ };
348
+ /** Limits of a project's source. */
349
+ export declare const STUDIO_LIMITS: {
350
+ readonly files: 8;
351
+ readonly bytes: 120000;
352
+ readonly messageChars: 8000;
353
+ };
354
+ /** Starters a new hook project can begin from (the template's `src/lib.rs` variants). */
355
+ export declare const STUDIO_STARTERS: readonly {
356
+ id: string;
357
+ name: string;
358
+ blurb: string;
359
+ }[];
package/dist/studio.js ADDED
@@ -0,0 +1,40 @@
1
+ /** The message a wallet signs to use Studio: no transaction, nothing moves. */
2
+ export function studioSignInMessage(wallet, nonce, issuedAt) {
3
+ return ['Sign in to Bordrless Studio', '', 'This signature proves you own this wallet. It does not move funds or approve any transaction.', '', `Wallet: ${wallet}`, `Nonce: ${nonce}`, `Issued: ${issuedAt}`].join('\n');
4
+ }
5
+ /** The header the session token travels in, browser → site proxy → backend. */
6
+ export const STUDIO_SESSION_HEADER = 'x-studio-session';
7
+ // ---- constants ----------------------------------------------------------------------------------------
8
+ /** Bordrless Studio's upgrade key: the upgrade authority of every hook Studio deploys (STUDIO_UPGRADE_AUTHORITY defaults to it). */
9
+ export const STUDIO_UPGRADE_AUTHORITY = 'CS1NRyXNCPxEUP4CRoa26cHQSeSJCxXh5SPijwFhDW6W';
10
+ /** The protocol's own upgrade authority (Half-Life, tax_hook). */
11
+ export const PROTOCOL_UPGRADE_AUTHORITY = '5xsibKwtiN6ruxsYrEyWVpV3KcwuzSPbQd1n28a7spEd';
12
+ /**
13
+ * `bordrless_launch::constants::HOOK_UPGRADE_AUTHORITIES`: besides no one at all, the only keys that
14
+ * may hold a custom hook's upgrade authority for `create_config` to accept it (docs/hooks-v2.md §5.8).
15
+ */
16
+ export const HOOK_UPGRADE_AUTHORITIES = [STUDIO_UPGRADE_AUTHORITY, PROTOCOL_UPGRADE_AUTHORITY];
17
+ /** `bordrless_launch::constants::MAX_AUTHOR_SHARE_BPS`: half the creator fee, the most the program lets a listed config pay its author. */
18
+ export const MAX_AUTHOR_SHARE_BPS = 5_000;
19
+ /**
20
+ * The only share Studio lists with: a listed config's author gets half the creator fee of every
21
+ * launch someone else makes from it (nothing when the config has no creator fee). It is not the
22
+ * author's to choose. A config listed straight through the SDK may carry less, so the marketplace
23
+ * always shows the share that is on chain.
24
+ */
25
+ export const AUTHOR_SHARE_BPS = 5_000;
26
+ /**
27
+ * The standard `prepare` of a Studio hook: `prepare()` (no arguments) with the accounts
28
+ * `[payer (signer, writable), mint, state = PDA(["state", mint], hook) (writable), registry =
29
+ * PDA(["bordrless-hook-accounts", mint], hook) (writable), system program]`. It creates the hook's
30
+ * state for the mint and writes its registry; anyone may send it, once per mint.
31
+ */
32
+ export const STUDIO_PREPARE = { instruction: 'prepare', stateSeed: 'state' };
33
+ /** Limits of a project's source. */
34
+ export const STUDIO_LIMITS = { files: 8, bytes: 120_000, messageChars: 8_000 };
35
+ /** Starters a new hook project can begin from (the template's `src/lib.rs` variants). */
36
+ export const STUDIO_STARTERS = [
37
+ { id: 'blank', name: 'Blank hook', blurb: 'The template: every callback stubbed, nothing taken, nothing refused.' },
38
+ { id: 'sell-tax', name: 'Sell tax to a wallet', blurb: 'A cut of every sell sent to a wallet you choose; buys and transfers pass free.' },
39
+ { id: 'cooldown', name: 'Transfer cooldown', blurb: 'A holding that received tokens cannot send them on for a while, stamped in its hook data.' },
40
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bordrless/shared",
3
- "version": "0.2.0",
3
+ "version": "0.4.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",