@forgedevv/shared 0.0.0-stage → 0.1.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 +429 -0
- package/dist/api.js +264 -0
- package/dist/constants.d.ts +53 -0
- package/dist/constants.js +42 -0
- package/dist/db.d.ts +164 -0
- package/dist/db.js +38 -0
- package/dist/env.d.ts +21 -0
- package/dist/env.js +92 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/jobs.d.ts +44 -0
- package/dist/jobs.js +76 -0
- package/dist/site-config.d.ts +66 -0
- package/dist/site-config.js +48 -0
- package/dist/spec.d.ts +66 -0
- package/dist/spec.js +121 -0
- package/dist/web-client.d.ts +176 -0
- package/dist/web-client.js +37 -0
- package/package.json +38 -3
- package/README.md +0 -3
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Business constants shared by every FORGE app (docs/INTERFACES.md §1).
|
|
3
|
+
* Percentages are expressed in basis points (bps) unless the name says `Pct`.
|
|
4
|
+
*/
|
|
5
|
+
export declare const PRICING: {
|
|
6
|
+
readonly creationUsd: 33;
|
|
7
|
+
readonly modificationUsd: 5.5;
|
|
8
|
+
readonly includedModifications: 2;
|
|
9
|
+
readonly maxAttemptsBeforeRefund: 2;
|
|
10
|
+
readonly quoteValiditySeconds: 120;
|
|
11
|
+
};
|
|
12
|
+
export declare const FEES: {
|
|
13
|
+
/** Our fee on our own buy button (before graduation). */
|
|
14
|
+
readonly platformFeeBps: 30;
|
|
15
|
+
/** After graduation; Jupiter keeps 20 % of it. */
|
|
16
|
+
readonly jupiterIntegratorFeeBps: 30;
|
|
17
|
+
/** FORGE creator share on the coin of every launchpad. */
|
|
18
|
+
readonly forgeCreatorSharePct: 25;
|
|
19
|
+
};
|
|
20
|
+
export declare const CLIENT_BOUNDS: {
|
|
21
|
+
/** Trading fee range offered to clients. */
|
|
22
|
+
readonly tradingFeeBps: {
|
|
23
|
+
readonly min: 50;
|
|
24
|
+
readonly max: 200;
|
|
25
|
+
};
|
|
26
|
+
readonly coinCreatorSharePct: {
|
|
27
|
+
readonly min: 0;
|
|
28
|
+
readonly max: 50;
|
|
29
|
+
readonly default: 25;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Coin creation fee set by the client: 0 (no fee) or between 0.001 and 1 SOL
|
|
33
|
+
* (0.001 SOL = MIN_POOL_CREATION_FEE of the SDK). Whether the SDK accepts 0 must be
|
|
34
|
+
* confirmed by devnet test 1; otherwise the minimum becomes 0.001.
|
|
35
|
+
*/
|
|
36
|
+
readonly poolCreationFeeSol: {
|
|
37
|
+
readonly min: 0.001;
|
|
38
|
+
readonly max: 1;
|
|
39
|
+
readonly allowZero: true;
|
|
40
|
+
};
|
|
41
|
+
/** Imposed (Meteora migration bots). */
|
|
42
|
+
readonly migrationThresholdSol: 10;
|
|
43
|
+
};
|
|
44
|
+
export declare const OPS: {
|
|
45
|
+
readonly dormantDaysBeforeSleep: 30;
|
|
46
|
+
readonly claimIntervalHours: 24;
|
|
47
|
+
readonly agentBudgetUsdPerJob: 15;
|
|
48
|
+
readonly agentTimeoutMinutes: 30;
|
|
49
|
+
/** Past this delay, an active job with no news is considered crashed. */
|
|
50
|
+
readonly jobLockStaleMinutes: 45;
|
|
51
|
+
};
|
|
52
|
+
/** 1 SOL = 1_000_000_000 lamports. */
|
|
53
|
+
export declare const LAMPORTS_PER_SOL = 1000000000;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Business constants shared by every FORGE app (docs/INTERFACES.md §1).
|
|
3
|
+
* Percentages are expressed in basis points (bps) unless the name says `Pct`.
|
|
4
|
+
*/
|
|
5
|
+
export const PRICING = {
|
|
6
|
+
creationUsd: 33,
|
|
7
|
+
modificationUsd: 5.5,
|
|
8
|
+
includedModifications: 2,
|
|
9
|
+
maxAttemptsBeforeRefund: 2,
|
|
10
|
+
quoteValiditySeconds: 120,
|
|
11
|
+
};
|
|
12
|
+
export const FEES = {
|
|
13
|
+
/** Our fee on our own buy button (before graduation). */
|
|
14
|
+
platformFeeBps: 30,
|
|
15
|
+
/** After graduation; Jupiter keeps 20 % of it. */
|
|
16
|
+
jupiterIntegratorFeeBps: 30,
|
|
17
|
+
/** FORGE creator share on the coin of every launchpad. */
|
|
18
|
+
forgeCreatorSharePct: 25,
|
|
19
|
+
};
|
|
20
|
+
export const CLIENT_BOUNDS = {
|
|
21
|
+
/** Trading fee range offered to clients. */
|
|
22
|
+
tradingFeeBps: { min: 50, max: 200 },
|
|
23
|
+
coinCreatorSharePct: { min: 0, max: 50, default: 25 },
|
|
24
|
+
/**
|
|
25
|
+
* Coin creation fee set by the client: 0 (no fee) or between 0.001 and 1 SOL
|
|
26
|
+
* (0.001 SOL = MIN_POOL_CREATION_FEE of the SDK). Whether the SDK accepts 0 must be
|
|
27
|
+
* confirmed by devnet test 1; otherwise the minimum becomes 0.001.
|
|
28
|
+
*/
|
|
29
|
+
poolCreationFeeSol: { min: 0.001, max: 1, allowZero: true },
|
|
30
|
+
/** Imposed (Meteora migration bots). */
|
|
31
|
+
migrationThresholdSol: 10,
|
|
32
|
+
};
|
|
33
|
+
export const OPS = {
|
|
34
|
+
dormantDaysBeforeSleep: 30,
|
|
35
|
+
claimIntervalHours: 24,
|
|
36
|
+
agentBudgetUsdPerJob: 15,
|
|
37
|
+
agentTimeoutMinutes: 30,
|
|
38
|
+
/** Past this delay, an active job with no news is considered crashed. */
|
|
39
|
+
jobLockStaleMinutes: 45,
|
|
40
|
+
};
|
|
41
|
+
/** 1 SOL = 1_000_000_000 lamports. */
|
|
42
|
+
export const LAMPORTS_PER_SOL = 1_000_000_000;
|
package/dist/db.d.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { FailedStage, JobStatus, JobType } from './jobs.js';
|
|
3
|
+
import { type LaunchpadSpec } from './spec.js';
|
|
4
|
+
/**
|
|
5
|
+
* Row types of the Supabase tables (docs/INTERFACES.md §5). Column names are kept in snake_case.
|
|
6
|
+
* Nullability mirrors the SQL exactly: a column without `not null` is typed `| null`, even when
|
|
7
|
+
* it has a default.
|
|
8
|
+
*/
|
|
9
|
+
export declare const LaunchpadStatus: z.ZodEnum<{
|
|
10
|
+
live: "live";
|
|
11
|
+
draft: "draft";
|
|
12
|
+
sleeping: "sleeping";
|
|
13
|
+
disabled: "disabled";
|
|
14
|
+
}>;
|
|
15
|
+
export type LaunchpadStatus = z.infer<typeof LaunchpadStatus>;
|
|
16
|
+
export declare const PaymentStatus: z.ZodEnum<{
|
|
17
|
+
refunded: "refunded";
|
|
18
|
+
quoted: "quoted";
|
|
19
|
+
confirmed: "confirmed";
|
|
20
|
+
expired: "expired";
|
|
21
|
+
}>;
|
|
22
|
+
export type PaymentStatus = z.infer<typeof PaymentStatus>;
|
|
23
|
+
export declare const PaymentKind: z.ZodEnum<{
|
|
24
|
+
creation: "creation";
|
|
25
|
+
modification: "modification";
|
|
26
|
+
}>;
|
|
27
|
+
export type PaymentKind = z.infer<typeof PaymentKind>;
|
|
28
|
+
export declare const ChatRole: z.ZodEnum<{
|
|
29
|
+
user: "user";
|
|
30
|
+
assistant: "assistant";
|
|
31
|
+
system: "system";
|
|
32
|
+
}>;
|
|
33
|
+
export type ChatRole = z.infer<typeof ChatRole>;
|
|
34
|
+
/** Kill switches. */
|
|
35
|
+
export declare const FlagKey: z.ZodEnum<{
|
|
36
|
+
deploys_paused: "deploys_paused";
|
|
37
|
+
buyback_paused: "buyback_paused";
|
|
38
|
+
signups_paused: "signups_paused";
|
|
39
|
+
claims_paused: "claims_paused";
|
|
40
|
+
cashbox_sweep_paused: "cashbox_sweep_paused";
|
|
41
|
+
refunds_paused: "refunds_paused";
|
|
42
|
+
}>;
|
|
43
|
+
export type FlagKey = z.infer<typeof FlagKey>;
|
|
44
|
+
/** ISO 8601 timestamp as returned by PostgREST for `timestamptz`. */
|
|
45
|
+
export type Timestamptz = string;
|
|
46
|
+
/**
|
|
47
|
+
* Postgres `bigint` / `numeric`: PostgREST may return a JSON number or a string. Convert with
|
|
48
|
+
* `BigInt(String(value))` for lamports, never with floating point math.
|
|
49
|
+
*/
|
|
50
|
+
export type DbBigint = number | string;
|
|
51
|
+
export type DbNumeric = number | string;
|
|
52
|
+
export interface UserRow {
|
|
53
|
+
wallet: string;
|
|
54
|
+
created_at: Timestamptz | null;
|
|
55
|
+
}
|
|
56
|
+
export interface LaunchpadRow {
|
|
57
|
+
id: string;
|
|
58
|
+
owner_wallet: string;
|
|
59
|
+
slug: string;
|
|
60
|
+
spec: LaunchpadSpec;
|
|
61
|
+
github_repo: string | null;
|
|
62
|
+
vercel_project_id: string | null;
|
|
63
|
+
/** Meteora config address. */
|
|
64
|
+
launchpad_config: string | null;
|
|
65
|
+
launchpad_coin_config: string | null;
|
|
66
|
+
launchpad_coin_mint: string | null;
|
|
67
|
+
/** Identifier of the creator wallet inside the signer (never the key). */
|
|
68
|
+
creator_wallet_ref: string | null;
|
|
69
|
+
included_modifications_left: number | null;
|
|
70
|
+
status: LaunchpadStatus;
|
|
71
|
+
last_trade_at: Timestamptz | null;
|
|
72
|
+
created_at: Timestamptz | null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* `jobs.owner_tx_details` (jsonb): the public accounts of the launch transaction stored in
|
|
76
|
+
* `jobs.owner_tx`, as the signer reported them (`details` of `POST /v1/launch-coin/prepare`). The
|
|
77
|
+
* builder writes it in the same update as `owner_tx`; apps/web pins these accounts when it checks
|
|
78
|
+
* the stored transaction (`verifyLaunchCoinTransaction` of @forge/core) and hands them to the
|
|
79
|
+
* browser (`OwnerTransactionLaunch`), instead of reading them back from the transaction.
|
|
80
|
+
* `config` is the launchpad coin config. Null on rows written before migration 0009.
|
|
81
|
+
*/
|
|
82
|
+
export declare const JobOwnerTxDetails: z.ZodObject<{
|
|
83
|
+
config: z.ZodString;
|
|
84
|
+
pool: z.ZodString;
|
|
85
|
+
creator: z.ZodString;
|
|
86
|
+
nonceAccount: z.ZodString;
|
|
87
|
+
metadataUri: z.ZodURL;
|
|
88
|
+
}, z.core.$strip>;
|
|
89
|
+
export type JobOwnerTxDetails = z.infer<typeof JobOwnerTxDetails>;
|
|
90
|
+
export interface JobRow {
|
|
91
|
+
id: string;
|
|
92
|
+
launchpad_id: string;
|
|
93
|
+
type: JobType;
|
|
94
|
+
status: JobStatus;
|
|
95
|
+
/** Build attempts only. */
|
|
96
|
+
attempts: number;
|
|
97
|
+
/** Set when status = 'failed'. */
|
|
98
|
+
failed_stage: FailedStage | null;
|
|
99
|
+
/** Client request (modifications). */
|
|
100
|
+
request: string | null;
|
|
101
|
+
preview_url: string | null;
|
|
102
|
+
/** Partially signed launch transaction (base64) with a durable nonce. */
|
|
103
|
+
owner_tx: string | null;
|
|
104
|
+
/** Launch accounts of `owner_tx` (jsonb, validate with `JobOwnerTxDetails` when reading). */
|
|
105
|
+
owner_tx_details: JobOwnerTxDetails | null;
|
|
106
|
+
error: string | null;
|
|
107
|
+
api_cost_usd: DbNumeric | null;
|
|
108
|
+
/** Id of the worker holding the job. */
|
|
109
|
+
locked_by: string | null;
|
|
110
|
+
locked_at: Timestamptz | null;
|
|
111
|
+
created_at: Timestamptz | null;
|
|
112
|
+
updated_at: Timestamptz | null;
|
|
113
|
+
}
|
|
114
|
+
export interface PaymentRow {
|
|
115
|
+
id: string;
|
|
116
|
+
job_id: string;
|
|
117
|
+
/** = launchpads.owner_wallet */
|
|
118
|
+
payer_wallet: string;
|
|
119
|
+
kind: PaymentKind;
|
|
120
|
+
usd_amount: DbNumeric;
|
|
121
|
+
lamports: DbBigint;
|
|
122
|
+
quote_expires_at: Timestamptz;
|
|
123
|
+
tx_signature: string | null;
|
|
124
|
+
status: PaymentStatus;
|
|
125
|
+
refund_signature: string | null;
|
|
126
|
+
created_at: Timestamptz | null;
|
|
127
|
+
}
|
|
128
|
+
export interface ConversationRow {
|
|
129
|
+
id: string;
|
|
130
|
+
owner_wallet: string;
|
|
131
|
+
/** Null while designing, set when the spec is confirmed. */
|
|
132
|
+
launchpad_id: string | null;
|
|
133
|
+
created_at: Timestamptz | null;
|
|
134
|
+
}
|
|
135
|
+
export interface ChatMessageRow {
|
|
136
|
+
id: number;
|
|
137
|
+
conversation_id: string;
|
|
138
|
+
role: ChatRole;
|
|
139
|
+
content: string;
|
|
140
|
+
created_at: Timestamptz | null;
|
|
141
|
+
}
|
|
142
|
+
export interface JobEventRow {
|
|
143
|
+
id: number;
|
|
144
|
+
job_id: string;
|
|
145
|
+
/** Shown in the chat in real time. */
|
|
146
|
+
message: string;
|
|
147
|
+
created_at: Timestamptz | null;
|
|
148
|
+
}
|
|
149
|
+
export interface FlagRow {
|
|
150
|
+
key: FlagKey;
|
|
151
|
+
value: boolean;
|
|
152
|
+
}
|
|
153
|
+
/** Table name -> row type. */
|
|
154
|
+
export interface Tables {
|
|
155
|
+
users: UserRow;
|
|
156
|
+
launchpads: LaunchpadRow;
|
|
157
|
+
jobs: JobRow;
|
|
158
|
+
payments: PaymentRow;
|
|
159
|
+
conversations: ConversationRow;
|
|
160
|
+
chat_messages: ChatMessageRow;
|
|
161
|
+
job_events: JobEventRow;
|
|
162
|
+
flags: FlagRow;
|
|
163
|
+
}
|
|
164
|
+
export type TableName = keyof Tables;
|
package/dist/db.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SolanaAddress } from './spec.js';
|
|
3
|
+
/**
|
|
4
|
+
* Row types of the Supabase tables (docs/INTERFACES.md §5). Column names are kept in snake_case.
|
|
5
|
+
* Nullability mirrors the SQL exactly: a column without `not null` is typed `| null`, even when
|
|
6
|
+
* it has a default.
|
|
7
|
+
*/
|
|
8
|
+
export const LaunchpadStatus = z.enum(['draft', 'live', 'sleeping', 'disabled']);
|
|
9
|
+
export const PaymentStatus = z.enum(['quoted', 'confirmed', 'expired', 'refunded']);
|
|
10
|
+
export const PaymentKind = z.enum(['creation', 'modification']);
|
|
11
|
+
export const ChatRole = z.enum(['user', 'assistant', 'system']);
|
|
12
|
+
/** Kill switches. */
|
|
13
|
+
export const FlagKey = z.enum([
|
|
14
|
+
'deploys_paused',
|
|
15
|
+
'buyback_paused',
|
|
16
|
+
'signups_paused',
|
|
17
|
+
'claims_paused',
|
|
18
|
+
'cashbox_sweep_paused',
|
|
19
|
+
'refunds_paused',
|
|
20
|
+
]);
|
|
21
|
+
/**
|
|
22
|
+
* `jobs.owner_tx_details` (jsonb): the public accounts of the launch transaction stored in
|
|
23
|
+
* `jobs.owner_tx`, as the signer reported them (`details` of `POST /v1/launch-coin/prepare`). The
|
|
24
|
+
* builder writes it in the same update as `owner_tx`; apps/web pins these accounts when it checks
|
|
25
|
+
* the stored transaction (`verifyLaunchCoinTransaction` of @forge/core) and hands them to the
|
|
26
|
+
* browser (`OwnerTransactionLaunch`), instead of reading them back from the transaction.
|
|
27
|
+
* `config` is the launchpad coin config. Null on rows written before migration 0009.
|
|
28
|
+
*/
|
|
29
|
+
export const JobOwnerTxDetails = z.object({
|
|
30
|
+
config: SolanaAddress,
|
|
31
|
+
pool: SolanaAddress,
|
|
32
|
+
/** FORGE creator wallet of the launchpad: pool creator and durable nonce authority. */
|
|
33
|
+
creator: SolanaAddress,
|
|
34
|
+
/** Durable nonce account of the launch transaction. */
|
|
35
|
+
nonceAccount: SolanaAddress,
|
|
36
|
+
/** Coin metadata URI written by the pool creation (https, kept exactly as sent). */
|
|
37
|
+
metadataUri: z.url({ protocol: /^https$/, error: 'Must be an https URL' }),
|
|
38
|
+
});
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const R2_ENV: readonly ["R2_ACCESS_KEY_ID", "R2_SECRET_ACCESS_KEY", "R2_ACCOUNT_ID", "R2_BUCKET"];
|
|
2
|
+
/** Variables that may be absent. FORGE_MINT is absent before the $FORGE launch. */
|
|
3
|
+
export declare const OPTIONAL_ENV: readonly ["FORGE_MINT"];
|
|
4
|
+
/**
|
|
5
|
+
* apps/web. RPC_URL and SUPABASE_SERVICE_ROLE_KEY are server-only.
|
|
6
|
+
* FORGE_GATING_AMOUNT is required only when FORGE_MINT is set.
|
|
7
|
+
*/
|
|
8
|
+
export declare const WEB_ENV: readonly ["SOLANA_CLUSTER", "RPC_URL", "SUPABASE_URL", "SUPABASE_ANON_KEY", "SUPABASE_SERVICE_ROLE_KEY", "ANTHROPIC_API_KEY", "FORGE_MINT", "FORGE_GATING_AMOUNT", "FORGE_CASHBOX_WALLET", "JUPITER_API_KEY", "SESSION_SECRET", "SUPABASE_JWT_SECRET", "NEXT_PUBLIC_APP_URL", "NEXT_PUBLIC_SUPABASE_URL", "NEXT_PUBLIC_SUPABASE_ANON_KEY", "NEXT_PUBLIC_SOLANA_CLUSTER", "R2_ACCESS_KEY_ID", "R2_SECRET_ACCESS_KEY", "R2_ACCOUNT_ID", "R2_BUCKET"];
|
|
9
|
+
/** apps/launchpad-template. RPC_URL is server-only; FORGE_* addresses are read through @forge/core. */
|
|
10
|
+
export declare const TEMPLATE_ENV: readonly ["SOLANA_CLUSTER", "RPC_URL", "FORGE_MULTISIG_VAULT", "FORGE_METEORA_REFERRAL_ACCOUNT", "FORGE_PLATFORM_FEE_WALLET", "FORGE_JUPITER_REFERRAL_ACCOUNT", "JUPITER_API_KEY", "R2_ACCESS_KEY_ID", "R2_SECRET_ACCESS_KEY", "R2_ACCOUNT_ID", "R2_BUCKET"];
|
|
11
|
+
/** Variables the builder does not use itself but copies into each client Vercel project. */
|
|
12
|
+
export declare const BUILDER_VERCEL_INJECTED_ENV: readonly ["FORGE_MULTISIG_VAULT", "FORGE_METEORA_REFERRAL_ACCOUNT", "FORGE_PLATFORM_FEE_WALLET", "FORGE_JUPITER_REFERRAL_ACCOUNT", "JUPITER_API_KEY", "R2_ACCESS_KEY_ID", "R2_SECRET_ACCESS_KEY", "R2_ACCOUNT_ID", "R2_BUCKET"];
|
|
13
|
+
/** apps/builder. ANTHROPIC_API_KEY is used by the gateway only. */
|
|
14
|
+
export declare const BUILDER_ENV: readonly ["SOLANA_CLUSTER", "SUPABASE_URL", "SUPABASE_SERVICE_ROLE_KEY", "ANTHROPIC_API_KEY", "FORGE_MULTISIG_VAULT", "FORGE_METEORA_REFERRAL_ACCOUNT", "FORGE_PLATFORM_FEE_WALLET", "FORGE_JUPITER_REFERRAL_ACCOUNT", "JUPITER_API_KEY", "R2_ACCESS_KEY_ID", "R2_SECRET_ACCESS_KEY", "R2_ACCOUNT_ID", "R2_BUCKET", "GITHUB_APP_ID", "GITHUB_APP_PRIVATE_KEY", "GITHUB_ORG", "VERCEL_TOKEN", "VERCEL_TEAM_ID", "SIGNER_URL", "SIGNER_HMAC_SECRET", "TELEGRAM_BOT_TOKEN", "TELEGRAM_CHAT_ID"];
|
|
15
|
+
/** apps/signer. FORGE_MINT is used for the buyback (simulation mode when absent). */
|
|
16
|
+
export declare const SIGNER_ENV: readonly ["SOLANA_CLUSTER", "RPC_URL", "SUPABASE_URL", "SUPABASE_SERVICE_ROLE_KEY", "FORGE_MINT", "FORGE_CASHBOX_WALLET", "FORGE_MULTISIG_VAULT", "FORGE_JUPITER_REFERRAL_ACCOUNT", "JUPITER_API_KEY", "SIGNER_URL", "SIGNER_HMAC_SECRET", "SIGNER_KEYSTORE_PASSPHRASE", "SIGNER_KEYSTORE_DIR", "SIGNER_ALLOWED_IPS", "SIGNER_PORT", "TELEGRAM_BOT_TOKEN", "TELEGRAM_CHAT_ID"];
|
|
17
|
+
export type WebEnvName = (typeof WEB_ENV)[number];
|
|
18
|
+
export type TemplateEnvName = (typeof TEMPLATE_ENV)[number];
|
|
19
|
+
export type BuilderEnvName = (typeof BUILDER_ENV)[number];
|
|
20
|
+
export type SignerEnvName = (typeof SIGNER_ENV)[number];
|
|
21
|
+
export type EnvName = WebEnvName | TemplateEnvName | BuilderEnvName | SignerEnvName;
|
package/dist/env.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Environment variable names per app (docs/INTERFACES.md §8). Names only, never values.
|
|
3
|
+
* `R2_*` is expanded to the variables of the fun-launch scaffold (docs/METEORA.md).
|
|
4
|
+
*/
|
|
5
|
+
export const R2_ENV = [
|
|
6
|
+
'R2_ACCESS_KEY_ID',
|
|
7
|
+
'R2_SECRET_ACCESS_KEY',
|
|
8
|
+
'R2_ACCOUNT_ID',
|
|
9
|
+
'R2_BUCKET',
|
|
10
|
+
];
|
|
11
|
+
/** Variables that may be absent. FORGE_MINT is absent before the $FORGE launch. */
|
|
12
|
+
export const OPTIONAL_ENV = ['FORGE_MINT'];
|
|
13
|
+
/**
|
|
14
|
+
* apps/web. RPC_URL and SUPABASE_SERVICE_ROLE_KEY are server-only.
|
|
15
|
+
* FORGE_GATING_AMOUNT is required only when FORGE_MINT is set.
|
|
16
|
+
*/
|
|
17
|
+
export const WEB_ENV = [
|
|
18
|
+
'SOLANA_CLUSTER',
|
|
19
|
+
'RPC_URL',
|
|
20
|
+
'SUPABASE_URL',
|
|
21
|
+
'SUPABASE_ANON_KEY',
|
|
22
|
+
'SUPABASE_SERVICE_ROLE_KEY',
|
|
23
|
+
'ANTHROPIC_API_KEY',
|
|
24
|
+
'FORGE_MINT',
|
|
25
|
+
'FORGE_GATING_AMOUNT',
|
|
26
|
+
'FORGE_CASHBOX_WALLET',
|
|
27
|
+
'JUPITER_API_KEY',
|
|
28
|
+
'SESSION_SECRET',
|
|
29
|
+
'SUPABASE_JWT_SECRET',
|
|
30
|
+
'NEXT_PUBLIC_APP_URL',
|
|
31
|
+
'NEXT_PUBLIC_SUPABASE_URL',
|
|
32
|
+
'NEXT_PUBLIC_SUPABASE_ANON_KEY',
|
|
33
|
+
'NEXT_PUBLIC_SOLANA_CLUSTER',
|
|
34
|
+
...R2_ENV,
|
|
35
|
+
];
|
|
36
|
+
/** apps/launchpad-template. RPC_URL is server-only; FORGE_* addresses are read through @forge/core. */
|
|
37
|
+
export const TEMPLATE_ENV = [
|
|
38
|
+
'SOLANA_CLUSTER',
|
|
39
|
+
'RPC_URL',
|
|
40
|
+
'FORGE_MULTISIG_VAULT',
|
|
41
|
+
'FORGE_METEORA_REFERRAL_ACCOUNT',
|
|
42
|
+
'FORGE_PLATFORM_FEE_WALLET',
|
|
43
|
+
'FORGE_JUPITER_REFERRAL_ACCOUNT',
|
|
44
|
+
'JUPITER_API_KEY',
|
|
45
|
+
...R2_ENV,
|
|
46
|
+
];
|
|
47
|
+
/** Variables the builder does not use itself but copies into each client Vercel project. */
|
|
48
|
+
export const BUILDER_VERCEL_INJECTED_ENV = [
|
|
49
|
+
'FORGE_MULTISIG_VAULT',
|
|
50
|
+
'FORGE_METEORA_REFERRAL_ACCOUNT',
|
|
51
|
+
'FORGE_PLATFORM_FEE_WALLET',
|
|
52
|
+
'FORGE_JUPITER_REFERRAL_ACCOUNT',
|
|
53
|
+
'JUPITER_API_KEY',
|
|
54
|
+
...R2_ENV,
|
|
55
|
+
];
|
|
56
|
+
/** apps/builder. ANTHROPIC_API_KEY is used by the gateway only. */
|
|
57
|
+
export const BUILDER_ENV = [
|
|
58
|
+
'SOLANA_CLUSTER',
|
|
59
|
+
'SUPABASE_URL',
|
|
60
|
+
'SUPABASE_SERVICE_ROLE_KEY',
|
|
61
|
+
'ANTHROPIC_API_KEY',
|
|
62
|
+
...BUILDER_VERCEL_INJECTED_ENV,
|
|
63
|
+
'GITHUB_APP_ID',
|
|
64
|
+
'GITHUB_APP_PRIVATE_KEY',
|
|
65
|
+
'GITHUB_ORG',
|
|
66
|
+
'VERCEL_TOKEN',
|
|
67
|
+
'VERCEL_TEAM_ID',
|
|
68
|
+
'SIGNER_URL',
|
|
69
|
+
'SIGNER_HMAC_SECRET',
|
|
70
|
+
'TELEGRAM_BOT_TOKEN',
|
|
71
|
+
'TELEGRAM_CHAT_ID',
|
|
72
|
+
];
|
|
73
|
+
/** apps/signer. FORGE_MINT is used for the buyback (simulation mode when absent). */
|
|
74
|
+
export const SIGNER_ENV = [
|
|
75
|
+
'SOLANA_CLUSTER',
|
|
76
|
+
'RPC_URL',
|
|
77
|
+
'SUPABASE_URL',
|
|
78
|
+
'SUPABASE_SERVICE_ROLE_KEY',
|
|
79
|
+
'FORGE_MINT',
|
|
80
|
+
'FORGE_CASHBOX_WALLET',
|
|
81
|
+
'FORGE_MULTISIG_VAULT',
|
|
82
|
+
'FORGE_JUPITER_REFERRAL_ACCOUNT',
|
|
83
|
+
'JUPITER_API_KEY',
|
|
84
|
+
'SIGNER_URL',
|
|
85
|
+
'SIGNER_HMAC_SECRET',
|
|
86
|
+
'SIGNER_KEYSTORE_PASSPHRASE',
|
|
87
|
+
'SIGNER_KEYSTORE_DIR',
|
|
88
|
+
'SIGNER_ALLOWED_IPS',
|
|
89
|
+
'SIGNER_PORT',
|
|
90
|
+
'TELEGRAM_BOT_TOKEN',
|
|
91
|
+
'TELEGRAM_CHAT_ID',
|
|
92
|
+
];
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/jobs.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Job statuses (docs/INTERFACES.md §4). */
|
|
3
|
+
export declare const JobStatus: z.ZodEnum<{
|
|
4
|
+
spec_ready: "spec_ready";
|
|
5
|
+
paid: "paid";
|
|
6
|
+
building: "building";
|
|
7
|
+
preview_ready: "preview_ready";
|
|
8
|
+
approved: "approved";
|
|
9
|
+
onchain_setup: "onchain_setup";
|
|
10
|
+
awaiting_owner_signature: "awaiting_owner_signature";
|
|
11
|
+
owner_signed: "owner_signed";
|
|
12
|
+
deploying: "deploying";
|
|
13
|
+
live: "live";
|
|
14
|
+
failed: "failed";
|
|
15
|
+
refunded: "refunded";
|
|
16
|
+
}>;
|
|
17
|
+
export type JobStatus = z.infer<typeof JobStatus>;
|
|
18
|
+
export declare const JobType: z.ZodEnum<{
|
|
19
|
+
create_launchpad: "create_launchpad";
|
|
20
|
+
modify_launchpad: "modify_launchpad";
|
|
21
|
+
}>;
|
|
22
|
+
export type JobType = z.infer<typeof JobType>;
|
|
23
|
+
export declare const FailedStage: z.ZodEnum<{
|
|
24
|
+
build: "build";
|
|
25
|
+
onchain: "onchain";
|
|
26
|
+
deploy: "deploy";
|
|
27
|
+
}>;
|
|
28
|
+
export type FailedStage = z.infer<typeof FailedStage>;
|
|
29
|
+
/** Statuses during which the builder holds the job lock (locked_by / locked_at). */
|
|
30
|
+
export declare const ACTIVE_JOB_STATUSES: readonly ["building", "onchain_setup", "deploying"];
|
|
31
|
+
export type ActiveJobStatus = (typeof ACTIVE_JOB_STATUSES)[number];
|
|
32
|
+
/** Happy path of a `create_launchpad` job, in order. */
|
|
33
|
+
export declare const CREATE_FLOW: readonly ["spec_ready", "paid", "building", "preview_ready", "approved", "onchain_setup", "awaiting_owner_signature", "owner_signed", "deploying", "live"];
|
|
34
|
+
/** Happy path of a `modify_launchpad` job, in order. */
|
|
35
|
+
export declare const MODIFY_FLOW: readonly ["spec_ready", "paid", "building", "preview_ready", "approved", "deploying", "live"];
|
|
36
|
+
export declare function isActiveJobStatus(status: JobStatus): status is ActiveJobStatus;
|
|
37
|
+
/** Ordered happy path for a job type. */
|
|
38
|
+
export declare function flowForJobType(type: JobType): readonly JobStatus[];
|
|
39
|
+
/**
|
|
40
|
+
* Stage recorded in failed_stage when a job fails (or is found stale) in the given status:
|
|
41
|
+
* building -> build, onchain_setup -> onchain, deploying -> deploy. Null for non-active statuses.
|
|
42
|
+
*/
|
|
43
|
+
export declare function failedStageForStatus(status: ActiveJobStatus): FailedStage;
|
|
44
|
+
export declare function failedStageForStatus(status: JobStatus): FailedStage | null;
|
package/dist/jobs.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Job statuses (docs/INTERFACES.md §4). */
|
|
3
|
+
export const JobStatus = z.enum([
|
|
4
|
+
/** Created by apps/web: spec confirmed (creation) or modification request recorded. */
|
|
5
|
+
'spec_ready',
|
|
6
|
+
/** Payment confirmed on-chain. */
|
|
7
|
+
'paid',
|
|
8
|
+
/** Builder: container running. */
|
|
9
|
+
'building',
|
|
10
|
+
/** Preview URL available. */
|
|
11
|
+
'preview_ready',
|
|
12
|
+
/** The client approved the preview. */
|
|
13
|
+
'approved',
|
|
14
|
+
/** Builder + signer: configs creation and launch transaction preparation. */
|
|
15
|
+
'onchain_setup',
|
|
16
|
+
/** Launch transaction ready in jobs.owner_tx; the client must sign the first buy. */
|
|
17
|
+
'awaiting_owner_signature',
|
|
18
|
+
/** apps/web: client transaction confirmed on-chain. */
|
|
19
|
+
'owner_signed',
|
|
20
|
+
/** Builder: merge to main, Vercel production deploy. */
|
|
21
|
+
'deploying',
|
|
22
|
+
'live',
|
|
23
|
+
/** A stage failed (see failed_stage and attempts). */
|
|
24
|
+
'failed',
|
|
25
|
+
'refunded',
|
|
26
|
+
]);
|
|
27
|
+
export const JobType = z.enum(['create_launchpad', 'modify_launchpad']);
|
|
28
|
+
export const FailedStage = z.enum(['build', 'onchain', 'deploy']);
|
|
29
|
+
/** Statuses during which the builder holds the job lock (locked_by / locked_at). */
|
|
30
|
+
export const ACTIVE_JOB_STATUSES = [
|
|
31
|
+
'building',
|
|
32
|
+
'onchain_setup',
|
|
33
|
+
'deploying',
|
|
34
|
+
];
|
|
35
|
+
/** Happy path of a `create_launchpad` job, in order. */
|
|
36
|
+
export const CREATE_FLOW = [
|
|
37
|
+
'spec_ready',
|
|
38
|
+
'paid',
|
|
39
|
+
'building',
|
|
40
|
+
'preview_ready',
|
|
41
|
+
'approved',
|
|
42
|
+
'onchain_setup',
|
|
43
|
+
'awaiting_owner_signature',
|
|
44
|
+
'owner_signed',
|
|
45
|
+
'deploying',
|
|
46
|
+
'live',
|
|
47
|
+
];
|
|
48
|
+
/** Happy path of a `modify_launchpad` job, in order. */
|
|
49
|
+
export const MODIFY_FLOW = [
|
|
50
|
+
'spec_ready',
|
|
51
|
+
'paid',
|
|
52
|
+
'building',
|
|
53
|
+
'preview_ready',
|
|
54
|
+
'approved',
|
|
55
|
+
'deploying',
|
|
56
|
+
'live',
|
|
57
|
+
];
|
|
58
|
+
export function isActiveJobStatus(status) {
|
|
59
|
+
return ACTIVE_JOB_STATUSES.includes(status);
|
|
60
|
+
}
|
|
61
|
+
/** Ordered happy path for a job type. */
|
|
62
|
+
export function flowForJobType(type) {
|
|
63
|
+
return type === 'create_launchpad' ? CREATE_FLOW : MODIFY_FLOW;
|
|
64
|
+
}
|
|
65
|
+
export function failedStageForStatus(status) {
|
|
66
|
+
switch (status) {
|
|
67
|
+
case 'building':
|
|
68
|
+
return 'build';
|
|
69
|
+
case 'onchain_setup':
|
|
70
|
+
return 'onchain';
|
|
71
|
+
case 'deploying':
|
|
72
|
+
return 'deploy';
|
|
73
|
+
default:
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const SolanaCluster: z.ZodEnum<{
|
|
3
|
+
devnet: "devnet";
|
|
4
|
+
"mainnet-beta": "mainnet-beta";
|
|
5
|
+
}>;
|
|
6
|
+
export type SolanaCluster = z.infer<typeof SolanaCluster>;
|
|
7
|
+
/** `live`, `sleeping` (dormant) or `disabled` (cut by FORGE). Written by the builder only. */
|
|
8
|
+
export declare const SiteMode: z.ZodEnum<{
|
|
9
|
+
live: "live";
|
|
10
|
+
sleeping: "sleeping";
|
|
11
|
+
disabled: "disabled";
|
|
12
|
+
}>;
|
|
13
|
+
export type SiteMode = z.infer<typeof SiteMode>;
|
|
14
|
+
/**
|
|
15
|
+
* `forge.config.json`, generated by the builder in each client repo and read by the client site
|
|
16
|
+
* (docs/INTERFACES.md §3). The builder agent may change `theme` and `content`, never `onchain`
|
|
17
|
+
* nor `mode`. FORGE addresses (multisig, referrals, platform fee wallet) are NOT in this file.
|
|
18
|
+
*/
|
|
19
|
+
export declare const ForgeSiteConfig: z.ZodObject<{
|
|
20
|
+
version: z.ZodLiteral<1>;
|
|
21
|
+
name: z.ZodString;
|
|
22
|
+
slug: z.ZodString;
|
|
23
|
+
mode: z.ZodEnum<{
|
|
24
|
+
live: "live";
|
|
25
|
+
sleeping: "sleeping";
|
|
26
|
+
disabled: "disabled";
|
|
27
|
+
}>;
|
|
28
|
+
onchain: z.ZodOptional<z.ZodObject<{
|
|
29
|
+
cluster: z.ZodEnum<{
|
|
30
|
+
devnet: "devnet";
|
|
31
|
+
"mainnet-beta": "mainnet-beta";
|
|
32
|
+
}>;
|
|
33
|
+
launchpadConfig: z.ZodString;
|
|
34
|
+
launchpadCoinConfig: z.ZodString;
|
|
35
|
+
launchpadCoinMint: z.ZodString;
|
|
36
|
+
ownerWallet: z.ZodString;
|
|
37
|
+
poolCreationFeeSol: z.ZodOptional<z.ZodNumber>;
|
|
38
|
+
}, z.core.$strip>>;
|
|
39
|
+
theme: z.ZodObject<{
|
|
40
|
+
primaryColor: z.ZodString;
|
|
41
|
+
accentColor: z.ZodString;
|
|
42
|
+
darkMode: z.ZodBoolean;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
content: z.ZodObject<{
|
|
45
|
+
tagline: z.ZodString;
|
|
46
|
+
about: z.ZodString;
|
|
47
|
+
}, z.core.$strip>;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
export type ForgeSiteConfig = z.infer<typeof ForgeSiteConfig>;
|
|
50
|
+
/** Read-only view of forge.config.json exposed to the template UI (docs/frontend/CONTRACT.md). */
|
|
51
|
+
export interface SiteConfig {
|
|
52
|
+
name: string;
|
|
53
|
+
slug: string;
|
|
54
|
+
theme: {
|
|
55
|
+
primaryColor: string;
|
|
56
|
+
accentColor: string;
|
|
57
|
+
darkMode: boolean;
|
|
58
|
+
};
|
|
59
|
+
content: {
|
|
60
|
+
tagline: string;
|
|
61
|
+
about: string;
|
|
62
|
+
};
|
|
63
|
+
mode: SiteMode;
|
|
64
|
+
}
|
|
65
|
+
/** Pure projection of a parsed forge.config.json to the UI-facing SiteConfig. */
|
|
66
|
+
export declare function toSiteConfig(config: ForgeSiteConfig): SiteConfig;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { Slug, SolanaAddress, isValidPoolCreationFeeSol } from './spec.js';
|
|
3
|
+
export const SolanaCluster = z.enum(['devnet', 'mainnet-beta']);
|
|
4
|
+
/** `live`, `sleeping` (dormant) or `disabled` (cut by FORGE). Written by the builder only. */
|
|
5
|
+
export const SiteMode = z.enum(['live', 'sleeping', 'disabled']);
|
|
6
|
+
const HexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/);
|
|
7
|
+
/**
|
|
8
|
+
* `forge.config.json`, generated by the builder in each client repo and read by the client site
|
|
9
|
+
* (docs/INTERFACES.md §3). The builder agent may change `theme` and `content`, never `onchain`
|
|
10
|
+
* nor `mode`. FORGE addresses (multisig, referrals, platform fee wallet) are NOT in this file.
|
|
11
|
+
*/
|
|
12
|
+
export const ForgeSiteConfig = z.object({
|
|
13
|
+
version: z.literal(1),
|
|
14
|
+
name: z.string().min(2).max(32),
|
|
15
|
+
slug: Slug,
|
|
16
|
+
mode: SiteMode,
|
|
17
|
+
/** Absent until the on-chain setup is done. */
|
|
18
|
+
onchain: z
|
|
19
|
+
.object({
|
|
20
|
+
cluster: SolanaCluster,
|
|
21
|
+
launchpadConfig: SolanaAddress,
|
|
22
|
+
launchpadCoinConfig: SolanaAddress,
|
|
23
|
+
launchpadCoinMint: SolanaAddress,
|
|
24
|
+
ownerWallet: SolanaAddress,
|
|
25
|
+
/** Coin creation fee charged by this launchpad, shown to coin creators before signing. */
|
|
26
|
+
poolCreationFeeSol: z.number().refine(isValidPoolCreationFeeSol).optional(),
|
|
27
|
+
})
|
|
28
|
+
.optional(),
|
|
29
|
+
theme: z.object({
|
|
30
|
+
primaryColor: HexColor,
|
|
31
|
+
accentColor: HexColor,
|
|
32
|
+
darkMode: z.boolean(),
|
|
33
|
+
}),
|
|
34
|
+
content: z.object({
|
|
35
|
+
tagline: z.string().max(120),
|
|
36
|
+
about: z.string(),
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
39
|
+
/** Pure projection of a parsed forge.config.json to the UI-facing SiteConfig. */
|
|
40
|
+
export function toSiteConfig(config) {
|
|
41
|
+
return {
|
|
42
|
+
name: config.name,
|
|
43
|
+
slug: config.slug,
|
|
44
|
+
theme: { ...config.theme },
|
|
45
|
+
content: { ...config.content },
|
|
46
|
+
mode: config.mode,
|
|
47
|
+
};
|
|
48
|
+
}
|