@chest-gate/cli 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.
Files changed (51) hide show
  1. package/README.md +55 -0
  2. package/dist/chest_splitter_idl.json +482 -0
  3. package/dist/commands/app.d.ts +3 -0
  4. package/dist/commands/app.d.ts.map +1 -0
  5. package/dist/commands/app.js +42 -0
  6. package/dist/commands/app.js.map +1 -0
  7. package/dist/commands/deploy.d.ts +3 -0
  8. package/dist/commands/deploy.d.ts.map +1 -0
  9. package/dist/commands/deploy.js +285 -0
  10. package/dist/commands/deploy.js.map +1 -0
  11. package/dist/commands/gate.d.ts +3 -0
  12. package/dist/commands/gate.d.ts.map +1 -0
  13. package/dist/commands/gate.js +114 -0
  14. package/dist/commands/gate.js.map +1 -0
  15. package/dist/commands/init.d.ts +3 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +153 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/keypair.d.ts +3 -0
  20. package/dist/commands/keypair.d.ts.map +1 -0
  21. package/dist/commands/keypair.js +38 -0
  22. package/dist/commands/keypair.js.map +1 -0
  23. package/dist/commands/split.d.ts +3 -0
  24. package/dist/commands/split.d.ts.map +1 -0
  25. package/dist/commands/split.js +98 -0
  26. package/dist/commands/split.js.map +1 -0
  27. package/dist/commands/status.d.ts +3 -0
  28. package/dist/commands/status.d.ts.map +1 -0
  29. package/dist/commands/status.js +37 -0
  30. package/dist/commands/status.js.map +1 -0
  31. package/dist/config.d.ts +43 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +114 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +23 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/keypair.d.ts +9 -0
  40. package/dist/keypair.d.ts.map +1 -0
  41. package/dist/keypair.js +50 -0
  42. package/dist/keypair.js.map +1 -0
  43. package/dist/manifest.d.ts +69 -0
  44. package/dist/manifest.d.ts.map +1 -0
  45. package/dist/manifest.js +171 -0
  46. package/dist/manifest.js.map +1 -0
  47. package/dist/splitter-init.d.ts +32 -0
  48. package/dist/splitter-init.d.ts.map +1 -0
  49. package/dist/splitter-init.js +99 -0
  50. package/dist/splitter-init.js.map +1 -0
  51. package/package.json +58 -0
