@ilalv3/cli 0.2.14 → 0.2.16
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 +29 -12
- package/dist/commands/demo.js +3 -3
- package/dist/commands/init.js +6 -6
- package/dist/commands/issuer.d.ts +14 -0
- package/dist/commands/issuer.js +134 -0
- package/dist/commands/liquidity.d.ts +1 -1
- package/dist/commands/liquidity.js +1 -1
- package/dist/index.js +34 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ ilal status --wallet 0xc0807D4778a9E5FE15ad68A8500e64d65BA78D58
|
|
|
34
34
|
ilal demo check --wallet 0xc0807D4778a9E5FE15ad68A8500e64d65BA78D58
|
|
35
35
|
|
|
36
36
|
# 4. Execute a compliant swap with the seeded reviewer key
|
|
37
|
-
PRIVATE_KEY=0x... ilal swap --amount-in 1 --token-in
|
|
37
|
+
PRIVATE_KEY=0x... ilal swap --amount-in 1 --token-in 0x8C38061e31FB02df445576685975d85F01D8686d --min-amount-out 0
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
For a fully seeded local/testnet demo, deploy mock EAS + demo pool pieces:
|
|
@@ -134,6 +134,10 @@ ILAL_ARTIFACT_CACHE=/opt/ilal/artifacts/ilal-v1
|
|
|
134
134
|
| `ilal credential prove` | Trader flow: hosted/cached ZK artifacts → local proof → mint or renew CNF |
|
|
135
135
|
| `ilal credential mint` | Mint CNF via Coinbase EAS attestation |
|
|
136
136
|
| `ilal credential renew` | Renew CNF via EAS attestation |
|
|
137
|
+
| `ilal issuer create` | Create issuer standard profile and return `standard_id` |
|
|
138
|
+
| `ilal issuer set-jurisdiction` | Set allowed jurisdictions |
|
|
139
|
+
| `ilal issuer set-type` | Set accredited-only requirement |
|
|
140
|
+
| `ilal issuer get` | Read standard profile and `credentialType` |
|
|
137
141
|
| `ilal swap` | Compliant swap via ILALRouter with optional `--min-amount-out` |
|
|
138
142
|
| `ilal pool add-liquidity` | Add liquidity to a compliant pool |
|
|
139
143
|
| `ilal pool remove-liquidity` | Remove liquidity from a compliant pool |
|
|
@@ -152,16 +156,29 @@ ILAL_ARTIFACT_CACHE=/opt/ilal/artifacts/ilal-v1
|
|
|
152
156
|
|
|
153
157
|
Session note: ILAL hookData is a one-time EIP-712 authorization with a deadline and nonce. The expensive compliance step is the CNF issuance or renewal; swaps do not verify a fresh ZK proof. Use `ilal session sign` to export hookData, and `ilal swap --hook-data <hex>` to execute with an externally signed authorization.
|
|
154
158
|
|
|
159
|
+
## Issuer standards
|
|
160
|
+
|
|
161
|
+
External issuers can define a compliance standard and use its `standard_id` as the on-chain `credentialType` for pool policy registration:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
ilal issuer create --standard "Goldfinch Accredited Investor"
|
|
165
|
+
ilal issuer set-jurisdiction --allow US,EU,SG
|
|
166
|
+
ilal issuer set-type --accredited-only true
|
|
167
|
+
ilal issuer get
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Profiles are stored in `.ilal-issuer-standards.json`. Pools enforce the returned `standard_id` through `PolicyRegistry.requiredCredentialType`.
|
|
171
|
+
|
|
155
172
|
## Configuration
|
|
156
173
|
|
|
157
174
|
The CLI reads `.ilal.json` in the current directory. Run `ilal init` to create it, or pass flags directly:
|
|
158
175
|
|
|
159
176
|
```bash
|
|
160
177
|
ilal swap \
|
|
161
|
-
--router
|
|
162
|
-
--hook
|
|
178
|
+
--router 0xA571F7f41c8abC19F20ABAe648e26a75fbe1F434 \
|
|
179
|
+
--hook 0x4847B222d11938A70073292d97cDB98ff8D64a80 \
|
|
163
180
|
--issuer 0x33541301e35d33eDf554c4DFba1e04d04FCc52F4 \
|
|
164
|
-
--pool-id
|
|
181
|
+
--pool-id 0x426925fe1ebecf2da7184f9749622ab1a4b8870c888d75da10332aee2080c86f \
|
|
165
182
|
--amount-in 0.001
|
|
166
183
|
```
|
|
167
184
|
|
|
@@ -172,19 +189,19 @@ ilal swap \
|
|
|
172
189
|
| CNFIssuer | `0x33541301e35d33eDf554c4DFba1e04d04FCc52F4` |
|
|
173
190
|
| MockEAS | `0x6A98096DF6F54DBF40498dC5525d84AEA840663A` |
|
|
174
191
|
| ZKVerifierAdapter | `0x9467ED8d962221e3C1865a387481B862B1b5bE95` |
|
|
175
|
-
| ComplianceHook | `
|
|
176
|
-
| ILALRouter | `
|
|
192
|
+
| ComplianceHook | `0x4847B222d11938A70073292d97cDB98ff8D64a80` |
|
|
193
|
+
| ILALRouter | `0xA571F7f41c8abC19F20ABAe648e26a75fbe1F434` |
|
|
177
194
|
| PolicyRegistry | `0x83d8111B415E97bA91eaAe717c2D9Ae6f0DD19d4` |
|
|
178
|
-
| Currency0 / TOKA | `
|
|
179
|
-
| Currency1 / TOKB | `
|
|
180
|
-
| Pool ID | `
|
|
195
|
+
| Currency0 / TOKA | `0x8C38061e31FB02df445576685975d85F01D8686d` |
|
|
196
|
+
| Currency1 / TOKB | `0xD0e6467D562829d215dB48CDfF4C289095D90B6B` |
|
|
197
|
+
| Pool ID | `0x426925fe1ebecf2da7184f9749622ab1a4b8870c888d75da10332aee2080c86f` |
|
|
181
198
|
|
|
182
199
|
Live proof:
|
|
183
200
|
|
|
184
201
|
- CNF ZK mint tx: `0xb9aa16c9604a575c8b2281cbfe9ba24fedbf205283a7b05638fbc413ed78de41`
|
|
185
|
-
- Add liquidity tx: `
|
|
186
|
-
- Swap tx: `
|
|
187
|
-
- Router bypass fix verified: `ComplianceHook.authorizedRouter()` returns `
|
|
202
|
+
- Add liquidity tx: `0x1ffd6b1546b3f3846d8f86fc21ec059a83a02f23130390c1b9343733d3a9776f`
|
|
203
|
+
- Swap tx: `0x36427e232b323e4a8c310286d0312dbf1f4ecde86d58245a81713aafe4df0720`
|
|
204
|
+
- Router bypass fix verified: `ComplianceHook.authorizedRouter()` returns `0xA571F7f41c8abC19F20ABAe648e26a75fbe1F434`
|
|
188
205
|
|
|
189
206
|
## License
|
|
190
207
|
|
package/dist/commands/demo.js
CHANGED
|
@@ -11,9 +11,9 @@ const POOL_MANAGER = {
|
|
|
11
11
|
const SAMPLE = {
|
|
12
12
|
wallet: "0xc0807D4778a9E5FE15ad68A8500e64d65BA78D58",
|
|
13
13
|
issuer: "0x33541301e35d33eDf554c4DFba1e04d04FCc52F4",
|
|
14
|
-
hook: "
|
|
15
|
-
router: "
|
|
16
|
-
pool: "
|
|
14
|
+
hook: "0x4847B222d11938A70073292d97cDB98ff8D64a80",
|
|
15
|
+
router: "0xA571F7f41c8abC19F20ABAe648e26a75fbe1F434",
|
|
16
|
+
pool: "0x426925fe1ebecf2da7184f9749622ab1a4b8870c888d75da10332aee2080c86f",
|
|
17
17
|
proof: "0x91f2b8a0c43e902f7f1a8c0d",
|
|
18
18
|
session: "0x6b84eac5e0db21f8d5d43b7a",
|
|
19
19
|
};
|
package/dist/commands/init.js
CHANGED
|
@@ -11,13 +11,13 @@ import { fmt, log, header, die } from "../ui.js";
|
|
|
11
11
|
const PRESETS = {
|
|
12
12
|
"84532": {
|
|
13
13
|
issuer: "0x33541301e35d33eDf554c4DFba1e04d04FCc52F4",
|
|
14
|
-
hook: "
|
|
14
|
+
hook: "0x4847B222d11938A70073292d97cDB98ff8D64a80",
|
|
15
15
|
registry: "0x83d8111B415E97bA91eaAe717c2D9Ae6f0DD19d4",
|
|
16
|
-
router: "
|
|
17
|
-
treasury: "
|
|
18
|
-
tokenA: "
|
|
19
|
-
tokenB: "
|
|
20
|
-
poolId: "
|
|
16
|
+
router: "0xA571F7f41c8abC19F20ABAe648e26a75fbe1F434",
|
|
17
|
+
treasury: "0xc0807D4778a9E5FE15ad68A8500e64d65BA78D58",
|
|
18
|
+
tokenA: "0x8C38061e31FB02df445576685975d85F01D8686d",
|
|
19
|
+
tokenB: "0xD0e6467D562829d215dB48CDfF4C289095D90B6B",
|
|
20
|
+
poolId: "0x426925fe1ebecf2da7184f9749622ab1a4b8870c888d75da10332aee2080c86f",
|
|
21
21
|
fee: "8388608",
|
|
22
22
|
tickSpacing: "60",
|
|
23
23
|
rpc: "https://sepolia.base.org",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function issuerCreate(opts: {
|
|
2
|
+
standard: string;
|
|
3
|
+
}): Promise<void>;
|
|
4
|
+
export declare function issuerSetJurisdiction(opts: {
|
|
5
|
+
id?: string;
|
|
6
|
+
allow: string;
|
|
7
|
+
}): Promise<void>;
|
|
8
|
+
export declare function issuerSetType(opts: {
|
|
9
|
+
id?: string;
|
|
10
|
+
accreditedOnly: string | boolean;
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
export declare function issuerGet(opts: {
|
|
13
|
+
id?: string;
|
|
14
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
import { keccak256, stringToBytes, isHex } from "viem";
|
|
4
|
+
import { fmt, header, log, die } from "../ui.js";
|
|
5
|
+
const STORE_FILE = ".ilal-issuer-standards.json";
|
|
6
|
+
function storePath() {
|
|
7
|
+
return resolve(process.cwd(), STORE_FILE);
|
|
8
|
+
}
|
|
9
|
+
function loadStore() {
|
|
10
|
+
const path = storePath();
|
|
11
|
+
if (!existsSync(path))
|
|
12
|
+
return { version: 1, standards: {} };
|
|
13
|
+
try {
|
|
14
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
15
|
+
return {
|
|
16
|
+
version: 1,
|
|
17
|
+
latest: parsed.latest,
|
|
18
|
+
standards: parsed.standards ?? {},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
die(`Could not parse ${STORE_FILE}. Fix or remove the file and try again.`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function saveStore(store) {
|
|
26
|
+
writeFileSync(storePath(), JSON.stringify(store, null, 2) + "\n");
|
|
27
|
+
}
|
|
28
|
+
function normalizeId(id, store) {
|
|
29
|
+
const resolved = id ?? store?.latest;
|
|
30
|
+
if (!resolved)
|
|
31
|
+
die("Standard id required. Pass --id <standard_id> or run `ilal issuer create` first.");
|
|
32
|
+
if (!isHex(resolved) || resolved.length !== 66)
|
|
33
|
+
die("standard_id must be 0x + 32 bytes.");
|
|
34
|
+
return resolved;
|
|
35
|
+
}
|
|
36
|
+
function parseJurisdictions(raw) {
|
|
37
|
+
const list = raw.split(",").map((item) => item.trim()).filter(Boolean);
|
|
38
|
+
if (list.length === 0)
|
|
39
|
+
die("--allow must include at least one jurisdiction, e.g. US,EU,SG");
|
|
40
|
+
return [...new Set(list)];
|
|
41
|
+
}
|
|
42
|
+
function parseBool(raw) {
|
|
43
|
+
if (typeof raw === "boolean")
|
|
44
|
+
return raw;
|
|
45
|
+
const value = raw.trim().toLowerCase();
|
|
46
|
+
if (["true", "1", "yes", "y"].includes(value))
|
|
47
|
+
return true;
|
|
48
|
+
if (["false", "0", "no", "n"].includes(value))
|
|
49
|
+
return false;
|
|
50
|
+
die("--accredited-only must be true or false");
|
|
51
|
+
}
|
|
52
|
+
function printStandard(item) {
|
|
53
|
+
log.kv("standard_id", fmt.cyan(item.id));
|
|
54
|
+
log.kv("standard", item.standard);
|
|
55
|
+
log.kv("jurisdictions", item.allowedJurisdictions.length ? item.allowedJurisdictions.join(", ") : fmt.badge("unset", "yellow"));
|
|
56
|
+
log.kv("accredited only", item.accreditedOnly === null ? fmt.badge("unset", "yellow") : String(item.accreditedOnly));
|
|
57
|
+
log.kv("credentialType", fmt.cyan(item.id));
|
|
58
|
+
log.kv("updated", fmt.gray(item.updatedAt));
|
|
59
|
+
}
|
|
60
|
+
export async function issuerCreate(opts) {
|
|
61
|
+
const standard = opts.standard.trim();
|
|
62
|
+
if (!standard)
|
|
63
|
+
die("--standard <name> required");
|
|
64
|
+
const store = loadStore();
|
|
65
|
+
const now = new Date().toISOString();
|
|
66
|
+
const id = keccak256(stringToBytes(`ILAL_STANDARD_V1:${standard}`));
|
|
67
|
+
const existing = store.standards[id];
|
|
68
|
+
const item = existing ?? {
|
|
69
|
+
id,
|
|
70
|
+
standard,
|
|
71
|
+
allowedJurisdictions: [],
|
|
72
|
+
accreditedOnly: null,
|
|
73
|
+
createdAt: now,
|
|
74
|
+
updatedAt: now,
|
|
75
|
+
};
|
|
76
|
+
item.standard = standard;
|
|
77
|
+
item.updatedAt = now;
|
|
78
|
+
store.standards[id] = item;
|
|
79
|
+
store.latest = id;
|
|
80
|
+
saveStore(store);
|
|
81
|
+
header("Issuer Standard Created");
|
|
82
|
+
log.section("Standard");
|
|
83
|
+
printStandard(item);
|
|
84
|
+
log.line();
|
|
85
|
+
log.callout("Use this id as credentialType", `ilal pool policy set --cred-type ${id}`, "green");
|
|
86
|
+
log.kv("file", fmt.gray(storePath()));
|
|
87
|
+
console.log();
|
|
88
|
+
}
|
|
89
|
+
export async function issuerSetJurisdiction(opts) {
|
|
90
|
+
const store = loadStore();
|
|
91
|
+
const id = normalizeId(opts.id, store);
|
|
92
|
+
const item = store.standards[id];
|
|
93
|
+
if (!item)
|
|
94
|
+
die(`Unknown standard_id ${id}. Run \`ilal issuer create --standard <name>\` first.`);
|
|
95
|
+
item.allowedJurisdictions = parseJurisdictions(opts.allow);
|
|
96
|
+
item.updatedAt = new Date().toISOString();
|
|
97
|
+
store.latest = id;
|
|
98
|
+
saveStore(store);
|
|
99
|
+
header("Issuer Jurisdiction Updated");
|
|
100
|
+
log.section("Standard");
|
|
101
|
+
printStandard(item);
|
|
102
|
+
log.kv("file", fmt.gray(storePath()));
|
|
103
|
+
console.log();
|
|
104
|
+
}
|
|
105
|
+
export async function issuerSetType(opts) {
|
|
106
|
+
const store = loadStore();
|
|
107
|
+
const id = normalizeId(opts.id, store);
|
|
108
|
+
const item = store.standards[id];
|
|
109
|
+
if (!item)
|
|
110
|
+
die(`Unknown standard_id ${id}. Run \`ilal issuer create --standard <name>\` first.`);
|
|
111
|
+
item.accreditedOnly = parseBool(opts.accreditedOnly);
|
|
112
|
+
item.updatedAt = new Date().toISOString();
|
|
113
|
+
store.latest = id;
|
|
114
|
+
saveStore(store);
|
|
115
|
+
header("Issuer Investor Type Updated");
|
|
116
|
+
log.section("Standard");
|
|
117
|
+
printStandard(item);
|
|
118
|
+
log.kv("file", fmt.gray(storePath()));
|
|
119
|
+
console.log();
|
|
120
|
+
}
|
|
121
|
+
export async function issuerGet(opts) {
|
|
122
|
+
const store = loadStore();
|
|
123
|
+
const id = normalizeId(opts.id, store);
|
|
124
|
+
const item = store.standards[id];
|
|
125
|
+
if (!item)
|
|
126
|
+
die(`Unknown standard_id ${id}. Available standards: ${Object.keys(store.standards).length}`);
|
|
127
|
+
header("Issuer Standard");
|
|
128
|
+
log.section("Standard");
|
|
129
|
+
printStandard(item);
|
|
130
|
+
log.line();
|
|
131
|
+
log.info("This CLI profile is the issuer-side descriptor. Pools enforce the matching credentialType on-chain via PolicyRegistry.");
|
|
132
|
+
log.command(`ilal pool policy set --cred-type ${item.id} --issuer <CNFIssuer> --registry <PolicyRegistry> --pool <poolId>`);
|
|
133
|
+
console.log();
|
|
134
|
+
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Usage:
|
|
10
10
|
* ilal pool add-liquidity \
|
|
11
11
|
* --tick-lower -600 --tick-upper 600 \
|
|
12
|
-
* --liquidity
|
|
12
|
+
* --liquidity 1000000000000 \
|
|
13
13
|
* --router 0xROUTER --hook 0xHOOK --issuer 0xISSUER \
|
|
14
14
|
* --pool-id 0xPOOLID --token-a 0xTOKA --token-b 0xTOKB
|
|
15
15
|
*/
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Usage:
|
|
10
10
|
* ilal pool add-liquidity \
|
|
11
11
|
* --tick-lower -600 --tick-upper 600 \
|
|
12
|
-
* --liquidity
|
|
12
|
+
* --liquidity 1000000000000 \
|
|
13
13
|
* --router 0xROUTER --hook 0xHOOK --issuer 0xISSUER \
|
|
14
14
|
* --pool-id 0xPOOLID --token-a 0xTOKA --token-b 0xTOKB
|
|
15
15
|
*/
|
package/dist/index.js
CHANGED
|
@@ -13,13 +13,14 @@ import { init } from "./commands/init.js";
|
|
|
13
13
|
import { status } from "./commands/status.js";
|
|
14
14
|
import { swap } from "./commands/swap.js";
|
|
15
15
|
import { addLiquidity, removeLiquidity } from "./commands/liquidity.js";
|
|
16
|
+
import { issuerCreate, issuerGet, issuerSetJurisdiction, issuerSetType } from "./commands/issuer.js";
|
|
16
17
|
import { fmt } from "./ui.js";
|
|
17
18
|
import { COINBASE_SCHEMA_UID } from "./constants.js";
|
|
18
19
|
const program = new Command();
|
|
19
20
|
program
|
|
20
21
|
.name("ilal")
|
|
21
22
|
.description("ILAL Protocol CLI — Uniswap v4 compliance hook toolkit")
|
|
22
|
-
.version("0.2.
|
|
23
|
+
.version("0.2.16")
|
|
23
24
|
.addHelpText("before", `\n ${fmt.bold(fmt.cyan("◆"))} ${fmt.bold("ILAL Protocol")} ${fmt.gray("Uniswap v4 Compliance Hook")}\n`);
|
|
24
25
|
// ─── init ─────────────────────────────────────────────────────────────────────
|
|
25
26
|
program
|
|
@@ -96,6 +97,38 @@ const err = (e) => {
|
|
|
96
97
|
console.error(fmt.red(`\nError: ${e instanceof Error ? e.message : String(e)}\n`));
|
|
97
98
|
process.exit(1);
|
|
98
99
|
};
|
|
100
|
+
// ─── issuer ──────────────────────────────────────────────────────────────────
|
|
101
|
+
const issuer = program.command("issuer").description("Issuer standard management");
|
|
102
|
+
issuer
|
|
103
|
+
.command("create")
|
|
104
|
+
.description("Create an issuer compliance standard profile and return a standard_id")
|
|
105
|
+
.requiredOption("--standard <name>", "Compliance standard name, e.g. Goldfinch Accredited Investor")
|
|
106
|
+
.action(async (opts) => {
|
|
107
|
+
await issuerCreate(opts).catch(err);
|
|
108
|
+
});
|
|
109
|
+
issuer
|
|
110
|
+
.command("set-jurisdiction")
|
|
111
|
+
.description("Set allowed jurisdictions for an issuer standard")
|
|
112
|
+
.option("--id <standard_id>", "Standard id (defaults to latest created standard)")
|
|
113
|
+
.requiredOption("--allow <list>", "Comma-separated jurisdictions, e.g. US,EU,SG")
|
|
114
|
+
.action(async (opts) => {
|
|
115
|
+
await issuerSetJurisdiction(opts).catch(err);
|
|
116
|
+
});
|
|
117
|
+
issuer
|
|
118
|
+
.command("set-type")
|
|
119
|
+
.description("Set investor type requirements for an issuer standard")
|
|
120
|
+
.option("--id <standard_id>", "Standard id (defaults to latest created standard)")
|
|
121
|
+
.requiredOption("--accredited-only <bool>", "true or false")
|
|
122
|
+
.action(async (opts) => {
|
|
123
|
+
await issuerSetType(opts).catch(err);
|
|
124
|
+
});
|
|
125
|
+
issuer
|
|
126
|
+
.command("get")
|
|
127
|
+
.description("Read an issuer standard profile")
|
|
128
|
+
.option("--id <standard_id>", "Standard id (defaults to latest created standard)")
|
|
129
|
+
.action(async (opts) => {
|
|
130
|
+
await issuerGet(opts).catch(err);
|
|
131
|
+
});
|
|
99
132
|
// ─── credential ───────────────────────────────────────────────────────────────
|
|
100
133
|
const credential = program.command("credential").description("Manage compliance credentials (CNF)");
|
|
101
134
|
credential
|