@sm-lab/merkle 1.2.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,98 @@
1
+ # @sm-lab/merkle
2
+
3
+ Merkle tree builder for Lido SM. One job: **build a tree, pin it to IPFS, print the root +
4
+ CID.** Tree shapes — **addresses** (vetted gate), **strikes** (node-operator violations), and
5
+ **rewards** (cumulative FeeDistributor shares).
6
+
7
+ ```
8
+ input JSON → build StandardMerkleTree → pin to IPFS → print { treeRoot, treeCid }
9
+ ```
10
+
11
+ > Pushing the root/CID on-chain (and resolving deploy addresses) is **not** this tool's job —
12
+ > that belongs to `@sm-lab/receipts`. merkle has no `cast`, no `DEPLOY_JSON_PATH`, no chain access.
13
+
14
+ ## CLI
15
+
16
+ Binary: `sm-merkle` (`npx @sm-lab/merkle …`).
17
+
18
+ ```bash
19
+ sm-merkle 0xABC 0xDEF # inline addresses → addresses (vetted gate) tree (default command)
20
+ sm-merkle addresses --source addresses.json # addresses (vetted gate) tree from file
21
+ sm-merkle addresses --input 0xABC --input 0xDEF # addresses (vetted gate) tree from repeated --input flags
22
+ sm-merkle strikes strikes.json # build strikes tree, pin, print root + CID
23
+ sm-merkle rewards --source rewards.json # build rewards tree from [[noId, shares], ...]
24
+ sm-merkle addresses --source a.json --no-upload # build/print root only, skip pinning
25
+ sm-merkle addresses --source a.json -o out.json # also write { treeRoot, treeCid } to out.json
26
+ sm-merkle help # self-contained cheat sheet
27
+ sm-merkle completion fish | source # shell completion (bash/zsh/fish)
28
+ ```
29
+
30
+ Flags: `--no-upload` (root only, skip IPFS) · `-o, --out <path>` (also write a
31
+ `{ treeRoot, treeCid }` JSON — a handoff seam for `@sm-lab/receipts` / CI) · `--json`
32
+ (machine-readable single-JSON-value output).
33
+
34
+ ## Library
35
+
36
+ ### Low-level (build + pin manually)
37
+
38
+ ```ts
39
+ import { buildAddressesTree, buildStrikesTree, pinJsonToIpfs } from '@sm-lab/merkle';
40
+
41
+ const tree = buildAddressesTree(['0x70997970…', '0x3C44CdD…']);
42
+ tree.root; // deterministic 0x… root
43
+ const cid = await pinJsonToIpfs(tree.dump(), 'merkle-tree-addresses'); // env-switched endpoint
44
+ ```
45
+
46
+ ### High-level TS API
47
+
48
+ `makeAddresses` accepts a resolved `string[]` of addresses, builds the tree, pins the dump to IPFS
49
+ (using the env-configured endpoint — local `@sm-lab/ipfs` by default), and returns
50
+ `{ treeRoot, treeCid }`. No filesystem access — pass the address list directly.
51
+
52
+ ```ts
53
+ import { makeAddresses } from '@sm-lab/merkle';
54
+
55
+ // Build + pin in one call. Addresses must already be resolved (inline list or pre-read file).
56
+ const { treeRoot, treeCid } = await makeAddresses(
57
+ ['0x70997970C51812dc3A010C7d01b50e0d17dc79C8', '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC'],
58
+ // options are optional:
59
+ // { noUpload: true } → skip IPFS, return only treeRoot
60
+ // { configPath: 'out.json' } → also write { treeRoot, treeCid } to disk
61
+ );
62
+
63
+ console.log('tree root:', treeRoot);
64
+ console.log('IPFS CID: ', treeCid);
65
+ ```
66
+
67
+ Tree leaf encodings: addresses (vetted gate) `["address"]` · strikes `["uint256", "string", "uint256[]"]` · rewards `["uint256", "uint256"]`.
68
+
69
+ ## Environment
70
+
71
+ | Var | Purpose |
72
+ | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
73
+ | `IPFS_API_URL` | Pinning endpoint. **Unset → local `@sm-lab/ipfs`** (`http://127.0.0.1:5001`). Pinata is used only when `PINATA_*` creds are set (and `IPFS_API_URL` is unset). Set explicitly to override both defaults. |
74
+ | `PINATA_API_KEY` / `PINATA_API_SECRET` | Pinata credentials (`pinata_api_key` / `pinata_secret_api_key` headers). When set, Pinata is preferred over the local default. |
75
+ | `PINATA_JWT` | Alternative to key/secret (`Authorization: Bearer …`). When set, Pinata is preferred over the local default. |
76
+
77
+ Copy `.env` from your own values; never commit secrets (`.env*` is gitignored).
78
+
79
+ ### Why a custom IPFS client, not `@pinata/sdk`
80
+
81
+ `@pinata/sdk` v2 hardcodes `baseUrl = 'https://api.pinata.cloud'` with no host override, so it
82
+ can't target the local mock. `ipfs.ts` is a thin `fetch` client that POSTs the **same**
83
+ `/pinning/pinJSONToIPFS` envelope (`{ pinataContent, pinataMetadata }`), with the base URL
84
+ resolved from `IPFS_API_URL` (→ env → real-Pinata default). Real Pinata works unchanged.
85
+
86
+ ## Build
87
+
88
+ tsdown (ESM, bundled) via the shared `@sm-lab/config` preset:
89
+
90
+ ```ts
91
+ // tsdown.config.ts
92
+ import { libConfig } from '@sm-lab/config/tsdown';
93
+ export default libConfig({
94
+ entry: { index: 'src/index.ts', cli: 'src/cli/index.ts' },
95
+ format: ['esm'],
96
+ platform: 'node',
97
+ });
98
+ ```
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };