@bordrless/shared 0.1.0 → 0.3.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 +2 -2
- package/dist/api.d.ts +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/policy.d.ts +30 -20
- package/dist/policy.js +34 -22
- package/dist/programs.d.ts +26 -0
- package/dist/programs.js +36 -0
- package/dist/studio.d.ts +333 -0
- package/dist/studio.js +26 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,8 +27,8 @@ TOKEN_HOOK_FLAGS.BEFORE_TRANSFER | TOKEN_HOOK_FLAGS.TRANSFER_RETURNS_DELTA;
|
|
|
27
27
|
|
|
28
28
|
## Where to read more
|
|
29
29
|
|
|
30
|
-
- The SDK page: https://bordrless.
|
|
31
|
-
- The standard in full: https://bordrless.
|
|
30
|
+
- The SDK page: https://bordrless.app/sdk
|
|
31
|
+
- The standard in full: https://bordrless.app/docs
|
|
32
32
|
|
|
33
33
|
Status: the programs run on localnet and devnet until they are deployed to mainnet; they keep an
|
|
34
34
|
upgrade authority until audited.
|
package/dist/api.d.ts
CHANGED
|
@@ -143,6 +143,12 @@ export interface ConfigInspection {
|
|
|
143
143
|
/** As `CustomHookInfo.upgradeable`; null without a hook or when its program could not be read. */
|
|
144
144
|
hookUpgradeable: boolean | null;
|
|
145
145
|
registryReady: boolean | null;
|
|
146
|
+
/** The hook is Half-Life: the launch prepares it for the mint and lights its furnace itself. */
|
|
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;
|
|
146
152
|
}
|
|
147
153
|
/** Live figures of a launch's token rules; each null when the launch lacks the rule or it is not tracked. */
|
|
148
154
|
export interface RuleStats {
|
|
@@ -351,12 +357,27 @@ export interface PortfolioEntry {
|
|
|
351
357
|
/** For a launch token with a creator's own hook (§5.8): the hook, so the row can say so; null otherwise (absent from backends that predate it). */
|
|
352
358
|
customHook?: CustomHookInfo | null;
|
|
353
359
|
}
|
|
360
|
+
/** A launch the wallet created, with the creator fee waiting for it (`Portfolio.created`). */
|
|
361
|
+
export interface CreatedLaunch {
|
|
362
|
+
mint: Address;
|
|
363
|
+
symbol: string;
|
|
364
|
+
name: string;
|
|
365
|
+
image: string | null;
|
|
366
|
+
status: LaunchStatus;
|
|
367
|
+
creatorFeeBps: number;
|
|
368
|
+
/** Lamports of bridged SOL accrued and not yet claimed (the launch's quote holding, what a claim pays); null when the chain could not be read. */
|
|
369
|
+
claimable: Amount | null;
|
|
370
|
+
/** Lamports claimed here, all time; null when not known. */
|
|
371
|
+
claimedTotal?: Amount | null;
|
|
372
|
+
}
|
|
354
373
|
export interface Portfolio {
|
|
355
374
|
owner: Address;
|
|
356
375
|
lamports: Amount;
|
|
357
376
|
/** What the wallet holds, plus launches it no longer holds when it has holder rewards to claim there. */
|
|
358
377
|
entries: PortfolioEntry[];
|
|
359
378
|
totalUsd: number | null;
|
|
379
|
+
/** The launches this wallet created, those with fees to claim first (absent from backends that predate it). */
|
|
380
|
+
created: CreatedLaunch[];
|
|
360
381
|
}
|
|
361
382
|
/** Native SOL (bridged on the way in, unbridged on the way out) or bridged SOL already held. */
|
|
362
383
|
export type SolMode = 'SOL' | 'BSOL';
|
|
@@ -518,6 +539,11 @@ export interface RewardsPrepareRequest {
|
|
|
518
539
|
/** Unwrap the bridged SOL to SOL and close the temporary holding. */
|
|
519
540
|
unwrap: boolean;
|
|
520
541
|
}
|
|
542
|
+
/** Claim the creator fees of launches the owner created: up to about 4 mints per transaction, paid as SOL. */
|
|
543
|
+
export interface CreatorPrepareRequest {
|
|
544
|
+
owner: Address;
|
|
545
|
+
mints: Address[];
|
|
546
|
+
}
|
|
521
547
|
/** Share with holders: send SOL that every holder of the token receives pro rata. */
|
|
522
548
|
export interface SharePrepareRequest {
|
|
523
549
|
owner: Address;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/policy.d.ts
CHANGED
|
@@ -230,9 +230,14 @@ export declare const rewardsOn: (r: Pick<LaunchRulesInput, "holderFeeBuyBps" | "
|
|
|
230
230
|
export declare const defaultCreatorFeeBps: (r: LaunchRulesInput) => number;
|
|
231
231
|
/** The four presets of §7.1 (2026-10-07: Holders first, Fair start, Scorched and Community are gone). */
|
|
232
232
|
export type RulePresetName = 'Plain' | 'Diamond hands' | 'Burn' | 'Paid to hold';
|
|
233
|
-
/**
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
/**
|
|
234
|
+
* The ways beside the presets (§7.1): Half-Life launches from Bordrless's own `LaunchConfig` with
|
|
235
|
+
* the Half-Life hook (programs/half_life), prepared and lit for the mint by the launch itself;
|
|
236
|
+
* Custom mixes the rules by hand with the form's controls; Build your own launches from a
|
|
237
|
+
* `LaunchConfig` a creator made with the SDK (§5.7).
|
|
238
|
+
*/
|
|
239
|
+
export type RulePathName = 'Half-Life' | 'Custom' | 'Build your own';
|
|
240
|
+
/** What the launch form's rules row can be set to: a preset, or one of the paths. */
|
|
236
241
|
export type RuleModeName = RulePresetName | RulePathName;
|
|
237
242
|
export interface RulePreset {
|
|
238
243
|
name: RulePresetName;
|
|
@@ -259,7 +264,7 @@ export interface RulePath {
|
|
|
259
264
|
* every one). Holder rewards set "both sides" take the same rate on buys and sells.
|
|
260
265
|
*/
|
|
261
266
|
export declare const RULE_PRESETS: readonly RulePreset[];
|
|
262
|
-
/** The
|
|
267
|
+
/** The paths beside the presets, in order, with the words the home console and the launch form print. */
|
|
263
268
|
export declare const RULE_PATHS: readonly RulePath[];
|
|
264
269
|
/** The preset the launch form starts on. */
|
|
265
270
|
export declare const DEFAULT_RULE_PRESET: RulePresetName;
|
|
@@ -332,7 +337,7 @@ export declare function launchBeforeSwap(side: Side, amountIn: bigint, p: Launch
|
|
|
332
337
|
export declare function launchAfterSwap(side: Side, amountOut: bigint, p: LaunchFeeParams): HookCut;
|
|
333
338
|
/** A swap on a launch pool, step by step. */
|
|
334
339
|
export interface LaunchSwap {
|
|
335
|
-
/** Bridged SOL to the creator: from a buy's input, or from a sell's output after the
|
|
340
|
+
/** Bridged SOL to the creator: from a buy's input, or from a sell's output after the LP fee. */
|
|
336
341
|
creatorFee: bigint;
|
|
337
342
|
/** Bridged SOL to holders, likewise. */
|
|
338
343
|
holderFee: bigint;
|
|
@@ -342,13 +347,13 @@ export interface LaunchSwap {
|
|
|
342
347
|
holderFeeOn: boolean;
|
|
343
348
|
/** What reached the input vault. */
|
|
344
349
|
received: bigint;
|
|
345
|
-
/** The LP fee, in
|
|
350
|
+
/** The LP fee, Bordrless's in bridged SOL (it never stays in a launch pool): on a buy from what reached the vault, on a sell from the curve's output. The DEX's event reports it inside `protocol_fee` with `lp_fee` 0. */
|
|
346
351
|
lpFee: bigint;
|
|
347
352
|
/** Bordrless's share of the creator and holder fees (`LAUNCH_PROTOCOL_SHARE_BPS` of them, rounded up; 0 when they are 0), always in bridged SOL: on a buy from what reached the vault, before the curve; on a sell held back from the delivery. */
|
|
348
353
|
protocolFee: bigint;
|
|
349
|
-
/** What went into the curve: `received` less the LP fee
|
|
354
|
+
/** What went into the curve: on a buy `received` less the LP fee and the protocol fee (negative when they take more than arrived); on a sell `received`. */
|
|
350
355
|
netIn: bigint;
|
|
351
|
-
/** What the curve gave (on a sell, before the
|
|
356
|
+
/** What the curve gave (on a sell, before the LP fee, the creator and holder fees and the protocol fee); null when the swap fails. */
|
|
352
357
|
amountOut: bigint | null;
|
|
353
358
|
/** What reaches the recipient; null when the swap fails. */
|
|
354
359
|
delivered: bigint | null;
|
|
@@ -362,21 +367,26 @@ export declare function curveOutput(r: Reserves, side: Side, netIn: bigint): big
|
|
|
362
367
|
* §5.4; the Rust reference is `bordrless_program_tests::launch::quote_launch_swap`): Bordrless
|
|
363
368
|
* takes `protocolShareBps` of the creator and holder fees (the hooks' cuts; the kit takes none of
|
|
364
369
|
* its own, so the cuts are exactly those fees), in bridged SOL, and nothing when they are nothing.
|
|
365
|
-
* A buy: the creator and holder fees from the input, Bordrless's share of them and the LP fee
|
|
366
|
-
* what reached the vault, the curve, the burn from the output. A sell: the
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
370
|
+
* A buy: the creator and holder fees from the input, Bordrless's share of them and the LP fee (both
|
|
371
|
+
* Bordrless's, in SOL) on what reached the vault, the curve, the burn from the output. A sell: the
|
|
372
|
+
* burn from the input, the curve on all the rest, the LP fee (Bordrless's) from the curve's output,
|
|
373
|
+
* then the creator and holder fees from what is left and Bordrless's share of them held back from the
|
|
374
|
+
* delivery. A launch pool's LP fee never stays in the pool (its LP is locked for ever). A sell takes
|
|
375
|
+
* its input out of the kit's eligible count before `after_swap` reads it (every seller is a holder:
|
|
376
|
+
* the pool and the launch never sell). An ordinary pool's flat rate is `quoteSwap`.
|
|
371
377
|
*/
|
|
372
378
|
export declare function quoteLaunchSwap(r: Reserves, side: Side, amountIn: bigint, lpFeeBps: number, protocolShareBps: number, p: LaunchFeeParams): LaunchSwap;
|
|
373
|
-
/** What a launch-pool swap adds to its input reserve (the Rust reference's `to_reserve_in`): what reached the vault, less a buy's protocol fee. */
|
|
374
|
-
export declare const launchSwapToReserve: (side: Side, q: Pick<LaunchSwap, "received" | "protocolFee">) => bigint;
|
|
375
379
|
/**
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
|
|
380
|
+
* What a launch-pool swap adds to its input reserve (the Rust reference's `to_reserve_in`): on a buy
|
|
381
|
+
* what goes into the curve (what reached the vault less the LP fee and the share, both Bordrless's;
|
|
382
|
+
* 0 when they take it all), on a sell what reached the vault.
|
|
383
|
+
*/
|
|
384
|
+
export declare const launchSwapToReserve: (side: Side, q: Pick<LaunchSwap, "received" | "netIn">) => bigint;
|
|
385
|
+
/**
|
|
386
|
+
* Whether a buy that lands leaves the launch ready to graduate, so `graduate` can follow it in the
|
|
387
|
+
* same transaction: the pool's quote reserve at or above the graduation threshold, or the curve sold
|
|
388
|
+
* out (the buy takes every token it has left). The LP fee does not compound, so the two come
|
|
389
|
+
* together, and a hook's cut on buys can keep the reserve just short of the threshold.
|
|
380
390
|
*/
|
|
381
391
|
export declare function buyGraduates(r: Reserves, q: LaunchSwap, graduationQuote: bigint): boolean;
|
|
382
392
|
/**
|
package/dist/policy.js
CHANGED
|
@@ -334,8 +334,9 @@ export const RULE_PRESETS = [
|
|
|
334
334
|
{ name: 'Burn', slug: 'burn', description: 'Burn 0.5% on buys and sells, holder rewards 0.5%, creator fee 0.5%.', creatorFeeBps: 50, rules: { ...NO_RULES, holderFeeBuyBps: 50, holderFeeSellBps: 50, burnBuyBps: 50, burnSellBps: 50 } },
|
|
335
335
|
{ name: 'Paid to hold', slug: 'paid-to-hold', description: 'Holder rewards 2% on sells only, creator wallet lock 30 d, creator fee 0.5%.', creatorFeeBps: 50, rules: { ...NO_RULES, holderFeeSellBps: 200, creatorLockDays: 30 } },
|
|
336
336
|
];
|
|
337
|
-
/** The
|
|
337
|
+
/** The paths beside the presets, in order, with the words the home console and the launch form print. */
|
|
338
338
|
export const RULE_PATHS = [
|
|
339
|
+
{ name: 'Half-Life', slug: 'half-life', description: 'An exit fee that halves every 6 hours held: 20% to sell at once, 0% after 2 days, burned. Buys are free.' },
|
|
339
340
|
{ name: 'Custom', slug: 'custom', description: 'Mix the rules by hand; holder rewards and burn can differ on buys and sells.' },
|
|
340
341
|
{ name: 'Build your own', slug: 'build-your-own', description: 'Write a hook with the SDK, make a launch config, paste its key.' },
|
|
341
342
|
];
|
|
@@ -482,23 +483,25 @@ export function curveOutput(r, side, netIn) {
|
|
|
482
483
|
* §5.4; the Rust reference is `bordrless_program_tests::launch::quote_launch_swap`): Bordrless
|
|
483
484
|
* takes `protocolShareBps` of the creator and holder fees (the hooks' cuts; the kit takes none of
|
|
484
485
|
* its own, so the cuts are exactly those fees), in bridged SOL, and nothing when they are nothing.
|
|
485
|
-
* A buy: the creator and holder fees from the input, Bordrless's share of them and the LP fee
|
|
486
|
-
* what reached the vault, the curve, the burn from the output. A sell: the
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
486
|
+
* A buy: the creator and holder fees from the input, Bordrless's share of them and the LP fee (both
|
|
487
|
+
* Bordrless's, in SOL) on what reached the vault, the curve, the burn from the output. A sell: the
|
|
488
|
+
* burn from the input, the curve on all the rest, the LP fee (Bordrless's) from the curve's output,
|
|
489
|
+
* then the creator and holder fees from what is left and Bordrless's share of them held back from the
|
|
490
|
+
* delivery. A launch pool's LP fee never stays in the pool (its LP is locked for ever). A sell takes
|
|
491
|
+
* its input out of the kit's eligible count before `after_swap` reads it (every seller is a holder:
|
|
492
|
+
* the pool and the launch never sell). An ordinary pool's flat rate is `quoteSwap`.
|
|
491
493
|
*/
|
|
492
494
|
export function quoteLaunchSwap(r, side, amountIn, lpFeeBps, protocolShareBps, p) {
|
|
493
495
|
const before = launchBeforeSwap(side, amountIn, p);
|
|
494
496
|
const received = amountIn - before.creatorFee - before.holderFee - before.burn;
|
|
495
497
|
const eligibleAtFees = side === 'sell' ? (p.eligible > amountIn ? p.eligible - amountIn : 0n) : p.eligible;
|
|
496
498
|
const holderFeeOn = (side === 'buy' ? p.holderFeeBuyBps : p.holderFeeSellBps) > 0 && eligibleAtFees >= p.minEligible;
|
|
497
|
-
|
|
499
|
+
// A buy's LP fee is on the SOL that reached the vault; a sell's on the curve's output.
|
|
500
|
+
const buyLpFee = side === 'buy' ? feeAmount(received, lpFeeBps) : 0n;
|
|
498
501
|
// A buy's cuts are the hook's quote fees; a sell's input side cuts nothing (the burn is not a cut), so its share is taken from the output.
|
|
499
502
|
const inputProtocolFee = side === 'buy' ? protocolShare(before.creatorFee + before.holderFee, protocolShareBps) : 0n;
|
|
500
|
-
const netIn = received -
|
|
501
|
-
const failed = (failure, protocolFee = inputProtocolFee) => ({ ...before, holderFeeOn, received, lpFee, protocolFee, netIn, amountOut: null, delivered: null, failure });
|
|
503
|
+
const netIn = received - buyLpFee - inputProtocolFee;
|
|
504
|
+
const failed = (failure, protocolFee = inputProtocolFee, carried = {}) => ({ ...before, holderFeeOn, received, lpFee: buyLpFee, protocolFee, netIn, amountOut: null, delivered: null, failure, ...carried });
|
|
502
505
|
if (received <= 0n || netIn <= 0n)
|
|
503
506
|
return failed('fees_exceed_input');
|
|
504
507
|
const out = curveOutput(r, side, netIn);
|
|
@@ -508,24 +511,33 @@ export function quoteLaunchSwap(r, side, amountIn, lpFeeBps, protocolShareBps, p
|
|
|
508
511
|
return failed('insufficient_liquidity');
|
|
509
512
|
if (side === 'buy') {
|
|
510
513
|
const after = launchAfterSwap('buy', out, p);
|
|
511
|
-
return { ...before, burn: after.burn, holderFeeOn, received, lpFee, protocolFee: inputProtocolFee, netIn, amountOut: out, delivered: out - after.burn, failure: null };
|
|
514
|
+
return { ...before, burn: after.burn, holderFeeOn, received, lpFee: buyLpFee, protocolFee: inputProtocolFee, netIn, amountOut: out, delivered: out - after.burn, failure: null };
|
|
512
515
|
}
|
|
513
|
-
|
|
516
|
+
// A sell: the LP fee leaves the curve's output before the hook is told the rest.
|
|
517
|
+
const lpFee = feeAmount(out, lpFeeBps);
|
|
518
|
+
if (lpFee >= out)
|
|
519
|
+
return failed('no_output', 0n, { lpFee });
|
|
520
|
+
const told = out - lpFee;
|
|
521
|
+
const after = launchAfterSwap('sell', told, { ...p, eligible: eligibleAtFees });
|
|
514
522
|
const protocolFee = protocolShare(after.creatorFee + after.holderFee, protocolShareBps);
|
|
515
|
-
if (after.creatorFee + after.holderFee + protocolFee >=
|
|
516
|
-
return failed('no_output', protocolFee);
|
|
517
|
-
return { creatorFee: after.creatorFee, holderFee: after.holderFee, burn: before.burn, holderFeeOn, received, lpFee, protocolFee, netIn, amountOut: out, delivered:
|
|
523
|
+
if (after.creatorFee + after.holderFee + protocolFee >= told)
|
|
524
|
+
return failed('no_output', protocolFee, { creatorFee: after.creatorFee, holderFee: after.holderFee, lpFee });
|
|
525
|
+
return { creatorFee: after.creatorFee, holderFee: after.holderFee, burn: before.burn, holderFeeOn, received, lpFee, protocolFee, netIn, amountOut: out, delivered: told - after.creatorFee - after.holderFee - protocolFee, failure: null };
|
|
518
526
|
}
|
|
519
|
-
/** What a launch-pool swap adds to its input reserve (the Rust reference's `to_reserve_in`): what reached the vault, less a buy's protocol fee. */
|
|
520
|
-
export const launchSwapToReserve = (side, q) => (side === 'buy' ? q.received - q.protocolFee : q.received);
|
|
521
527
|
/**
|
|
522
|
-
*
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
|
|
528
|
+
* What a launch-pool swap adds to its input reserve (the Rust reference's `to_reserve_in`): on a buy
|
|
529
|
+
* what goes into the curve (what reached the vault less the LP fee and the share, both Bordrless's;
|
|
530
|
+
* 0 when they take it all), on a sell what reached the vault.
|
|
531
|
+
*/
|
|
532
|
+
export const launchSwapToReserve = (side, q) => (side === 'buy' ? (q.netIn > 0n ? q.netIn : 0n) : q.received);
|
|
533
|
+
/**
|
|
534
|
+
* Whether a buy that lands leaves the launch ready to graduate, so `graduate` can follow it in the
|
|
535
|
+
* same transaction: the pool's quote reserve at or above the graduation threshold, or the curve sold
|
|
536
|
+
* out (the buy takes every token it has left). The LP fee does not compound, so the two come
|
|
537
|
+
* together, and a hook's cut on buys can keep the reserve just short of the threshold.
|
|
526
538
|
*/
|
|
527
539
|
export function buyGraduates(r, q, graduationQuote) {
|
|
528
|
-
return q.failure === null && r.quoteReserve + launchSwapToReserve('buy', q) >= graduationQuote;
|
|
540
|
+
return q.failure === null && (r.quoteReserve + launchSwapToReserve('buy', q) >= graduationQuote || q.amountOut === r.baseReserve);
|
|
529
541
|
}
|
|
530
542
|
/**
|
|
531
543
|
* §8.2 `maxAmountIn` on a curve pool: the largest buy the curve can still fill with these fees (one
|
package/dist/programs.d.ts
CHANGED
|
@@ -12,7 +12,33 @@ export declare const PROGRAM_IDS: {
|
|
|
12
12
|
readonly taxHook: "8tjnVSreJGBRQFyDBf1SyyhBgLsdBxa2rHYh9sbxFyX7";
|
|
13
13
|
/** The v2 token-rules hook (docs/hooks-v2.md §4): holder rewards, max wallet and the two locks. */
|
|
14
14
|
readonly kit: "14RJQXPdJfkehit6ezktjd3xujamf8nVSKw2shKamaEH";
|
|
15
|
+
/** Half-Life (programs/half_life): an exit fee that halves every six hours a token is held, burned. */
|
|
16
|
+
readonly halfLife: "53SpmtkdPWQ63mWoDeXk8P9tuwiT4ed2Wx4fwfy5NSF8";
|
|
15
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* Half-Life, Bordrless's own token hook (programs/half_life/README.md): the `LaunchConfig` the
|
|
20
|
+
* launch form's Half-Life path launches from (no kit rules, creator fee 1%, the hook with
|
|
21
|
+
* `flags`), and the fee curve the program has fixed: `maxFeePpm` for tokens that just arrived,
|
|
22
|
+
* halved every `halfLifeSecs`, linear within each, zero from `zeroAfterSecs`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const HALF_LIFE: {
|
|
25
|
+
readonly program: "53SpmtkdPWQ63mWoDeXk8P9tuwiT4ed2Wx4fwfy5NSF8";
|
|
26
|
+
readonly launchConfig: "ABz5Je9FznnotUQxxaj28vn18t1Wv9SsDzEfDxGLRJY";
|
|
27
|
+
/** `BEFORE_TRANSFER | TRANSFER_RETURNS_DELTA | WRITES_HOOK_DATA`. */
|
|
28
|
+
readonly flags: 193;
|
|
29
|
+
readonly creatorFeeBps: 100;
|
|
30
|
+
readonly maxFeePpm: 200000;
|
|
31
|
+
readonly halfLifeSecs: 21600;
|
|
32
|
+
readonly zeroAfterSecs: 172800;
|
|
33
|
+
/** The token program's signer of the hook's callbacks (`["hook-authority", half_life]`). */
|
|
34
|
+
readonly tokenHookSigner: "FBZPj9PmV9dXL8U4qmRffXdXm11e23KEBnNgEVXxhfhF";
|
|
35
|
+
readonly readme: "https://github.com/BordrlessDex/bordrless-programs/tree/main/programs/half_life";
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Half-Life's exit fee, in parts per million, for tokens `ageSecs` old: the program's `fee_ppm`
|
|
39
|
+
* (20% at 0, halved every six hours, linear within each, 0 from 48 h).
|
|
40
|
+
*/
|
|
41
|
+
export declare function halfLifeFeePpm(ageSecs: number): number;
|
|
16
42
|
/** The wSOL mint, which stands for native SOL on the bridge. */
|
|
17
43
|
export declare const NATIVE_MINT = "So11111111111111111111111111111111111111112";
|
|
18
44
|
export declare const TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
package/dist/programs.js
CHANGED
|
@@ -12,7 +12,43 @@ export const PROGRAM_IDS = {
|
|
|
12
12
|
taxHook: '8tjnVSreJGBRQFyDBf1SyyhBgLsdBxa2rHYh9sbxFyX7',
|
|
13
13
|
/** The v2 token-rules hook (docs/hooks-v2.md §4): holder rewards, max wallet and the two locks. */
|
|
14
14
|
kit: '14RJQXPdJfkehit6ezktjd3xujamf8nVSKw2shKamaEH',
|
|
15
|
+
/** Half-Life (programs/half_life): an exit fee that halves every six hours a token is held, burned. */
|
|
16
|
+
halfLife: '53SpmtkdPWQ63mWoDeXk8P9tuwiT4ed2Wx4fwfy5NSF8',
|
|
15
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* Half-Life, Bordrless's own token hook (programs/half_life/README.md): the `LaunchConfig` the
|
|
20
|
+
* launch form's Half-Life path launches from (no kit rules, creator fee 1%, the hook with
|
|
21
|
+
* `flags`), and the fee curve the program has fixed: `maxFeePpm` for tokens that just arrived,
|
|
22
|
+
* halved every `halfLifeSecs`, linear within each, zero from `zeroAfterSecs`.
|
|
23
|
+
*/
|
|
24
|
+
export const HALF_LIFE = {
|
|
25
|
+
program: PROGRAM_IDS.halfLife,
|
|
26
|
+
launchConfig: 'ABz5Je9FznnotUQxxaj28vn18t1Wv9SsDzEfDxGLRJY',
|
|
27
|
+
/** `BEFORE_TRANSFER | TRANSFER_RETURNS_DELTA | WRITES_HOOK_DATA`. */
|
|
28
|
+
flags: 193,
|
|
29
|
+
creatorFeeBps: 100,
|
|
30
|
+
maxFeePpm: 200_000,
|
|
31
|
+
halfLifeSecs: 21_600,
|
|
32
|
+
zeroAfterSecs: 172_800,
|
|
33
|
+
/** The token program's signer of the hook's callbacks (`["hook-authority", half_life]`). */
|
|
34
|
+
tokenHookSigner: 'FBZPj9PmV9dXL8U4qmRffXdXm11e23KEBnNgEVXxhfhF',
|
|
35
|
+
readme: 'https://github.com/BordrlessDex/bordrless-programs/tree/main/programs/half_life',
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Half-Life's exit fee, in parts per million, for tokens `ageSecs` old: the program's `fee_ppm`
|
|
39
|
+
* (20% at 0, halved every six hours, linear within each, 0 from 48 h).
|
|
40
|
+
*/
|
|
41
|
+
export function halfLifeFeePpm(ageSecs) {
|
|
42
|
+
if (!(ageSecs > 0))
|
|
43
|
+
return HALF_LIFE.maxFeePpm;
|
|
44
|
+
const halvings = Math.floor(ageSecs / HALF_LIFE.halfLifeSecs);
|
|
45
|
+
if (halvings >= HALF_LIFE.zeroAfterSecs / HALF_LIFE.halfLifeSecs)
|
|
46
|
+
return 0;
|
|
47
|
+
const into = Math.floor(ageSecs) % HALF_LIFE.halfLifeSecs;
|
|
48
|
+
const hi = Math.floor(HALF_LIFE.maxFeePpm / 2 ** halvings);
|
|
49
|
+
const lo = Math.floor(HALF_LIFE.maxFeePpm / 2 ** (halvings + 1));
|
|
50
|
+
return hi - Math.floor(((hi - lo) * into) / HALF_LIFE.halfLifeSecs);
|
|
51
|
+
}
|
|
16
52
|
/** The wSOL mint, which stands for native SOL on the bridge. */
|
|
17
53
|
export const NATIVE_MINT = 'So11111111111111111111111111111111111111112';
|
|
18
54
|
export const TOKEN_PROGRAM_ID = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
|
package/dist/studio.d.ts
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
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 (its upgrade authority then handed to them); makes the config; and may list it
|
|
7
|
+
* on the marketplace, where every launch someone else makes from it pays them their share of the
|
|
8
|
+
* creator fee (`create_listed_config`, docs/hooks-v2.md §5.7).
|
|
9
|
+
*
|
|
10
|
+
* A Studio hook is written against one template (`STUDIO_TEMPLATE`): an Anchor program with a fixed
|
|
11
|
+
* `Cargo.toml` and the standard `prepare` (`STUDIO_PREPARE`), so the site can prepare any Studio hook
|
|
12
|
+
* for a new mint without knowing its code. The backend refuses source that leaves the template's
|
|
13
|
+
* limits (`StaticCheck`) before it is built, reviewed or paid for.
|
|
14
|
+
*/
|
|
15
|
+
import type { Address, PreparedTx } from './api.ts';
|
|
16
|
+
/** One source file of a hook. Only `src/**.rs` files; `Cargo.toml` is the template's and never sent. */
|
|
17
|
+
export interface StudioFile {
|
|
18
|
+
/** Relative path, e.g. `src/lib.rs`. */
|
|
19
|
+
path: string;
|
|
20
|
+
content: string;
|
|
21
|
+
}
|
|
22
|
+
/** What a project becomes: a config of existing rules alone, or a config with its own hook program. */
|
|
23
|
+
export type StudioKind = 'config' | 'hook';
|
|
24
|
+
/** The launch config a project makes (the arguments of `create_config` / `create_listed_config`). */
|
|
25
|
+
export interface StudioConfigDraft {
|
|
26
|
+
/** At most 32 bytes. */
|
|
27
|
+
label: string;
|
|
28
|
+
creatorFeeBps: number;
|
|
29
|
+
burnBuyBps: number;
|
|
30
|
+
burnSellBps: number;
|
|
31
|
+
/** Kit rules, for a `config` project only (a hook of one's own excludes them). */
|
|
32
|
+
holderFeeBuyBps: number;
|
|
33
|
+
holderFeeSellBps: number;
|
|
34
|
+
maxWalletBps: number;
|
|
35
|
+
creatorLockDays: number;
|
|
36
|
+
earlyWindowSecs: number;
|
|
37
|
+
earlyLockSecs: number;
|
|
38
|
+
/** `TOKEN_HOOK_FLAGS` the hook runs on, for a `hook` project; 0 for a `config` project. */
|
|
39
|
+
hookFlags: number;
|
|
40
|
+
/** List it on the marketplace (made with `create_listed_config`). */
|
|
41
|
+
listed: boolean;
|
|
42
|
+
/** The author's share of the creator fee on others' launches, bps of it: 1 to `MAX_AUTHOR_SHARE_BPS`. */
|
|
43
|
+
authorShareBps: number;
|
|
44
|
+
}
|
|
45
|
+
/** Where a project stands, in the order the Studio walks it. */
|
|
46
|
+
export type StudioStage = 'draft' | 'reviewed' | 'built' | 'paid' | 'deploying' | 'deployed' | 'configured' | 'listed';
|
|
47
|
+
export interface StudioProjectSummary {
|
|
48
|
+
id: string;
|
|
49
|
+
owner: Address;
|
|
50
|
+
name: string;
|
|
51
|
+
kind: StudioKind;
|
|
52
|
+
stage: StudioStage;
|
|
53
|
+
/** The deployed hook, once deployed. */
|
|
54
|
+
programId: Address | null;
|
|
55
|
+
/** The config made from it, once made. */
|
|
56
|
+
config: Address | null;
|
|
57
|
+
updatedAt: number;
|
|
58
|
+
}
|
|
59
|
+
export interface StudioProject extends StudioProjectSummary {
|
|
60
|
+
/** A one-paragraph description, shown on the marketplace when listed. */
|
|
61
|
+
description: string;
|
|
62
|
+
files: StudioFile[];
|
|
63
|
+
draft: StudioConfigDraft;
|
|
64
|
+
/** The last review of the current source; null when the source changed since. */
|
|
65
|
+
review: StudioReview | null;
|
|
66
|
+
/** The last build of the current source; null when the source changed since. */
|
|
67
|
+
build: StudioBuild | null;
|
|
68
|
+
deploy: StudioDeploy | null;
|
|
69
|
+
createdAt: number;
|
|
70
|
+
}
|
|
71
|
+
export interface StudioProjectCreateRequest {
|
|
72
|
+
name: string;
|
|
73
|
+
kind: StudioKind;
|
|
74
|
+
/** Start from a template (`STUDIO_STARTERS`), or blank. */
|
|
75
|
+
starter?: string;
|
|
76
|
+
}
|
|
77
|
+
/** A save: any of the fields; files replace the whole set. Changing files drops the review and the build. */
|
|
78
|
+
export interface StudioProjectUpdateRequest {
|
|
79
|
+
name?: string;
|
|
80
|
+
description?: string;
|
|
81
|
+
files?: StudioFile[];
|
|
82
|
+
draft?: Partial<StudioConfigDraft>;
|
|
83
|
+
}
|
|
84
|
+
/** `POST /v1/studio/session`: the wallet signs `message` (from `studioSignInMessage`), the backend answers a session token. */
|
|
85
|
+
export interface StudioSessionRequest {
|
|
86
|
+
wallet: Address;
|
|
87
|
+
/** The exact message signed. */
|
|
88
|
+
message: string;
|
|
89
|
+
/** Base58 ed25519 signature of the message's UTF-8 bytes. */
|
|
90
|
+
signature: string;
|
|
91
|
+
}
|
|
92
|
+
export interface StudioSessionResponse {
|
|
93
|
+
token: string;
|
|
94
|
+
wallet: Address;
|
|
95
|
+
expiresAt: number;
|
|
96
|
+
/** What the assistant still allows this wallet today. */
|
|
97
|
+
quota: StudioQuota;
|
|
98
|
+
}
|
|
99
|
+
export interface StudioQuota {
|
|
100
|
+
/** Assistant messages left today (UTC). */
|
|
101
|
+
messagesLeft: number;
|
|
102
|
+
messagesPerDay: number;
|
|
103
|
+
/** The assistant is off for everyone (no key, or today's budget spent). */
|
|
104
|
+
assistantOff: boolean;
|
|
105
|
+
}
|
|
106
|
+
/** The message a wallet signs to use Studio: no transaction, nothing moves. */
|
|
107
|
+
export declare function studioSignInMessage(wallet: Address, nonce: string, issuedAt: string): string;
|
|
108
|
+
/** The header the session token travels in, browser → site proxy → backend. */
|
|
109
|
+
export declare const STUDIO_SESSION_HEADER = "x-studio-session";
|
|
110
|
+
export interface StudioMessage {
|
|
111
|
+
id: string;
|
|
112
|
+
role: 'user' | 'assistant';
|
|
113
|
+
/** Markdown. An assistant message may carry proposals (below) as fenced blocks. */
|
|
114
|
+
content: string;
|
|
115
|
+
at: number;
|
|
116
|
+
/** For an assistant message: the changes it proposes, parsed from its fenced blocks. */
|
|
117
|
+
proposal: StudioProposal | null;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* What an assistant reply proposes: whole files (```rust file=src/lib.rs fences) and config
|
|
121
|
+
* fields (a ```json studio-config fence). The Studio shows them as a diff to apply or dismiss.
|
|
122
|
+
*/
|
|
123
|
+
export interface StudioProposal {
|
|
124
|
+
files: StudioFile[];
|
|
125
|
+
draft: Partial<StudioConfigDraft> | null;
|
|
126
|
+
/** Applied by the user (the project's files or draft were replaced by it). */
|
|
127
|
+
applied: boolean;
|
|
128
|
+
}
|
|
129
|
+
/** `POST /v1/studio/projects/:id/chat`: one user message; the reply is produced in the background. */
|
|
130
|
+
export interface StudioChatRequest {
|
|
131
|
+
content: string;
|
|
132
|
+
}
|
|
133
|
+
export interface StudioChatResponse {
|
|
134
|
+
job: string;
|
|
135
|
+
/** The user's message as stored. */
|
|
136
|
+
message: StudioMessage;
|
|
137
|
+
quota: StudioQuota;
|
|
138
|
+
}
|
|
139
|
+
/** `GET /v1/studio/chat/:job`: the reply so far; poll until `state` is not `running`. */
|
|
140
|
+
export interface StudioChatJob {
|
|
141
|
+
job: string;
|
|
142
|
+
state: 'running' | 'done' | 'failed';
|
|
143
|
+
/** The reply's text so far (all of it once done). */
|
|
144
|
+
text: string;
|
|
145
|
+
/** Once done: the stored message, its proposal parsed. */
|
|
146
|
+
message: StudioMessage | null;
|
|
147
|
+
error: string | null;
|
|
148
|
+
}
|
|
149
|
+
/** One of the template's limits, checked on the source before anything else (no model involved). */
|
|
150
|
+
export interface StaticCheck {
|
|
151
|
+
id: string;
|
|
152
|
+
ok: boolean;
|
|
153
|
+
/** What is checked, in words. */
|
|
154
|
+
label: string;
|
|
155
|
+
/** Where it failed: `src/lib.rs:42` and the offending text. */
|
|
156
|
+
detail: string | null;
|
|
157
|
+
}
|
|
158
|
+
export type FindingSeverity = 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
159
|
+
export interface ReviewFinding {
|
|
160
|
+
severity: FindingSeverity;
|
|
161
|
+
title: string;
|
|
162
|
+
detail: string;
|
|
163
|
+
/** `src/lib.rs:42`, when it points at a line. */
|
|
164
|
+
location: string | null;
|
|
165
|
+
}
|
|
166
|
+
/** `POST /v1/studio/projects/:id/review`: the static checks, then the assistant's security review. */
|
|
167
|
+
export interface StudioReview {
|
|
168
|
+
/** `fail`: a static check failed or a critical/high finding; deploy is refused. */
|
|
169
|
+
verdict: 'pass' | 'warn' | 'fail';
|
|
170
|
+
checks: StaticCheck[];
|
|
171
|
+
findings: ReviewFinding[];
|
|
172
|
+
/** A short paragraph: what the hook does, as the reviewer read it. */
|
|
173
|
+
summary: string;
|
|
174
|
+
/** sha256 of the source reviewed. */
|
|
175
|
+
sourceHash: string;
|
|
176
|
+
at: number;
|
|
177
|
+
}
|
|
178
|
+
/** `POST /v1/studio/projects/:id/build`: compiled by the build worker in the verifiable-build image. */
|
|
179
|
+
export interface StudioBuild {
|
|
180
|
+
state: 'queued' | 'building' | 'ok' | 'failed';
|
|
181
|
+
/** The program id the source was built for (its `declare_id!`), reserved for this project. */
|
|
182
|
+
programId: Address;
|
|
183
|
+
/** sha256 of the program binary (what `solana-verify get-executable-hash` prints). */
|
|
184
|
+
hash: string | null;
|
|
185
|
+
bytes: number | null;
|
|
186
|
+
/** The compiler's output, its tail. */
|
|
187
|
+
log: string;
|
|
188
|
+
sourceHash: string;
|
|
189
|
+
at: number;
|
|
190
|
+
}
|
|
191
|
+
/** `POST /v1/studio/projects/:id/deploy/quote`: what deploying the built hook costs, in lamports. */
|
|
192
|
+
export interface StudioDeployQuote {
|
|
193
|
+
/** Rent of the program's data account (the binary plus room to upgrade: `maxDataLen`). */
|
|
194
|
+
programDataRent: string;
|
|
195
|
+
/** Rent of the program account. */
|
|
196
|
+
programRent: string;
|
|
197
|
+
/** Transaction fees of writing and deploying it. */
|
|
198
|
+
fees: string;
|
|
199
|
+
/** Bordrless's service fee. */
|
|
200
|
+
service: string;
|
|
201
|
+
total: string;
|
|
202
|
+
maxDataLen: number;
|
|
203
|
+
/** The wallet the payment goes to (Studio's deployer). */
|
|
204
|
+
payTo: Address;
|
|
205
|
+
/** The payment transaction: a plain SOL transfer of `total` with a memo naming this deploy. */
|
|
206
|
+
transactions: PreparedTx[];
|
|
207
|
+
/** The quote holds until then (unix seconds). */
|
|
208
|
+
expiresAt: number;
|
|
209
|
+
}
|
|
210
|
+
export interface StudioDeployRequest {
|
|
211
|
+
/** The confirmed payment transaction. */
|
|
212
|
+
paymentSignature: string;
|
|
213
|
+
/** Hand the upgrade authority to the owner (default), or make the program final. */
|
|
214
|
+
authority: 'owner' | 'final';
|
|
215
|
+
}
|
|
216
|
+
export type StudioDeployState = 'awaiting_payment' | 'paid' | 'writing' | 'deploying' | 'handing_over' | 'deployed' | 'failed' | 'refunded';
|
|
217
|
+
export interface StudioDeploy {
|
|
218
|
+
state: StudioDeployState;
|
|
219
|
+
programId: Address;
|
|
220
|
+
/** Lamports paid, and the payment. */
|
|
221
|
+
paid: string | null;
|
|
222
|
+
paymentSignature: string | null;
|
|
223
|
+
/** Bytes written of the binary, while writing. */
|
|
224
|
+
written: number;
|
|
225
|
+
bytes: number;
|
|
226
|
+
deploySignature: string | null;
|
|
227
|
+
/** Who can upgrade it now: the owner, or null once final. */
|
|
228
|
+
upgradeAuthority: Address | null;
|
|
229
|
+
error: string | null;
|
|
230
|
+
refundSignature: string | null;
|
|
231
|
+
at: number;
|
|
232
|
+
}
|
|
233
|
+
/** `POST /v1/studio/projects/:id/config/prepare`: `create_config` or `create_listed_config` for the draft. */
|
|
234
|
+
export interface StudioConfigPrepareRequest {
|
|
235
|
+
/** A fresh keypair's address the browser made; it signs after the wallet. */
|
|
236
|
+
config: Address;
|
|
237
|
+
}
|
|
238
|
+
export interface StudioConfigPrepareResponse {
|
|
239
|
+
config: Address;
|
|
240
|
+
transactions: PreparedTx[];
|
|
241
|
+
}
|
|
242
|
+
export interface MarketplaceListing {
|
|
243
|
+
config: Address;
|
|
244
|
+
author: Address;
|
|
245
|
+
/** The config's on-chain label. */
|
|
246
|
+
label: string;
|
|
247
|
+
/** The author's title and description (from Studio), or the label alone. */
|
|
248
|
+
title: string;
|
|
249
|
+
description: string;
|
|
250
|
+
authorShareBps: number;
|
|
251
|
+
creatorFeeBps: number;
|
|
252
|
+
burnBuyBps: number;
|
|
253
|
+
burnSellBps: number;
|
|
254
|
+
holderFeeBuyBps: number;
|
|
255
|
+
holderFeeSellBps: number;
|
|
256
|
+
maxWalletBps: number;
|
|
257
|
+
customHook: Address | null;
|
|
258
|
+
customHookFlags: number;
|
|
259
|
+
/** The hook was built and deployed by Studio from source anyone can read. */
|
|
260
|
+
studioSource: boolean;
|
|
261
|
+
/** Who can upgrade the hook now (null: final, or no hook). */
|
|
262
|
+
hookUpgradeAuthority: Address | null;
|
|
263
|
+
/** The source passed review when it was deployed. */
|
|
264
|
+
reviewVerdict: 'pass' | 'warn' | null;
|
|
265
|
+
launches: number;
|
|
266
|
+
/** Paid to the author so far, lamports. */
|
|
267
|
+
authorEarned: string;
|
|
268
|
+
volumeUsd: number | null;
|
|
269
|
+
createdAt: number;
|
|
270
|
+
}
|
|
271
|
+
export interface MarketplaceListResponse {
|
|
272
|
+
listings: MarketplaceListing[];
|
|
273
|
+
total: number;
|
|
274
|
+
}
|
|
275
|
+
export interface MarketplaceDetail extends MarketplaceListing {
|
|
276
|
+
/** The hook's source when Studio built it. */
|
|
277
|
+
files: StudioFile[] | null;
|
|
278
|
+
buildHash: string | null;
|
|
279
|
+
review: StudioReview | null;
|
|
280
|
+
/** Launches made from it, newest first. */
|
|
281
|
+
recentLaunches: {
|
|
282
|
+
mint: Address;
|
|
283
|
+
symbol: string;
|
|
284
|
+
name: string;
|
|
285
|
+
image: string | null;
|
|
286
|
+
createdAt: number;
|
|
287
|
+
}[];
|
|
288
|
+
}
|
|
289
|
+
/** `POST /v1/author/prepare`: a config author's claims of their share, on up to four launches a transaction, paid as SOL. */
|
|
290
|
+
export interface AuthorPrepareRequest {
|
|
291
|
+
author: Address;
|
|
292
|
+
/** The launches to claim on; all with something to claim when absent. */
|
|
293
|
+
mints?: Address[];
|
|
294
|
+
}
|
|
295
|
+
export interface AuthorEarnings {
|
|
296
|
+
author: Address;
|
|
297
|
+
/** Waiting to be claimed on each launch: the author's part of what the launch holds. */
|
|
298
|
+
launches: {
|
|
299
|
+
mint: Address;
|
|
300
|
+
symbol: string;
|
|
301
|
+
config: Address;
|
|
302
|
+
claimable: string;
|
|
303
|
+
paid: string;
|
|
304
|
+
}[];
|
|
305
|
+
claimable: string;
|
|
306
|
+
paid: string;
|
|
307
|
+
}
|
|
308
|
+
/** `bordrless_launch::constants::MAX_AUTHOR_SHARE_BPS`: half the creator fee. */
|
|
309
|
+
export declare const MAX_AUTHOR_SHARE_BPS = 5000;
|
|
310
|
+
/** The share the Studio suggests. */
|
|
311
|
+
export declare const DEFAULT_AUTHOR_SHARE_BPS = 2000;
|
|
312
|
+
/**
|
|
313
|
+
* The standard `prepare` of a Studio hook: `prepare()` (no arguments) with the accounts
|
|
314
|
+
* `[payer (signer, writable), mint, state = PDA(["state", mint], hook) (writable), registry =
|
|
315
|
+
* PDA(["bordrless-hook-accounts", mint], hook) (writable), system program]`. It creates the hook's
|
|
316
|
+
* state for the mint and writes its registry; anyone may send it, once per mint.
|
|
317
|
+
*/
|
|
318
|
+
export declare const STUDIO_PREPARE: {
|
|
319
|
+
readonly instruction: "prepare";
|
|
320
|
+
readonly stateSeed: "state";
|
|
321
|
+
};
|
|
322
|
+
/** Limits of a project's source. */
|
|
323
|
+
export declare const STUDIO_LIMITS: {
|
|
324
|
+
readonly files: 8;
|
|
325
|
+
readonly bytes: 120000;
|
|
326
|
+
readonly messageChars: 8000;
|
|
327
|
+
};
|
|
328
|
+
/** Starters a new hook project can begin from (the template's `src/lib.rs` variants). */
|
|
329
|
+
export declare const STUDIO_STARTERS: readonly {
|
|
330
|
+
id: string;
|
|
331
|
+
name: string;
|
|
332
|
+
blurb: string;
|
|
333
|
+
}[];
|
package/dist/studio.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
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_launch::constants::MAX_AUTHOR_SHARE_BPS`: half the creator fee. */
|
|
9
|
+
export const MAX_AUTHOR_SHARE_BPS = 5_000;
|
|
10
|
+
/** The share the Studio suggests. */
|
|
11
|
+
export const DEFAULT_AUTHOR_SHARE_BPS = 2_000;
|
|
12
|
+
/**
|
|
13
|
+
* The standard `prepare` of a Studio hook: `prepare()` (no arguments) with the accounts
|
|
14
|
+
* `[payer (signer, writable), mint, state = PDA(["state", mint], hook) (writable), registry =
|
|
15
|
+
* PDA(["bordrless-hook-accounts", mint], hook) (writable), system program]`. It creates the hook's
|
|
16
|
+
* state for the mint and writes its registry; anyone may send it, once per mint.
|
|
17
|
+
*/
|
|
18
|
+
export const STUDIO_PREPARE = { instruction: 'prepare', stateSeed: 'state' };
|
|
19
|
+
/** Limits of a project's source. */
|
|
20
|
+
export const STUDIO_LIMITS = { files: 8, bytes: 120_000, messageChars: 8_000 };
|
|
21
|
+
/** Starters a new hook project can begin from (the template's `src/lib.rs` variants). */
|
|
22
|
+
export const STUDIO_STARTERS = [
|
|
23
|
+
{ id: 'blank', name: 'Blank hook', blurb: 'The template: every callback stubbed, nothing taken, nothing refused.' },
|
|
24
|
+
{ 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.' },
|
|
25
|
+
{ id: 'cooldown', name: 'Transfer cooldown', blurb: 'A holding that received tokens cannot send them on for a while, stamped in its hook data.' },
|
|
26
|
+
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bordrless/shared",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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",
|