@ilalv3/cli 0.2.8 → 0.2.10
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/commands/credential.d.ts +2 -2
- package/dist/commands/credential.js +22 -12
- package/dist/commands/demo.js +8 -9
- package/dist/commands/deploy.js +2 -4
- package/dist/commands/liquidity.js +8 -6
- package/dist/commands/mint.d.ts +2 -2
- package/dist/commands/mint.js +35 -22
- package/dist/commands/oracle.js +2 -4
- package/dist/commands/pool.js +2 -6
- package/dist/commands/proof.js +2 -4
- package/dist/commands/prove.js +2 -4
- package/dist/commands/session.js +2 -6
- package/dist/commands/swap.js +3 -5
- package/dist/index.js +9 -9
- package/dist/ui.d.ts +1 -0
- package/dist/ui.js +13 -0
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createPublicClient, http, isAddress } from "viem";
|
|
2
2
|
import { base, baseSepolia } from "viem/chains";
|
|
3
3
|
import { fmt, log, die } from "../ui.js";
|
|
4
|
+
import { withConfig } from "../config.js";
|
|
4
5
|
const CNF_ABI = [
|
|
5
6
|
{ name: "isValid", type: "function", stateMutability: "view", inputs: [{ name: "wallet", type: "address" }], outputs: [{ type: "bool" }] },
|
|
6
7
|
{ name: "credentialOf", type: "function", stateMutability: "view", inputs: [{ name: "wallet", type: "address" }], outputs: [{ name: "tokenId", type: "uint256" }] },
|
|
@@ -11,30 +12,39 @@ const CHAINS = {
|
|
|
11
12
|
"84532": baseSepolia,
|
|
12
13
|
};
|
|
13
14
|
export async function credentialStatus(opts) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
const cfg = withConfig(opts);
|
|
16
|
+
if (!isAddress(cfg.wallet))
|
|
17
|
+
die(`Invalid wallet address: ${cfg.wallet}`);
|
|
18
|
+
if (!cfg.issuer)
|
|
19
|
+
die("CNFIssuer address required. Use --issuer or run `ilal init`.");
|
|
20
|
+
if (!isAddress(cfg.issuer))
|
|
21
|
+
die(`Invalid issuer address: ${cfg.issuer}`);
|
|
22
|
+
const chain = CHAINS[cfg.chain ?? "84532"] ?? baseSepolia;
|
|
23
|
+
const transport = cfg.rpc ? http(cfg.rpc) : http();
|
|
20
24
|
const client = createPublicClient({ chain, transport });
|
|
21
25
|
console.log();
|
|
22
26
|
console.log(fmt.bold(" ILAL Credential Status"));
|
|
23
27
|
log.line();
|
|
24
|
-
log.kv("wallet",
|
|
25
|
-
log.kv("issuer",
|
|
28
|
+
log.kv("wallet", cfg.wallet);
|
|
29
|
+
log.kv("issuer", cfg.issuer);
|
|
26
30
|
log.kv("chain", chain.name);
|
|
27
31
|
log.line();
|
|
28
32
|
log.step("Querying CNFIssuer on-chain…");
|
|
29
33
|
const [valid, tokenId] = await Promise.all([
|
|
30
|
-
client.readContract({ address:
|
|
31
|
-
client.readContract({ address:
|
|
34
|
+
client.readContract({ address: cfg.issuer, abi: CNF_ABI, functionName: "isValid", args: [cfg.wallet] }),
|
|
35
|
+
client.readContract({ address: cfg.issuer, abi: CNF_ABI, functionName: "credentialOf", args: [cfg.wallet] }),
|
|
32
36
|
]);
|
|
33
37
|
if (tokenId === 0n) {
|
|
34
38
|
log.fail("No credential found for this wallet");
|
|
35
39
|
console.log();
|
|
36
40
|
console.log(fmt.bold(" How to get a CNF credential:"));
|
|
37
41
|
console.log();
|
|
42
|
+
console.log(fmt.bold(" Demo path — issuer-created MockEAS attestation"));
|
|
43
|
+
console.log(` ${fmt.gray("1.")} Ask the issuer/operator to run:`);
|
|
44
|
+
console.log(` ${fmt.cyan("PRIVATE_KEY=<issuer-owner> ilal demo attest --wallet " + cfg.wallet)}`);
|
|
45
|
+
console.log(` ${fmt.gray("2.")} Then mint with your wallet key:`);
|
|
46
|
+
console.log(` ${fmt.cyan("PRIVATE_KEY=<wallet-key> ilal credential mint --attestation <uid>")}`);
|
|
47
|
+
console.log();
|
|
38
48
|
console.log(fmt.bold(" Path A — Coinbase Verifications (EAS)"));
|
|
39
49
|
console.log(` ${fmt.gray("1.")} Complete KYC at ${fmt.cyan("https://coinbase.com/onchain-verify")}`);
|
|
40
50
|
console.log(` ${fmt.gray("2.")} Find your attestation UID on EAS Explorer:`);
|
|
@@ -49,12 +59,12 @@ export async function credentialStatus(opts) {
|
|
|
49
59
|
console.log(` ${fmt.gray("1.")} Issuer/operator adds wallet to the Merkle tree`);
|
|
50
60
|
console.log(` ${fmt.gray("2.")} Operator queues root: ${fmt.cyan("ilal oracle propose-root --root <newMerkleRoot>")}`);
|
|
51
61
|
console.log(` ${fmt.gray("3.")} After timelock, operator activates: ${fmt.cyan("ilal oracle activate-root")}`);
|
|
52
|
-
console.log(` ${fmt.gray("4.")} Trader runs: ${fmt.cyan("ilal credential prove --wallet " +
|
|
62
|
+
console.log(` ${fmt.gray("4.")} Trader runs: ${fmt.cyan("ilal credential prove --wallet " + cfg.wallet)}`);
|
|
53
63
|
console.log();
|
|
54
64
|
return;
|
|
55
65
|
}
|
|
56
66
|
const cred = await client.readContract({
|
|
57
|
-
address:
|
|
67
|
+
address: cfg.issuer,
|
|
58
68
|
abi: CNF_ABI,
|
|
59
69
|
functionName: "getCredential",
|
|
60
70
|
args: [tokenId],
|
package/dist/commands/demo.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createPublicClient, createWalletClient, decodeEventLog, formatUnits, ht
|
|
|
2
2
|
import { privateKeyToAccount } from "viem/accounts";
|
|
3
3
|
import { base, baseSepolia } from "viem/chains";
|
|
4
4
|
import { loadConfig } from "../config.js";
|
|
5
|
-
import { die, fmt, header, log, Spinner } from "../ui.js";
|
|
5
|
+
import { die, fmt, header, log, Spinner, requirePrivateKey } from "../ui.js";
|
|
6
6
|
const CHAINS = { "8453": base, "84532": baseSepolia };
|
|
7
7
|
const POOL_MANAGER = {
|
|
8
8
|
"84532": "0x05E73354cFDd6745C338b50BcFDfA3Aa6fA03408",
|
|
@@ -442,6 +442,11 @@ export async function demoCheck(opts) {
|
|
|
442
442
|
}
|
|
443
443
|
if (wallet) {
|
|
444
444
|
log.command(`ilal status --wallet ${wallet}`);
|
|
445
|
+
if (!credentialReady) {
|
|
446
|
+
log.info("Credential missing: the issuer must create an attestation before the wallet can mint CNF.");
|
|
447
|
+
log.command(`PRIVATE_KEY=<issuer-owner> ilal demo attest --wallet ${wallet}`);
|
|
448
|
+
log.command("PRIVATE_KEY=<wallet-key> ilal credential mint --attestation <uid>");
|
|
449
|
+
}
|
|
445
450
|
log.command(`ilal session sign --pool ${cfg.poolId ?? "<poolId>"} --action swap --hook ${cfg.hook ?? "<hook>"} --issuer ${cfg.issuer ?? "<issuer>"} --caller ${cfg.router ?? "<router>"}`);
|
|
446
451
|
}
|
|
447
452
|
else {
|
|
@@ -454,10 +459,7 @@ export async function demoCheck(opts) {
|
|
|
454
459
|
export async function demoFaucet(opts) {
|
|
455
460
|
const cfg = loadConfig();
|
|
456
461
|
const chain = CHAINS[cfg.chain ?? "84532"] ?? baseSepolia;
|
|
457
|
-
const rawKey = opts.privateKey ?? process.env["PRIVATE_KEY"];
|
|
458
|
-
if (!rawKey || !isHex(rawKey) || rawKey.length !== 66) {
|
|
459
|
-
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
460
|
-
}
|
|
462
|
+
const rawKey = requirePrivateKey(opts.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
461
463
|
if (!cfg.tokenA || !cfg.tokenB || !isAddress(cfg.tokenA) || !isAddress(cfg.tokenB)) {
|
|
462
464
|
die("tokenA/tokenB required. Run `ilal init` with demo token addresses first.");
|
|
463
465
|
}
|
|
@@ -492,10 +494,7 @@ export async function demoFaucet(opts) {
|
|
|
492
494
|
export async function demoAttest(opts) {
|
|
493
495
|
const cfg = loadConfig();
|
|
494
496
|
const chain = CHAINS[cfg.chain ?? "84532"] ?? baseSepolia;
|
|
495
|
-
const rawKey = opts.privateKey ?? process.env["PRIVATE_KEY"];
|
|
496
|
-
if (!rawKey || !isHex(rawKey) || rawKey.length !== 66) {
|
|
497
|
-
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
498
|
-
}
|
|
497
|
+
const rawKey = requirePrivateKey(opts.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
499
498
|
if (!cfg.issuer || !isAddress(cfg.issuer))
|
|
500
499
|
die("CNFIssuer required. Run `ilal init` first.");
|
|
501
500
|
if (!isAddress(opts.wallet))
|
package/dist/commands/deploy.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execSync } from "child_process";
|
|
2
2
|
import { existsSync } from "fs";
|
|
3
3
|
import { resolve } from "path";
|
|
4
|
-
import { fmt, log, die } from "../ui.js";
|
|
4
|
+
import { fmt, log, die, requirePrivateKey } from "../ui.js";
|
|
5
5
|
import { EAS_ADDRESSES, COINBASE_ATTESTER, COINBASE_SCHEMA_UID } from "../constants.js";
|
|
6
6
|
const POOL_MANAGERS = {
|
|
7
7
|
"8453": "0x498581ff718922c3f8e6a244956af099b2652b2b", // Base mainnet
|
|
@@ -12,9 +12,7 @@ const RPC_URLS = {
|
|
|
12
12
|
"84532": "https://sepolia.base.org",
|
|
13
13
|
};
|
|
14
14
|
export async function deploy(opts) {
|
|
15
|
-
const privateKey = opts.privateKey ?? process.env["PRIVATE_KEY"];
|
|
16
|
-
if (!privateKey)
|
|
17
|
-
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
15
|
+
const privateKey = requirePrivateKey(opts.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
18
16
|
const chainId = opts.chain;
|
|
19
17
|
const poolManager = POOL_MANAGERS[chainId];
|
|
20
18
|
if (!poolManager)
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { createPublicClient, createWalletClient, encodeAbiParameters, formatEther, formatUnits, http, isAddress, isHex, parseAbiParameters, } from "viem";
|
|
17
17
|
import { privateKeyToAccount } from "viem/accounts";
|
|
18
18
|
import { base, baseSepolia } from "viem/chains";
|
|
19
|
-
import { fmt, log, header, Spinner, die, dieOnContract } from "../ui.js";
|
|
19
|
+
import { fmt, log, header, Spinner, die, dieOnContract, requirePrivateKey } from "../ui.js";
|
|
20
20
|
import { withConfig } from "../config.js";
|
|
21
21
|
const CHAINS = { "8453": base, "84532": baseSepolia };
|
|
22
22
|
// ─── ABIs ─────────────────────────────────────────────────────────────────────
|
|
@@ -122,12 +122,13 @@ function allowanceLabel(raw, decimals, symbol) {
|
|
|
122
122
|
function secondsSince(startMs) {
|
|
123
123
|
return `${((Date.now() - startMs) / 1000).toFixed(1)}s`;
|
|
124
124
|
}
|
|
125
|
+
function defaultUserSalt(address) {
|
|
126
|
+
return `0x000000000000000000000000${address.slice(2)}`;
|
|
127
|
+
}
|
|
125
128
|
// ─── Shared core ──────────────────────────────────────────────────────────────
|
|
126
129
|
async function executeLiquidity(action, opts) {
|
|
127
130
|
const cfg = withConfig(opts);
|
|
128
|
-
const rawKey = cfg.privateKey ?? process.env["PRIVATE_KEY"];
|
|
129
|
-
if (!rawKey)
|
|
130
|
-
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
131
|
+
const rawKey = requirePrivateKey(cfg.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
131
132
|
if (!cfg.router)
|
|
132
133
|
die("ILALRouter address required. Use --router or set in .ilal.json");
|
|
133
134
|
if (!cfg.hook)
|
|
@@ -161,7 +162,7 @@ async function executeLiquidity(action, opts) {
|
|
|
161
162
|
const liquidity = BigInt(opts.liquidity);
|
|
162
163
|
const fee = parseInt(cfg.fee ?? "3000");
|
|
163
164
|
const tickSpacing = parseInt(cfg.tickSpacing ?? "60");
|
|
164
|
-
const salt = (opts.salt ??
|
|
165
|
+
const salt = (opts.salt ?? defaultUserSalt(account.address));
|
|
165
166
|
const verb = action === "add" ? "Add" : "Remove";
|
|
166
167
|
header(`ILAL ${verb} Liquidity`, chain.name);
|
|
167
168
|
log.kv("router", fmt.cyan(cfg.router));
|
|
@@ -170,6 +171,7 @@ async function executeLiquidity(action, opts) {
|
|
|
170
171
|
log.kv("tickLower", tickLower.toString());
|
|
171
172
|
log.kv("tickUpper", tickUpper.toString());
|
|
172
173
|
log.kv("liquidity", liquidity.toString());
|
|
174
|
+
log.kv("salt", opts.salt ? fmt.hash(salt) : `${fmt.hash(salt)} ${fmt.gray("user-scoped default")}`);
|
|
173
175
|
log.line();
|
|
174
176
|
if (liquidity <= 0n) {
|
|
175
177
|
die("liquidity must be greater than 0. No approval or liquidity transaction was sent.");
|
|
@@ -195,7 +197,7 @@ async function executeLiquidity(action, opts) {
|
|
|
195
197
|
if (tokenId === 0n) {
|
|
196
198
|
preflightErrors.push("wallet has no CNF credential; mint one before changing liquidity.");
|
|
197
199
|
if (hasEASPath)
|
|
198
|
-
preflightErrors.push("issuer supports EAS/mock attestation minting: run `ilal credential mint --attestation <uid>`.");
|
|
200
|
+
preflightErrors.push("issuer supports EAS/mock attestation minting: first ask issuer to run `ilal demo attest --wallet <wallet>`, then run `ilal credential mint --attestation <uid>`.");
|
|
199
201
|
else if (hasZKPath)
|
|
200
202
|
preflightErrors.push(`issuer supports ZK minting: run \`ilal credential prove --wallet ${account.address}\`.`);
|
|
201
203
|
else
|
package/dist/commands/mint.d.ts
CHANGED
package/dist/commands/mint.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createPublicClient, createWalletClient, http, isAddress, isHex, } from "viem";
|
|
2
2
|
import { privateKeyToAccount } from "viem/accounts";
|
|
3
3
|
import { base, baseSepolia } from "viem/chains";
|
|
4
|
-
import { fmt, log, die } from "../ui.js";
|
|
4
|
+
import { fmt, log, die, Spinner, requirePrivateKey } from "../ui.js";
|
|
5
|
+
import { withConfig } from "../config.js";
|
|
5
6
|
import { EAS_ADDRESSES, COINBASE_SCHEMA_UID, COINBASE_ATTESTER } from "../constants.js";
|
|
6
7
|
const CHAINS = { "8453": base, "84532": baseSepolia };
|
|
7
8
|
const CNF_ISSUER_ABI = [
|
|
@@ -32,25 +33,24 @@ const CNF_ISSUER_ABI = [
|
|
|
32
33
|
];
|
|
33
34
|
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
34
35
|
async function sendMintTx(mode, opts) {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
die(`Invalid issuer address: ${opts.issuer}`);
|
|
36
|
+
const cfg = withConfig(opts);
|
|
37
|
+
const rawKey = requirePrivateKey(cfg.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
38
|
+
if (!cfg.issuer)
|
|
39
|
+
die("CNFIssuer address required. Use --issuer or run `ilal init`.");
|
|
40
|
+
if (!isAddress(cfg.issuer))
|
|
41
|
+
die(`Invalid issuer address: ${cfg.issuer}`);
|
|
42
42
|
if (!isHex(opts.attestation) || opts.attestation.length !== 66)
|
|
43
43
|
die("Attestation UID must be 0x + 32 bytes (64 hex chars).");
|
|
44
|
-
const chain = CHAINS[
|
|
44
|
+
const chain = CHAINS[cfg.chain ?? "84532"] ?? baseSepolia;
|
|
45
45
|
const account = privateKeyToAccount(rawKey);
|
|
46
|
-
const transport =
|
|
46
|
+
const transport = cfg.rpc ? http(cfg.rpc) : http();
|
|
47
47
|
const publicClient = createPublicClient({ chain, transport });
|
|
48
48
|
const walletClient = createWalletClient({ account, chain, transport });
|
|
49
49
|
console.log();
|
|
50
50
|
console.log(fmt.bold(` ILAL Credential ${mode === "mint" ? "Mint" : "Renew"}`));
|
|
51
51
|
log.line();
|
|
52
52
|
log.kv("wallet", account.address);
|
|
53
|
-
log.kv("issuer",
|
|
53
|
+
log.kv("issuer", cfg.issuer);
|
|
54
54
|
log.kv("attestation", opts.attestation);
|
|
55
55
|
log.kv("chain", chain.name);
|
|
56
56
|
if (opts.simulate)
|
|
@@ -59,9 +59,9 @@ async function sendMintTx(mode, opts) {
|
|
|
59
59
|
// Verify EAS attestation exists on-chain before sending tx
|
|
60
60
|
log.step("Verifying attestation on EAS…");
|
|
61
61
|
const [issuerEAS, issuerSchema, issuerAttester] = await Promise.all([
|
|
62
|
-
publicClient.readContract({ address:
|
|
63
|
-
publicClient.readContract({ address:
|
|
64
|
-
publicClient.readContract({ address:
|
|
62
|
+
publicClient.readContract({ address: cfg.issuer, abi: CNF_ISSUER_ABI, functionName: "eas" }),
|
|
63
|
+
publicClient.readContract({ address: cfg.issuer, abi: CNF_ISSUER_ABI, functionName: "schemaUID" }),
|
|
64
|
+
publicClient.readContract({ address: cfg.issuer, abi: CNF_ISSUER_ABI, functionName: "trustedAttester" }),
|
|
65
65
|
]);
|
|
66
66
|
const easAddress = issuerEAS !== ZERO_ADDRESS ? issuerEAS : EAS_ADDRESSES[chain.id];
|
|
67
67
|
if (!easAddress)
|
|
@@ -132,7 +132,7 @@ async function sendMintTx(mode, opts) {
|
|
|
132
132
|
}
|
|
133
133
|
log.step(`Sending ${mode === "mint" ? "mintWithEAS" : "renewWithEAS"} transaction…`);
|
|
134
134
|
const hash = await walletClient.writeContract({
|
|
135
|
-
address:
|
|
135
|
+
address: cfg.issuer,
|
|
136
136
|
abi: CNF_ISSUER_ABI,
|
|
137
137
|
functionName: mode === "mint" ? "mintWithEAS" : "renewWithEAS",
|
|
138
138
|
args: [opts.attestation],
|
|
@@ -144,13 +144,26 @@ async function sendMintTx(mode, opts) {
|
|
|
144
144
|
log.ok(fmt.bold(fmt.green(`CNF ${mode === "mint" ? "minted" : "renewed"} successfully`)));
|
|
145
145
|
log.kv("tx hash", hash);
|
|
146
146
|
log.kv("block", receipt.blockNumber.toString());
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
147
|
+
const validSpin = new Spinner("Waiting for credential validity…").start();
|
|
148
|
+
let valid = false;
|
|
149
|
+
for (let attempt = 0; attempt < 6; attempt++) {
|
|
150
|
+
valid = await publicClient.readContract({
|
|
151
|
+
address: cfg.issuer,
|
|
152
|
+
abi: CNF_ISSUER_ABI,
|
|
153
|
+
functionName: "isValid",
|
|
154
|
+
args: [account.address],
|
|
155
|
+
});
|
|
156
|
+
if (valid)
|
|
157
|
+
break;
|
|
158
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
159
|
+
}
|
|
160
|
+
if (valid)
|
|
161
|
+
validSpin.succeed("Credential active");
|
|
162
|
+
else {
|
|
163
|
+
validSpin.succeed("Mint confirmed; credential validity may take a few seconds to appear on this RPC");
|
|
164
|
+
log.info("Run `ilal credential status <wallet>` if this RPC still shows stale state.");
|
|
165
|
+
}
|
|
166
|
+
log.kv("isValid()", valid ? fmt.green("true ✓") : fmt.yellow("pending RPC refresh"));
|
|
154
167
|
}
|
|
155
168
|
else {
|
|
156
169
|
die(`Transaction reverted. Hash: ${hash}`);
|
package/dist/commands/oracle.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import { createPublicClient, createWalletClient, http, isAddress, } from "viem";
|
|
26
26
|
import { privateKeyToAccount } from "viem/accounts";
|
|
27
27
|
import { base, baseSepolia } from "viem/chains";
|
|
28
|
-
import { fmt, log, header, Spinner, die, dieOnContract } from "../ui.js";
|
|
28
|
+
import { fmt, log, header, Spinner, die, dieOnContract, requirePrivateKey } from "../ui.js";
|
|
29
29
|
import { withConfig } from "../config.js";
|
|
30
30
|
const CHAINS = { "8453": base, "84532": baseSepolia };
|
|
31
31
|
const ORACLE_ABI = [
|
|
@@ -79,9 +79,7 @@ function txUrl(chain, hash) {
|
|
|
79
79
|
return baseUrl ? `${baseUrl}/tx/${hash}` : undefined;
|
|
80
80
|
}
|
|
81
81
|
function makeClients(cfg, opts) {
|
|
82
|
-
const rawKey = opts.privateKey ?? process.env["PRIVATE_KEY"];
|
|
83
|
-
if (!rawKey)
|
|
84
|
-
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
82
|
+
const rawKey = requirePrivateKey(opts.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
85
83
|
const chain = CHAINS[opts.chain ?? "84532"] ?? baseSepolia;
|
|
86
84
|
const transport = opts.rpc ? http(opts.rpc) : http();
|
|
87
85
|
const account = privateKeyToAccount(rawKey);
|
package/dist/commands/pool.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createPublicClient, createWalletClient, http, isAddress, isHex, } from "viem";
|
|
2
2
|
import { privateKeyToAccount } from "viem/accounts";
|
|
3
3
|
import { base, baseSepolia } from "viem/chains";
|
|
4
|
-
import { fmt, log, header, Spinner, die } from "../ui.js";
|
|
4
|
+
import { fmt, log, header, Spinner, die, requirePrivateKey } from "../ui.js";
|
|
5
5
|
const CHAINS = { "8453": base, "84532": baseSepolia };
|
|
6
6
|
const REGISTRY_ABI = [
|
|
7
7
|
{
|
|
@@ -38,11 +38,7 @@ const REGISTRY_ABI = [
|
|
|
38
38
|
},
|
|
39
39
|
];
|
|
40
40
|
export async function poolPolicySet(opts) {
|
|
41
|
-
const rawKey = opts.privateKey ?? process.env["PRIVATE_KEY"];
|
|
42
|
-
if (!rawKey)
|
|
43
|
-
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
44
|
-
if (!isHex(rawKey) || rawKey.length !== 66)
|
|
45
|
-
die("Invalid private key.");
|
|
41
|
+
const rawKey = requirePrivateKey(opts.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
46
42
|
if (!isAddress(opts.issuer))
|
|
47
43
|
die(`Invalid issuer address: ${opts.issuer}`);
|
|
48
44
|
if (!isAddress(opts.registry))
|
package/dist/commands/proof.js
CHANGED
|
@@ -2,7 +2,7 @@ import { readFileSync } from "fs";
|
|
|
2
2
|
import { createPublicClient, createWalletClient, encodeAbiParameters, http, isAddress, } from "viem";
|
|
3
3
|
import { privateKeyToAccount } from "viem/accounts";
|
|
4
4
|
import { base, baseSepolia } from "viem/chains";
|
|
5
|
-
import { fmt, log, die } from "../ui.js";
|
|
5
|
+
import { fmt, log, die, requirePrivateKey } from "../ui.js";
|
|
6
6
|
const CHAINS = { "8453": base, "84532": baseSepolia };
|
|
7
7
|
const CNF_ISSUER_ABI = [
|
|
8
8
|
{
|
|
@@ -73,9 +73,7 @@ export async function proofRenew(opts) {
|
|
|
73
73
|
await sendProofTx("renew", opts);
|
|
74
74
|
}
|
|
75
75
|
async function sendProofTx(mode, opts) {
|
|
76
|
-
const rawKey = opts.privateKey ?? process.env["PRIVATE_KEY"];
|
|
77
|
-
if (!rawKey)
|
|
78
|
-
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
76
|
+
const rawKey = requirePrivateKey(opts.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
79
77
|
if (!isAddress(opts.issuer))
|
|
80
78
|
die(`Invalid issuer address: ${opts.issuer}`);
|
|
81
79
|
const chain = CHAINS[opts.chain] ?? baseSepolia;
|
package/dist/commands/prove.js
CHANGED
|
@@ -26,7 +26,7 @@ import { base, baseSepolia } from "viem/chains";
|
|
|
26
26
|
// @ts-ignore — no bundled types for this package
|
|
27
27
|
import { IncrementalMerkleTree } from "@zk-kit/incremental-merkle-tree";
|
|
28
28
|
import { poseidon2, poseidon4 } from "poseidon-lite";
|
|
29
|
-
import { fmt, log, header, Spinner, die, dieOnContract } from "../ui.js";
|
|
29
|
+
import { fmt, log, header, Spinner, die, dieOnContract, requirePrivateKey } from "../ui.js";
|
|
30
30
|
import { withConfig } from "../config.js";
|
|
31
31
|
import { COINBASE_SCHEMA_UID } from "../constants.js";
|
|
32
32
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -193,9 +193,7 @@ function encodeProof(proofJson, publicJson) {
|
|
|
193
193
|
// ─── Main export ──────────────────────────────────────────────────────────────
|
|
194
194
|
export async function credentialProve(opts) {
|
|
195
195
|
const cfg = withConfig(opts);
|
|
196
|
-
const rawKey = cfg.privateKey ?? process.env["PRIVATE_KEY"];
|
|
197
|
-
if (!rawKey)
|
|
198
|
-
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
196
|
+
const rawKey = requirePrivateKey(cfg.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
199
197
|
if (!cfg.wallet)
|
|
200
198
|
die("Wallet address required. Use --wallet or set issuer in .ilal.json");
|
|
201
199
|
if (!cfg.issuer)
|
package/dist/commands/session.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createWalletClient, encodeAbiParameters, http, isAddress, isHex, parseAbiParameters, } from "viem";
|
|
2
2
|
import { privateKeyToAccount } from "viem/accounts";
|
|
3
3
|
import { base, baseSepolia } from "viem/chains";
|
|
4
|
-
import { fmt, log, header, die } from "../ui.js";
|
|
4
|
+
import { fmt, log, header, die, requirePrivateKey } from "../ui.js";
|
|
5
5
|
import { withConfig } from "../config.js";
|
|
6
6
|
const CHAINS = {
|
|
7
7
|
"8453": base,
|
|
@@ -30,11 +30,7 @@ const HOOK_DATA_ABI = parseAbiParameters([
|
|
|
30
30
|
export async function sessionSign(opts) {
|
|
31
31
|
const cfg = withConfig({ chain: opts.chain, hook: opts.hook, issuer: opts.issuer });
|
|
32
32
|
// Resolve private key
|
|
33
|
-
const rawKey = opts.privateKey ?? process.env["PRIVATE_KEY"];
|
|
34
|
-
if (!rawKey)
|
|
35
|
-
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
36
|
-
if (!isHex(rawKey) || rawKey.length !== 66)
|
|
37
|
-
die("Invalid private key format (expected 0x + 32 bytes).");
|
|
33
|
+
const rawKey = requirePrivateKey(opts.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
38
34
|
const account = privateKeyToAccount(rawKey);
|
|
39
35
|
const user = (opts.user ?? account.address);
|
|
40
36
|
const pool = opts.pool ?? cfg.poolId;
|
package/dist/commands/swap.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
import { createPublicClient, createWalletClient, decodeAbiParameters, encodeAbiParameters, formatEther, formatUnits, http, isAddress, isHex, parseAbiParameters, parseUnits, } from "viem";
|
|
22
22
|
import { privateKeyToAccount } from "viem/accounts";
|
|
23
23
|
import { base, baseSepolia } from "viem/chains";
|
|
24
|
-
import { fmt, log, header, Spinner, die, dieOnContract } from "../ui.js";
|
|
24
|
+
import { fmt, log, header, Spinner, die, dieOnContract, requirePrivateKey } from "../ui.js";
|
|
25
25
|
import { withConfig } from "../config.js";
|
|
26
26
|
const CHAINS = { "8453": base, "84532": baseSepolia };
|
|
27
27
|
// ─── ABIs ─────────────────────────────────────────────────────────────────────
|
|
@@ -127,9 +127,7 @@ function secondsSince(startMs) {
|
|
|
127
127
|
// ─── Main export ──────────────────────────────────────────────────────────────
|
|
128
128
|
export async function swap(opts) {
|
|
129
129
|
const cfg = withConfig(opts);
|
|
130
|
-
const rawKey = cfg.privateKey ?? process.env["PRIVATE_KEY"];
|
|
131
|
-
if (!rawKey)
|
|
132
|
-
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
130
|
+
const rawKey = requirePrivateKey(cfg.privateKey ?? process.env["PRIVATE_KEY"]);
|
|
133
131
|
if (!cfg.router)
|
|
134
132
|
die("ILALRouter address required. Use --router or set in .ilal.json");
|
|
135
133
|
if (!cfg.hook)
|
|
@@ -211,7 +209,7 @@ export async function swap(opts) {
|
|
|
211
209
|
if (tokenId === 0n) {
|
|
212
210
|
preflightErrors.push(`wallet has no CNF credential; mint one before trading.`);
|
|
213
211
|
if (hasEASPath)
|
|
214
|
-
preflightErrors.push("issuer supports EAS/mock attestation minting: run `ilal credential mint --attestation <uid>`.");
|
|
212
|
+
preflightErrors.push("issuer supports EAS/mock attestation minting: first ask issuer to run `ilal demo attest --wallet <wallet>`, then run `ilal credential mint --attestation <uid>`.");
|
|
215
213
|
else if (hasZKPath)
|
|
216
214
|
preflightErrors.push(`issuer supports ZK minting: run \`ilal credential prove --wallet ${account.address}\`.`);
|
|
217
215
|
else
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ const program = new Command();
|
|
|
19
19
|
program
|
|
20
20
|
.name("ilal")
|
|
21
21
|
.description("ILAL Protocol CLI — Uniswap v4 compliance hook toolkit")
|
|
22
|
-
.version("0.2.
|
|
22
|
+
.version("0.2.10")
|
|
23
23
|
.addHelpText("before", `\n ${fmt.bold(fmt.cyan("◆"))} ${fmt.bold("ILAL Protocol")} ${fmt.gray("Uniswap v4 Compliance Hook")}\n`);
|
|
24
24
|
// ─── init ─────────────────────────────────────────────────────────────────────
|
|
25
25
|
program
|
|
@@ -99,8 +99,8 @@ const credential = program.command("credential").description("Manage compliance
|
|
|
99
99
|
credential
|
|
100
100
|
.command("status <wallet>")
|
|
101
101
|
.description("Check CNF credential status for a wallet")
|
|
102
|
-
.
|
|
103
|
-
.option("-c, --chain <chainId>", "Chain ID (8453=Base, 84532=Base Sepolia)", "
|
|
102
|
+
.option("-i, --issuer <address>", "CNFIssuer contract address (or set in .ilal.json)")
|
|
103
|
+
.option("-c, --chain <chainId>", "Chain ID (8453=Base, 84532=Base Sepolia)", "84532")
|
|
104
104
|
.option("-r, --rpc <url>", "Custom RPC URL")
|
|
105
105
|
.action(async (wallet, opts) => {
|
|
106
106
|
await credentialStatus({ wallet, ...opts }).catch(err);
|
|
@@ -133,8 +133,8 @@ credential
|
|
|
133
133
|
.command("mint")
|
|
134
134
|
.description("Mint a CNF credential using a Coinbase EAS attestation")
|
|
135
135
|
.requiredOption("-a, --attestation <uid>", "EAS attestation UID (0x + 64 hex chars)")
|
|
136
|
-
.
|
|
137
|
-
.option("-c, --chain <chainId>", "Chain ID", "
|
|
136
|
+
.option("-i, --issuer <address>", "CNFIssuer contract address (or set in .ilal.json)")
|
|
137
|
+
.option("-c, --chain <chainId>", "Chain ID", "84532")
|
|
138
138
|
.option("-r, --rpc <url>", "Custom RPC URL")
|
|
139
139
|
.option("-k, --private-key <hex>", "Private key (or set PRIVATE_KEY env var)")
|
|
140
140
|
.option("--simulate", "Verify attestation without sending tx", false)
|
|
@@ -145,8 +145,8 @@ credential
|
|
|
145
145
|
.command("renew")
|
|
146
146
|
.description("Renew an existing CNF credential with a fresh EAS attestation")
|
|
147
147
|
.requiredOption("-a, --attestation <uid>", "EAS attestation UID (0x + 64 hex chars)")
|
|
148
|
-
.
|
|
149
|
-
.option("-c, --chain <chainId>", "Chain ID", "
|
|
148
|
+
.option("-i, --issuer <address>", "CNFIssuer contract address (or set in .ilal.json)")
|
|
149
|
+
.option("-c, --chain <chainId>", "Chain ID", "84532")
|
|
150
150
|
.option("-r, --rpc <url>", "Custom RPC URL")
|
|
151
151
|
.option("-k, --private-key <hex>", "Private key (or set PRIVATE_KEY env var)")
|
|
152
152
|
.option("--simulate", "Verify attestation without sending tx", false)
|
|
@@ -228,7 +228,7 @@ pool
|
|
|
228
228
|
.requiredOption("--tick-lower <int24>", "Lower tick of position")
|
|
229
229
|
.requiredOption("--tick-upper <int24>", "Upper tick of position")
|
|
230
230
|
.requiredOption("--liquidity <uint128>", "Liquidity amount to add (in raw units)")
|
|
231
|
-
.option("--salt <bytes32>", "Position salt for multiple positions at the same range
|
|
231
|
+
.option("--salt <bytes32>", "Position salt for multiple positions at the same range (defaults to user-scoped salt)")
|
|
232
232
|
.option("--pool-id <bytes32>", "Pool ID (or set in .ilal.json)")
|
|
233
233
|
.option("--router <address>", "ILALRouter address (or set in .ilal.json)")
|
|
234
234
|
.option("-H, --hook <address>", "ComplianceHook address (or set in .ilal.json)")
|
|
@@ -250,7 +250,7 @@ pool
|
|
|
250
250
|
.requiredOption("--tick-lower <int24>", "Lower tick of position")
|
|
251
251
|
.requiredOption("--tick-upper <int24>", "Upper tick of position")
|
|
252
252
|
.requiredOption("--liquidity <uint128>", "Liquidity amount to remove (in raw units)")
|
|
253
|
-
.option("--salt <bytes32>", "Position salt
|
|
253
|
+
.option("--salt <bytes32>", "Position salt (defaults to user-scoped salt)")
|
|
254
254
|
.option("--pool-id <bytes32>", "Pool ID (or set in .ilal.json)")
|
|
255
255
|
.option("--router <address>", "ILALRouter address (or set in .ilal.json)")
|
|
256
256
|
.option("-H, --hook <address>", "ComplianceHook address (or set in .ilal.json)")
|
package/dist/ui.d.ts
CHANGED
|
@@ -56,4 +56,5 @@ export declare const log: {
|
|
|
56
56
|
};
|
|
57
57
|
export declare function header(title: string, subtitle?: string): void;
|
|
58
58
|
export declare function die(msg: string): never;
|
|
59
|
+
export declare function requirePrivateKey(rawKey?: string): `0x${string}`;
|
|
59
60
|
export declare function dieOnContract(e: unknown): never;
|
package/dist/ui.js
CHANGED
|
@@ -213,6 +213,19 @@ export function die(msg) {
|
|
|
213
213
|
console.error();
|
|
214
214
|
process.exit(1);
|
|
215
215
|
}
|
|
216
|
+
export function requirePrivateKey(rawKey) {
|
|
217
|
+
const key = rawKey?.trim();
|
|
218
|
+
if (!key) {
|
|
219
|
+
die("Private key required. Use --private-key or set PRIVATE_KEY env var.");
|
|
220
|
+
}
|
|
221
|
+
if (/^[0-9a-fA-F]{64}$/.test(key)) {
|
|
222
|
+
die("Private key must include the 0x prefix. Example: PRIVATE_KEY=0x...");
|
|
223
|
+
}
|
|
224
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(key)) {
|
|
225
|
+
die("Private key must be 32-byte hex and include the 0x prefix. Example: PRIVATE_KEY=0x...");
|
|
226
|
+
}
|
|
227
|
+
return key;
|
|
228
|
+
}
|
|
216
229
|
export function dieOnContract(e) {
|
|
217
230
|
die(parseViemError(e));
|
|
218
231
|
}
|