@liens/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.
package/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # lien-cli
2
+
3
+ ```
4
+ npm i -g lien-cli
5
+ ```
6
+
7
+ ## Commands
8
+
9
+ ```
10
+ lien list print the standard hook library
11
+ lien create hook --name MyHook scaffold a hook source file
12
+ lien create composition prompt-driven composition.ts
13
+ lien simulate --pool SOL-USDC run the deterministic simulator
14
+ lien action write .github/workflows/lien-hook-ci.yml
15
+ lien deploy --cluster mainnet print an Anchor deploy plan (does not broadcast)
16
+ ```
17
+
18
+ `lien deploy` is plan-only by design — actually running `anchor deploy` requires the operator to confirm the keypair pubkey and balance.
package/dist/bin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
package/dist/bin.js ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { createCommand } from "./commands/create.js";
4
+ import { simulateCommand } from "./commands/simulate.js";
5
+ import { deployCommand } from "./commands/deploy.js";
6
+ import { listCommand } from "./commands/list.js";
7
+ import { actionCommand } from "./commands/action.js";
8
+ const program = new Command();
9
+ program
10
+ .name("lien")
11
+ .description("Lien — tie your loans. Create, simulate, and deploy Solana lending hooks.")
12
+ .version("0.1.0");
13
+ program.addCommand(createCommand());
14
+ program.addCommand(simulateCommand());
15
+ program.addCommand(deployCommand());
16
+ program.addCommand(listCommand());
17
+ program.addCommand(actionCommand());
18
+ program.parseAsync(process.argv).catch((err) => {
19
+ console.error(err instanceof Error ? err.message : err);
20
+ process.exitCode = 1;
21
+ });
22
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CACV,2EAA2E,CAC5E;KACA,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;AACtC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;AAEpC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function actionCommand(): Command;
3
+ //# sourceMappingURL=action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../src/commands/action.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,wBAAgB,aAAa,IAAI,OAAO,CASvC"}
@@ -0,0 +1,29 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { Command } from "commander";
4
+ import kleur from "kleur";
5
+ const WORKFLOW = `name: lien-hook-ci
6
+ on: [push, pull_request]
7
+ jobs:
8
+ simulate:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-node@v4
13
+ with:
14
+ node-version: "20"
15
+ - run: npm install -g lien-cli
16
+ - run: lien list
17
+ - run: lien simulate --steps 120 --pool $\\{{ vars.LIEN_POOL || 'SOL-USDC' \\}}
18
+ `;
19
+ export function actionCommand() {
20
+ return new Command("action")
21
+ .description("Generate a GitHub Actions workflow that runs `lien simulate` on every push.")
22
+ .action(async () => {
23
+ const dir = path.resolve(process.cwd(), ".github", "workflows");
24
+ await mkdir(dir, { recursive: true });
25
+ await writeFile(path.join(dir, "lien-hook-ci.yml"), WORKFLOW.replace(/\\/g, ""));
26
+ console.log(kleur.green(`Wrote ${path.join(dir, "lien-hook-ci.yml")}`));
27
+ });
28
+ }
29
+ //# sourceMappingURL=action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action.js","sourceRoot":"","sources":["../../src/commands/action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,QAAQ,GAAG;;;;;;;;;;;;;CAahB,CAAC;AAEF,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;SACzB,WAAW,CAAC,6EAA6E,CAAC;SAC1F,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QAChE,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;QACjF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createCommand(): Command;
3
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBpC,wBAAgB,aAAa,IAAI,OAAO,CAuDvC"}
@@ -0,0 +1,96 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { Command } from "commander";
4
+ import kleur from "kleur";
5
+ import prompts from "prompts";
6
+ import { STANDARD_HOOK_NAMES } from "@liens/sdk";
7
+ const TEMPLATE = (name, lifecycle) => `import { Hook, HookContext, HookDecision, flagsFrom } from "@liens/sdk";
8
+
9
+ export class ${name} implements Hook {
10
+ readonly meta = {
11
+ name: "${name}",
12
+ version: "0.1.0",
13
+ author: "<your handle>",
14
+ flags: flagsFrom(["${lifecycle}"]),
15
+ description: "TODO: describe what this hook does",
16
+ };
17
+
18
+ evaluate(ctx: HookContext): HookDecision {
19
+ void ctx;
20
+ return HookDecision.Accept;
21
+ }
22
+ }
23
+ `;
24
+ export function createCommand() {
25
+ return new Command("create")
26
+ .description("Scaffold a new hook in a folder.")
27
+ .argument("[kind]", "hook | composition")
28
+ .option("-n, --name <name>", "hook name (PascalCase)")
29
+ .option("-l, --lifecycle <lifecycle>", "lifecycle flag", "BeforeBorrow")
30
+ .action(async (kind, opts) => {
31
+ const target = kind ?? (await prompts({
32
+ type: "select",
33
+ name: "v",
34
+ message: "What do you want to create?",
35
+ choices: [
36
+ { title: "hook (single hook program)", value: "hook" },
37
+ { title: "composition (TS file that bundles existing hooks)", value: "composition" },
38
+ ],
39
+ })).v;
40
+ if (target === "hook") {
41
+ const name = opts.name ?? (await prompts({
42
+ type: "text",
43
+ name: "v",
44
+ message: "Hook name (PascalCase)",
45
+ })).v;
46
+ const lifecycle = opts.lifecycle;
47
+ if (!name)
48
+ throw new Error("Hook name required");
49
+ const dir = path.resolve(process.cwd(), name);
50
+ await mkdir(dir, { recursive: true });
51
+ await writeFile(path.join(dir, `${name}.ts`), TEMPLATE(name, lifecycle));
52
+ console.log(kleur.green(`Created ${path.join(dir, `${name}.ts`)}`));
53
+ console.log(`Next: ${kleur.yellow(`lien simulate --hook ${name}`)}`);
54
+ return;
55
+ }
56
+ if (target === "composition") {
57
+ const hooks = await prompts({
58
+ type: "multiselect",
59
+ name: "v",
60
+ message: "Pick hooks to include",
61
+ choices: STANDARD_HOOK_NAMES.map((n) => ({ title: n, value: n, selected: false })),
62
+ });
63
+ const out = `import {
64
+ Composition,
65
+ ${hooks.v.map((h) => h[0]?.toLowerCase() + h.slice(1)).join(",\n ")}
66
+ } from "@liens/sdk";
67
+
68
+ export const composition = new Composition()
69
+ ${hooks.v.map((h, i) => `.add(${h[0]?.toLowerCase() + h.slice(1)}({ programId: "<replace>", priority: ${i * 10}, ${defaultArgs(h)} }))`).join("\n ")};
70
+ `;
71
+ await writeFile(path.resolve(process.cwd(), "composition.ts"), out);
72
+ console.log(kleur.green("Created composition.ts"));
73
+ return;
74
+ }
75
+ throw new Error(`Unknown create target: ${target}`);
76
+ });
77
+ }
78
+ function defaultArgs(name) {
79
+ switch (name) {
80
+ case "DynamicLTV":
81
+ return "baseLtvBps: 7500, sensitivity: 50, volFloorBps: 1000, minLtvBps: 2500";
82
+ case "TimeTriggerLiq":
83
+ return "allowedWindows: [{ startSec: 36000, endSec: 64800 }], maxOracleAgeSlots: 500, delaySlots: 300";
84
+ case "WhitelistBorrow":
85
+ return "allowedOwners: []";
86
+ case "AntiMEVLiq":
87
+ return "minDelaySlots: 3, keepers: []";
88
+ case "AutoHedge":
89
+ return "triggerPriceE8: 8000000000n, hedgeRatioBps: 5000, marketPubkey: \"<drift-market>\"";
90
+ case "ReputationRate":
91
+ return "baseRateBps: 1200, maxDiscountBps: 600, providerProgram: \"<provider>\"";
92
+ default:
93
+ return "";
94
+ }
95
+ }
96
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function deployCommand(): Command;
3
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,aAAa,IAAI,OAAO,CAqBvC"}
@@ -0,0 +1,23 @@
1
+ import { Command } from "commander";
2
+ import kleur from "kleur";
3
+ export function deployCommand() {
4
+ return new Command("deploy")
5
+ .description("Print the exact Anchor command sequence used to deploy lien-hook-executor. " +
6
+ "This command never signs on its own — you run `anchor deploy` yourself with your keypair.")
7
+ .option("--cluster <cluster>", "localnet | devnet | mainnet", "localnet")
8
+ .option("--keypair <path>", "path to deployer keypair", "~/.config/solana/id.json")
9
+ .action((opts) => {
10
+ console.log(kleur.bold().yellow("Lien deploy plan"));
11
+ console.log(kleur.gray(" (Run these yourself — `lien deploy` never broadcasts.)"));
12
+ console.log("");
13
+ console.log(` 1) anchor build`);
14
+ console.log(` 2) solana balance --keypair ${opts.keypair}`);
15
+ console.log(` 3) anchor deploy --provider.cluster ${opts.cluster} --provider.wallet ${opts.keypair}`);
16
+ console.log(` 4) solana program show <PROGRAM_ID> --url ${opts.cluster}`);
17
+ console.log("");
18
+ if (opts.cluster === "mainnet") {
19
+ console.log(kleur.red().bold("Mainnet deploy requires explicit operator approval. Confirm the keypair pubkey above before proceeding."));
20
+ }
21
+ });
22
+ }
23
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;SACzB,WAAW,CACV,6EAA6E;QAC3E,2FAA2F,CAC9F;SACA,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,UAAU,CAAC;SACxE,MAAM,CAAC,kBAAkB,EAAE,0BAA0B,EAAE,0BAA0B,CAAC;SAClF,MAAM,CAAC,CAAC,IAA0C,EAAE,EAAE;QACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC,CAAC;QACpF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,yCAAyC,IAAI,CAAC,OAAO,sBAAsB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACvG,OAAO,CAAC,GAAG,CAAC,+CAA+C,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,yGAAyG,CAAC,CAAC,CAAC;QAC3I,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function listCommand(): Command;
3
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,WAAW,IAAI,OAAO,CAOrC"}
@@ -0,0 +1,20 @@
1
+ import { Command } from "commander";
2
+ import kleur from "kleur";
3
+ import { STANDARD_HOOK_NAMES } from "@liens/sdk";
4
+ const DESCRIPTIONS = {
5
+ DynamicLTV: "Tightens the max LTV as realised volatility climbs.",
6
+ TimeTriggerLiq: "Limits liquidations to operator windows; delays under stale oracle.",
7
+ WhitelistBorrow: "Restricts borrowing to a registered allowlist.",
8
+ AntiMEVLiq: "Delays liquidation and (optionally) restricts to known keepers.",
9
+ AutoHedge: "Opens a Drift perp short when collateral price drops below a band.",
10
+ ReputationRate: "Discounts the borrow rate against on-chain repayment reputation.",
11
+ };
12
+ export function listCommand() {
13
+ return new Command("list").description("Print the standard hook library.").action(() => {
14
+ console.log(kleur.bold().yellow("Lien standard hook library"));
15
+ for (const name of STANDARD_HOOK_NAMES) {
16
+ console.log(` ${kleur.cyan(name.padEnd(18))} ${DESCRIPTIONS[name]}`);
17
+ }
18
+ });
19
+ }
20
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,YAAY,GAAyD;IACzE,UAAU,EAAE,qDAAqD;IACjE,cAAc,EAAE,qEAAqE;IACrF,eAAe,EAAE,gDAAgD;IACjE,UAAU,EAAE,iEAAiE;IAC7E,SAAS,EAAE,oEAAoE;IAC/E,cAAc,EAAE,kEAAkE;CACnF,CAAC;AAEF,MAAM,UAAU,WAAW;IACzB,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,kCAAkC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE;QACrF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC;QAC/D,KAAK,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function simulateCommand(): Command;
3
+ //# sourceMappingURL=simulate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simulate.d.ts","sourceRoot":"","sources":["../../src/commands/simulate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6CpC,wBAAgB,eAAe,IAAI,OAAO,CAmCzC"}
@@ -0,0 +1,69 @@
1
+ import { Command } from "commander";
2
+ import kleur from "kleur";
3
+ import { Composition, dynamicLtv, reputationRate, simulate, } from "@liens/sdk";
4
+ const KINDS = [
5
+ "beforeDeposit",
6
+ "afterDeposit",
7
+ "beforeBorrow",
8
+ "afterBorrow",
9
+ "beforeLiquidate",
10
+ "afterLiquidate",
11
+ ];
12
+ function fakeEvent(slot, kind) {
13
+ return {
14
+ kind,
15
+ adapter: "marginfi",
16
+ position: {
17
+ owner: "Br0wer11111111111111111111111111111111111111",
18
+ collateralMint: "So11111111111111111111111111111111111111112",
19
+ debtMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
20
+ collateralAmount: 1_000_000_000,
21
+ debtAmount: 500_000_000,
22
+ ltvBps: 5_000,
23
+ liquidationThresholdBps: 8_000,
24
+ },
25
+ market: {
26
+ slot,
27
+ timestamp: 40_000,
28
+ realisedVolBps: 1_200 + Math.floor(Math.sin(slot / 5) * 800),
29
+ utilisationBps: 6_000,
30
+ oraclePoints: [],
31
+ },
32
+ payload: [],
33
+ };
34
+ }
35
+ export function simulateCommand() {
36
+ return new Command("simulate")
37
+ .description("Run a default DynamicLTV+ReputationRate composition over a synthetic event stream.")
38
+ .option("--steps <n>", "number of synthetic events", "60")
39
+ .option("--pool <pool>", "label only — does not connect to mainnet", "SOL-USDC")
40
+ .action((opts) => {
41
+ const steps = Number.parseInt(opts.steps, 10) || 60;
42
+ const composition = new Composition()
43
+ .add(dynamicLtv({
44
+ programId: "HookDLTV1111111111111111111111111111111111",
45
+ priority: 10,
46
+ baseLtvBps: 7_500,
47
+ sensitivity: 50,
48
+ volFloorBps: 1_000,
49
+ minLtvBps: 2_500,
50
+ }))
51
+ .add(reputationRate({
52
+ programId: "HookRepRt1111111111111111111111111111111111",
53
+ priority: 20,
54
+ baseRateBps: 1_200,
55
+ maxDiscountBps: 600,
56
+ providerProgram: "RepuProvider1111111111111111111111111111111",
57
+ }));
58
+ const events = Array.from({ length: steps }, (_, i) => fakeEvent(1_000_000 + i, KINDS[i % KINDS.length] ?? "afterDeposit"));
59
+ const report = simulate(composition, events);
60
+ console.log(kleur.bold().yellow(`Lien simulation — pool=${opts.pool}, events=${report.totalEvents}`));
61
+ console.log(` ltv overrides ${kleur.cyan(report.ltvOverrides)}`);
62
+ console.log(` rate overrides ${kleur.cyan(report.rateOverrides)}`);
63
+ console.log(` liquidations delay ${kleur.cyan(report.liquidationsDelayed)}`);
64
+ console.log(` liquidations exec ${kleur.cyan(report.liquidationsExecuted)}`);
65
+ console.log(` borrows rejected ${kleur.red(report.borrowsRejected)}`);
66
+ console.log(` realised PnL (1e8) ${kleur.green(report.realisedPnlE8.toString())}`);
67
+ });
68
+ }
69
+ //# sourceMappingURL=simulate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simulate.js","sourceRoot":"","sources":["../../src/commands/simulate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { simulateCommand } from "./commands/simulate.js";
2
+ export { createCommand } from "./commands/create.js";
3
+ export { deployCommand } from "./commands/deploy.js";
4
+ export { listCommand } from "./commands/list.js";
5
+ export { actionCommand } from "./commands/action.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { simulateCommand } from "./commands/simulate.js";
2
+ export { createCommand } from "./commands/create.js";
3
+ export { deployCommand } from "./commands/deploy.js";
4
+ export { listCommand } from "./commands/list.js";
5
+ export { actionCommand } from "./commands/action.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@liens/cli",
3
+ "version": "0.1.0",
4
+ "description": "Lien command-line tools \u2014 create, simulate, and deploy lending hooks on Solana.",
5
+ "type": "module",
6
+ "bin": {
7
+ "lien": "dist/bin.js"
8
+ },
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "templates"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc -p tsconfig.json && chmod +x dist/bin.js",
18
+ "typecheck": "tsc --noEmit -p tsconfig.json",
19
+ "start": "tsx src/bin.ts"
20
+ },
21
+ "dependencies": {
22
+ "@liens/sdk": "^0.1.0",
23
+ "@solana/web3.js": "^1.95.4",
24
+ "commander": "^13.0.0",
25
+ "kleur": "^4.1.5",
26
+ "prompts": "^2.4.2"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^22.10.5",
30
+ "@types/prompts": "^2.4.9",
31
+ "tsx": "^4.19.2",
32
+ "typescript": "^5.7.2"
33
+ }
34
+ }