@@ -0,0 +1,38 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import { ensureKeypair } from "../keypair.js";
4
+ export const keypairCommand = new Command("keypair")
5
+ .description("Show or generate the fee-payer wallet")
6
+ .option("--show-mnemonic", "Display the seed phrase (careful, don't share this)")
7
+ .action(async (opts) => {
8
+ console.log(chalk.bold("\n ⚡ Chest Wallet\n"));
9
+ const feePayer = await ensureKeypair();
10
+ if (feePayer.created) {
11
+ console.log(chalk.bgYellow.black(" ⚠ NEW WALLET CREATED, BACK IT UP "));
12
+ console.log();
13
+ console.log(chalk.yellow(" A new Solana wallet was generated. If you lose the file or seed,"));
14
+ console.log(chalk.yellow(" you lose access to deploys under this wallet and any SOL it holds."));
15
+ console.log();
16
+ }
17
+ console.log(chalk.gray(" Solana address: ") + chalk.cyan(feePayer.address));
18
+ console.log(chalk.gray(" Wallet file: ") + chalk.white(feePayer.path));
19
+ console.log();
20
+ if (!opts.showMnemonic) {
21
+ console.log(chalk.yellow(" ⚠ Back up your seed phrase. Run with --show-mnemonic to view it."));
22
+ console.log(chalk.gray(" Anyone with this seed phrase controls this wallet."));
23
+ console.log();
24
+ }
25
+ if (opts.showMnemonic) {
26
+ console.log(chalk.yellow(" Seed phrase (keep this secret):"));
27
+ console.log(chalk.white(` ${feePayer.mnemonic}`));
28
+ console.log();
29
+ console.log(chalk.gray(" This seed phrase can derive wallets for Solana, Ethereum, and other chains."));
30
+ console.log(chalk.gray(" Derivation path (Solana): m/44'/501'/0'/0'"));
31
+ }
32
+ console.log();
33
+ console.log(chalk.yellow(" Fund this address with SOL for transaction fees."));
34
+ console.log(chalk.yellow(" On devnet: https://faucet.solana.com"));
35
+ console.log(chalk.yellow(" On mainnet: send ~0.01 SOL"));
36
+ console.log();
37
+ });
38
+ //# sourceMappingURL=keypair.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keypair.js","sourceRoot":"","sources":["../../src/commands/keypair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,uCAAuC,CAAC;KACpD,MAAM,CAAC,iBAAiB,EAAE,qDAAqD,CAAC;KAChF,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAEhD,MAAM,QAAQ,GAAG,MAAM,aAAa,EAAE,CAAC;IAEvC,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;QAC3E,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC,CAAC;QAChG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sEAAsE,CAAC,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,qEAAqE,CAAC,CAAC,CAAC;QACjG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC,CAAC;QACnF,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC,CAAC;QACzG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,oDAAoD,CAAC,CACnE,CAAC;IACF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,wCAAwC,CAAC,CACvD,CAAC;IACF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,8BAA8B,CAAC,CAC7C,CAAC;IACF,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const splitCommand: Command;
3
+ //# sourceMappingURL=split.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split.d.ts","sourceRoot":"","sources":["../../src/commands/split.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8HpC,eAAO,MAAM,YAAY,SAGQ,CAAC"}
@@ -0,0 +1,98 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import pkg from "@coral-xyz/anchor";
4
+ const { AnchorProvider, Program, Wallet, setProvider } = pkg;
5
+ import { Connection, Keypair, PublicKey } from "@solana/web3.js";
6
+ import { ensureKeypair } from "../keypair.js";
7
+ import { computeSlugHash, RPC_URLS } from "../splitter-init.js";
8
+ import idl from "../chest_splitter_idl.json" with { type: "json" };
9
+ const PROGRAM_ID = new PublicKey("9a6zrqau5xVEdxNqBUfL2G18WuryQbWeJScPAUHZvmmX");
10
+ const MAX_REFERRER_BPS = 9850;
11
+ function deriveSplitConfigPda(authority, slug) {
12
+ const slugHash = computeSlugHash(slug);
13
+ const [pda] = PublicKey.findProgramAddressSync([Buffer.from("split"), authority.toBuffer(), slugHash], PROGRAM_ID);
14
+ return pda;
15
+ }
16
+ function rpcUrlFor(network) {
17
+ return (RPC_URLS[network] ??
18
+ RPC_URLS[network.replace(/^solana-/, "")] ??
19
+ RPC_URLS["solana-devnet"]);
20
+ }
21
+ async function loadProgram(network, keypair) {
22
+ const connection = new Connection(rpcUrlFor(network), "confirmed");
23
+ const wallet = new Wallet(Keypair.fromSecretKey(keypair));
24
+ const provider = new AnchorProvider(connection, wallet, { commitment: "confirmed" });
25
+ setProvider(provider);
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ return { program: new Program(idl, provider), connection, wallet };
28
+ }
29
+ async function resolveSlug(cliSlug) {
30
+ if (cliSlug)
31
+ return cliSlug;
32
+ throw new Error("Pass --slug <slug> (the deployed slug, e.g. 'my-api')");
33
+ }
34
+ const splitInfoCommand = new Command("info")
35
+ .description("Read the on-chain SplitConfig PDA for this deploy")
36
+ .option("--slug <slug>", "deployment slug (required)")
37
+ .option("--network <net>", "solana network (devnet|mainnet)", "solana-devnet")
38
+ .action(async (opts) => {
39
+ const feePayer = await ensureKeypair();
40
+ const slug = await resolveSlug(opts.slug);
41
+ const { program } = await loadProgram(opts.network, feePayer.keypair);
42
+ const authority = new PublicKey(feePayer.address);
43
+ const pda = deriveSplitConfigPda(authority, slug);
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ const cfg = (await program.account.splitConfig.fetch(pda));
46
+ console.log(chalk.bold("\n ⚡ Split Config\n"));
47
+ console.log(chalk.gray(" PDA: ") + chalk.cyan(pda.toBase58()));
48
+ console.log(chalk.gray(" Authority: ") + chalk.white(cfg.authority.toBase58()));
49
+ console.log(chalk.gray(" Merchant wallet: ") + chalk.white(cfg.merchantWallet.toBase58()));
50
+ console.log(chalk.gray(" Protocol wallet: ") + chalk.white(cfg.protocolWallet.toBase58()));
51
+ console.log(chalk.gray(" Referrer bps: ") +
52
+ chalk.green(`${cfg.referrerBps} (${(cfg.referrerBps / 100).toFixed(2)}%)`));
53
+ console.log(chalk.gray(" Protocol bps: ") +
54
+ chalk.white(`${cfg.protocolBps} (${(cfg.protocolBps / 100).toFixed(2)}%)`));
55
+ console.log();
56
+ });
57
+ const splitUpdateCommand = new Command("update")
58
+ .description("Update the referrer commission % for this deploy")
59
+ .requiredOption("--referrer <pct>", "new referrer commission in % (0–98.5)")
60
+ .option("--slug <slug>", "deployment slug (required)")
61
+ .option("--network <net>", "solana network (devnet|mainnet)", "solana-devnet")
62
+ .action(async (opts) => {
63
+ const pct = parseFloat(opts.referrer);
64
+ if (!Number.isFinite(pct) || pct < 0 || pct > 98.5) {
65
+ console.error(chalk.red(`Referrer % out of range: ${opts.referrer} (must be 0–98.5)`));
66
+ process.exit(1);
67
+ }
68
+ const newBps = Math.round(pct * 100);
69
+ if (newBps > MAX_REFERRER_BPS) {
70
+ console.error(chalk.red(`Referrer bps out of range: ${newBps} (max ${MAX_REFERRER_BPS})`));
71
+ process.exit(1);
72
+ }
73
+ const feePayer = await ensureKeypair();
74
+ const slug = await resolveSlug(opts.slug);
75
+ const { program, connection } = await loadProgram(opts.network, feePayer.keypair);
76
+ const authority = Keypair.fromSecretKey(feePayer.keypair);
77
+ const pda = deriveSplitConfigPda(authority.publicKey, slug);
78
+ const existing = await connection.getAccountInfo(pda);
79
+ if (!existing) {
80
+ console.error(chalk.red(`No split config at ${pda.toBase58()}. Run 'chest-gate deploy' first.`));
81
+ process.exit(1);
82
+ }
83
+ console.log(chalk.gray(` Updating referrer bps → ${newBps} (${pct.toFixed(2)}%) for slug '${slug}'...`));
84
+ const sig = await program.methods
85
+ .updateReferrerBps(newBps)
86
+ .accounts({
87
+ authority: authority.publicKey,
88
+ splitConfig: pda,
89
+ })
90
+ .rpc();
91
+ console.log(chalk.green(`\n ✓ Updated. Tx: ${sig}`));
92
+ console.log(chalk.gray(` PDA: ${pda.toBase58()}\n`));
93
+ });
94
+ export const splitCommand = new Command("split")
95
+ .description("Manage the on-chain revenue split for a deploy")
96
+ .addCommand(splitInfoCommand)
97
+ .addCommand(splitUpdateCommand);
98
+ //# sourceMappingURL=split.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split.js","sourceRoot":"","sources":["../../src/commands/split.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const statusCommand: Command;
3
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,aAAa,SAsCtB,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import { TransactionStore } from "@chest-gate/proxy";
4
+ export const statusCommand = new Command("status")
5
+ .description("Show proxy status and revenue summary")
6
+ .action(async () => {
7
+ console.log(chalk.bold("\n ⚡ Chest Status\n"));
8
+ let store;
9
+ try {
10
+ store = new TransactionStore();
11
+ }
12
+ catch {
13
+ console.log(chalk.gray(" No transaction data found. Run `chest-gate gate` first.\n"));
14
+ return;
15
+ }
16
+ const stats = store.getStats();
17
+ store.close();
18
+ console.log(chalk.white(" Revenue"));
19
+ console.log(chalk.gray(" ─────────────────────────────────────────"));
20
+ console.log(chalk.gray(" Total revenue: ") + chalk.green(`$${stats.totalRevenue.toFixed(6)} USDC`));
21
+ console.log(chalk.gray(" Settled payments: ") + chalk.white(String(stats.settledTransactions)));
22
+ console.log(chalk.gray(" Total requests: ") + chalk.white(String(stats.totalTransactions)));
23
+ console.log(chalk.gray(" Unique payers: ") + chalk.white(String(stats.uniquePayers)));
24
+ console.log();
25
+ if (stats.topRoutes.length > 0) {
26
+ console.log(chalk.white(" Top Routes"));
27
+ console.log(chalk.gray(" ─────────────────────────────────────────"));
28
+ for (const route of stats.topRoutes) {
29
+ console.log(chalk.gray(" ") +
30
+ chalk.white(route.route.padEnd(30)) +
31
+ chalk.green(`$${route.revenue.toFixed(4)}`) +
32
+ chalk.gray(` (${route.count} payments)`));
33
+ }
34
+ }
35
+ console.log();
36
+ });
37
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,uCAAuC,CAAC;KACpD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAEhD,IAAI,KAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,gBAAgB,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC,CAAC;QACvF,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC/B,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1G,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IACnG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IACjG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5F,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,CAAC;QACvE,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;gBAChB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACnC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3C,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,KAAK,YAAY,CAAC,CACzC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,43 @@
1
+ export interface RouteConfig {
2
+ path: string;
3
+ price: number;
4
+ }
5
+ export interface SplitConfig {
6
+ referrerBps: number;
7
+ protocolBps: number;
8
+ splitConfigPda?: string;
9
+ protocolWallet?: string;
10
+ merchantTokenAccount?: string;
11
+ protocolTokenAccount?: string;
12
+ /** When true, X-Referrer-Wallet is accepted without a signature. Default: false. */
13
+ allowUnsignedReferrers?: boolean;
14
+ }
15
+ export interface ChestConfig {
16
+ name: string;
17
+ upstream: string;
18
+ wallet: string;
19
+ network: string;
20
+ port: number;
21
+ freebie: number;
22
+ defaultPrice: number;
23
+ /** Session duration in seconds, paying agent gets free reuse for this long. */
24
+ session: number;
25
+ routes: RouteConfig[];
26
+ split?: SplitConfig;
27
+ }
28
+ interface GateOptions {
29
+ price?: string;
30
+ /** Either form is accepted, commander camelCases --payout-wallet to payoutWallet. */
31
+ wallet?: string;
32
+ payoutWallet?: string;
33
+ wrap?: string;
34
+ port?: string;
35
+ freebie?: string;
36
+ network?: string;
37
+ session?: string;
38
+ config?: string;
39
+ }
40
+ export declare function loadConfig(opts: GateOptions): Promise<ChestConfig>;
41
+ export declare function normalizeNetwork(network: string): string;
42
+ export {};
43
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oFAAoF;IACpF,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CA4CxE;AA6CD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMxD"}
package/dist/config.js ADDED
@@ -0,0 +1,114 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { parse as parseYaml } from "yaml";
4
+ export async function loadConfig(opts) {
5
+ const configPath = opts.config || "chest.config.yaml";
6
+ // Try loading from config file
7
+ if (existsSync(configPath)) {
8
+ const raw = await readFile(configPath, "utf-8");
9
+ const yaml = parseYaml(raw);
10
+ // CLI flag (--payout-wallet) wins over YAML. The YAML field is `payoutWallet`.
11
+ if (yaml.wallet !== undefined) {
12
+ throw new Error(`${configPath}: \`wallet:\` is not a valid field. Rename it to \`payoutWallet:\`.`);
13
+ }
14
+ const payoutFlag = opts.payoutWallet ?? opts.wallet;
15
+ return {
16
+ name: yaml.name || "Chest Gate",
17
+ upstream: normalizeUpstream(opts.wrap || yaml.upstream || ""),
18
+ wallet: payoutFlag || yaml.payoutWallet || "",
19
+ network: normalizeNetwork(opts.network || yaml.network || "devnet"),
20
+ port: parseInt(opts.port || String(yaml.port || 4020), 10),
21
+ freebie: parseInt(opts.freebie ?? String(yaml.freebie ?? 0), 10),
22
+ defaultPrice: parsePrice(opts.price || yaml.price || "$0.01"),
23
+ session: parseSession(opts.session ?? yaml.session),
24
+ routes: parseRoutes(yaml.routes),
25
+ split: parseSplit(yaml.split),
26
+ };
27
+ }
28
+ // Fall back to CLI flags only
29
+ return {
30
+ name: "Chest Gate",
31
+ upstream: normalizeUpstream(opts.wrap || ""),
32
+ wallet: opts.payoutWallet ?? opts.wallet ?? "",
33
+ network: normalizeNetwork(opts.network || "devnet"),
34
+ port: parseInt(opts.port ?? "4020", 10),
35
+ freebie: parseInt(opts.freebie ?? "0", 10),
36
+ defaultPrice: parsePrice(opts.price || "$0.01"),
37
+ session: parseSession(opts.session),
38
+ routes: [],
39
+ split: undefined,
40
+ };
41
+ }
42
+ /**
43
+ * Accepts numbers, numeric strings, or suffixed strings ("5m", "1h", "30s").
44
+ * Returns seconds. Defaults to 300 (5 min) when input is missing/invalid.
45
+ */
46
+ function parseSession(input) {
47
+ if (input === undefined || input === null || input === "")
48
+ return 300;
49
+ if (typeof input === "number")
50
+ return Number.isFinite(input) && input >= 0 ? Math.round(input) : 300;
51
+ const s = String(input).trim().toLowerCase();
52
+ const match = s.match(/^(\d+(?:\.\d+)?)\s*(s|sec|secs|m|min|mins|h|hr|hrs)?$/);
53
+ if (!match)
54
+ return 300;
55
+ const n = parseFloat(match[1]);
56
+ if (!Number.isFinite(n) || n < 0)
57
+ return 300;
58
+ const unit = match[2] ?? "s";
59
+ if (unit.startsWith("h"))
60
+ return Math.round(n * 3600);
61
+ if (unit.startsWith("m") && unit !== "ms")
62
+ return Math.round(n * 60);
63
+ return Math.round(n);
64
+ }
65
+ function parseRoutes(routes) {
66
+ if (!Array.isArray(routes))
67
+ return [];
68
+ return routes.map((r) => ({
69
+ path: String(r.path || r.route || ""),
70
+ price: parsePrice(String(r.price || "$0.01")),
71
+ }));
72
+ }
73
+ function parseSplit(split) {
74
+ if (!split || typeof split !== 'object')
75
+ return undefined;
76
+ const s = split;
77
+ const referrerPercent = parseFloat(String(s.referrer ?? 10));
78
+ const protocolPercent = parseFloat(String(s.protocol ?? 1.5));
79
+ return {
80
+ referrerBps: Math.round(referrerPercent * 100),
81
+ protocolBps: Math.round(protocolPercent * 100),
82
+ splitConfigPda: s.splitConfigPda ? String(s.splitConfigPda) : undefined,
83
+ protocolWallet: s.protocolWallet ? String(s.protocolWallet) : undefined,
84
+ merchantTokenAccount: s.merchantTokenAccount ? String(s.merchantTokenAccount) : undefined,
85
+ protocolTokenAccount: s.protocolTokenAccount ? String(s.protocolTokenAccount) : undefined,
86
+ allowUnsignedReferrers: s.allowUnsignedReferrers === true || s.allowUnsignedReferrers === "true",
87
+ };
88
+ }
89
+ export function normalizeNetwork(network) {
90
+ const n = network.toLowerCase().trim();
91
+ if (n === "devnet" || n === "dev")
92
+ return "solana-devnet";
93
+ if (n === "mainnet" || n === "main" || n === "mainnet-beta")
94
+ return "solana-mainnet";
95
+ if (n.startsWith("solana:") || n.startsWith("solana-"))
96
+ return n;
97
+ return "solana-devnet";
98
+ }
99
+ function parsePrice(price) {
100
+ const cleaned = String(price).replace(/^\$/, "");
101
+ const parsed = parseFloat(cleaned);
102
+ if (isNaN(parsed))
103
+ return 0.01;
104
+ return parsed;
105
+ }
106
+ function normalizeUpstream(url) {
107
+ if (!url)
108
+ return "";
109
+ if (!url.startsWith("http://") && !url.startsWith("https://")) {
110
+ return `http://${url}`;
111
+ }
112
+ return url;
113
+ }
114
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { gateCommand } from "./commands/gate.js";
4
+ import { deployCommand } from "./commands/deploy.js";
5
+ import { initCommand } from "./commands/init.js";
6
+ import { statusCommand } from "./commands/status.js";
7
+ import { keypairCommand } from "./commands/keypair.js";
8
+ import { splitCommand } from "./commands/split.js";
9
+ import { appCommand } from "./commands/app.js";
10
+ const program = new Command();
11
+ program
12
+ .name("chest-gate")
13
+ .description("One command to monetise any API with x402 on Solana")
14
+ .version("0.1.0");
15
+ program.addCommand(gateCommand);
16
+ program.addCommand(deployCommand);
17
+ program.addCommand(initCommand);
18
+ program.addCommand(statusCommand);
19
+ program.addCommand(keypairCommand);
20
+ program.addCommand(splitCommand);
21
+ program.addCommand(appCommand);
22
+ program.parse();
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,qDAAqD,CAAC;KAClE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAE/B,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface FeePayerInfo {
2
+ address: string;
3
+ keypair: Uint8Array;
4
+ mnemonic: string;
5
+ path: string;
6
+ created: boolean;
7
+ }
8
+ export declare function ensureKeypair(): Promise<FeePayerInfo>;
9
+ //# sourceMappingURL=keypair.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keypair.d.ts","sourceRoot":"","sources":["../src/keypair.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AASD,wBAAsB,aAAa,IAAI,OAAO,CAAC,YAAY,CAAC,CA4C3D"}
@@ -0,0 +1,50 @@
1
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ import * as bip39 from "bip39";
6
+ import { derivePath } from "ed25519-hd-key";
7
+ import { Keypair } from "@solana/web3.js";
8
+ const CHEST_DIR = join(homedir(), ".chest");
9
+ const WALLET_PATH = join(CHEST_DIR, "wallet.json");
10
+ // Solana BIP-44 derivation path
11
+ const SOLANA_DERIVATION_PATH = "m/44'/501'/0'/0'";
12
+ export async function ensureKeypair() {
13
+ // Check for existing wallet
14
+ if (existsSync(WALLET_PATH)) {
15
+ const raw = await readFile(WALLET_PATH, "utf-8");
16
+ const wallet = JSON.parse(raw);
17
+ const secretKey = new Uint8Array(wallet.solanaKeypair);
18
+ const kp = Keypair.fromSecretKey(secretKey);
19
+ return {
20
+ address: kp.publicKey.toBase58(),
21
+ keypair: secretKey,
22
+ mnemonic: wallet.mnemonic,
23
+ path: WALLET_PATH,
24
+ created: false,
25
+ };
26
+ }
27
+ // Generate new seed phrase
28
+ const mnemonic = bip39.generateMnemonic();
29
+ const seed = await bip39.mnemonicToSeed(mnemonic);
30
+ // Derive Solana keypair from seed
31
+ const derived = derivePath(SOLANA_DERIVATION_PATH, seed.toString("hex"));
32
+ const kp = Keypair.fromSeed(derived.key);
33
+ // Save wallet file
34
+ await mkdir(CHEST_DIR, { recursive: true });
35
+ const walletFile = {
36
+ mnemonic,
37
+ derivationPath: SOLANA_DERIVATION_PATH,
38
+ solanaAddress: kp.publicKey.toBase58(),
39
+ solanaKeypair: Array.from(kp.secretKey),
40
+ };
41
+ await writeFile(WALLET_PATH, JSON.stringify(walletFile, null, 2));
42
+ return {
43
+ address: kp.publicKey.toBase58(),
44
+ keypair: kp.secretKey,
45
+ mnemonic,
46
+ path: WALLET_PATH,
47
+ created: true,
48
+ };
49
+ }
50
+ //# sourceMappingURL=keypair.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keypair.js","sourceRoot":"","sources":["../src/keypair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AAEnD,gCAAgC;AAChC,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AAiBlD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,4BAA4B;IAC5B,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,MAAM,GAAe,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAE5C,OAAO;YACL,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE;YAChC,OAAO,EAAE,SAAS;YAClB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,gBAAgB,EAAE,CAAC;IAC1C,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAElD,kCAAkC;IAClC,MAAM,OAAO,GAAG,UAAU,CAAC,sBAAsB,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACzE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAEzC,mBAAmB;IACnB,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,MAAM,UAAU,GAAe;QAC7B,QAAQ;QACR,cAAc,EAAE,sBAAsB;QACtC,aAAa,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE;QACtC,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC;KACxC,CAAC;IAEF,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAElE,OAAO;QACL,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE;QAChC,OAAO,EAAE,EAAE,CAAC,SAAS;QACrB,QAAQ;QACR,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * app.md manifest, the authoring-side artifact for an App (an install-ready
3
+ * agent capability that wraps one or more paid Gates).
4
+ *
5
+ * Authors keep an `app.md` in their repo with YAML frontmatter declaring the
6
+ * App's identity, the upstream Gates it calls, and human-readable metadata.
7
+ * The markdown body becomes the listing description on chest.sh.
8
+ *
9
+ * The payout wallet is **deliberately not a manifest field**, it is resolved
10
+ * from the on-chain author record (npm/crates.io/Hugging Face pattern).
11
+ * Wallet rotation, multi-sig payouts, and impersonation prevention all live
12
+ * on the author record, not in every manifest.
13
+ *
14
+ * Hand-rolled validator (no zod dep). Returns either a typed manifest or
15
+ * a structured list of errors with field paths so the CLI can render them
16
+ * with line/column hints.
17
+ */
18
+ export declare const CAPABILITY_TAGS: readonly ["INFERENCE", "SEARCH", "DATA", "MEDIA", "INFRA"];
19
+ export type CapabilityTag = (typeof CAPABILITY_TAGS)[number];
20
+ export interface AppManifest {
21
+ /** kebab-case slug, [a-z0-9-]+, max 64 chars. Identifier within the author's namespace. */
22
+ name: string;
23
+ /** Author handle, prefixed with @, e.g. "@smd00". Resolves to on-chain author record. */
24
+ author: string;
25
+ /** Valid semver, e.g. "0.1.0". */
26
+ version: string;
27
+ /** 1–280 chars. Used as the registry listing tagline. */
28
+ description: string;
29
+ /** ≥1 capability tags from the enum. */
30
+ capabilityTags: CapabilityTag[];
31
+ /** Optional @author/name slugs. Each must match the same shape as App slugs. */
32
+ upstreamGates?: string[];
33
+ /** Optional https URL. */
34
+ homepage?: string;
35
+ /** Optional https URL. */
36
+ repository?: string;
37
+ /** Optional SPDX identifier. Free-form string for v1. */
38
+ license?: string;
39
+ /** Markdown body (everything below the frontmatter `---` delimiter). */
40
+ body: string;
41
+ }
42
+ export interface ManifestValidationError {
43
+ /** Dotted field path, e.g. "name", "capabilityTags[2]". */
44
+ path: string;
45
+ message: string;
46
+ }
47
+ /**
48
+ * Parse and validate an app.md manifest from disk. Returns either the
49
+ * typed manifest (`{ ok: true, manifest }`) or a list of errors.
50
+ */
51
+ export declare function loadManifest(path: string): Promise<{
52
+ ok: true;
53
+ manifest: AppManifest;
54
+ } | {
55
+ ok: false;
56
+ errors: ManifestValidationError[];
57
+ }>;
58
+ /**
59
+ * Parse and validate a manifest from a raw string. Exposed separately so
60
+ * tests don't need a real file on disk.
61
+ */
62
+ export declare function parseManifest(raw: string): {
63
+ ok: true;
64
+ manifest: AppManifest;
65
+ } | {
66
+ ok: false;
67
+ errors: ManifestValidationError[];
68
+ };
69
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,eAAO,MAAM,eAAe,4DAMlB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAQD;;;GAGG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,GACX,OAAO,CACN;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,GACnC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,uBAAuB,EAAE,CAAA;CAAE,CACnD,CAYA;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,GAET;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,GACnC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,uBAAuB,EAAE,CAAA;CAAE,CAwHnD"}