fangorn-sdk 2026.2.24 → 2026.2.26

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 CHANGED
@@ -10,44 +10,62 @@ Fangorn is a programmable data framework that lets you **register datasources**
10
10
 
11
11
  Fangorn can be deployed on any EVM chain that has a brige to Lit protocol. Currently, contracts are deployed to both Arbitrum Sepolia and Base Sepolia. See the [contracts](#contracts) section for more info.
12
12
 
13
- ## Build
13
+ ## Usage
14
14
 
15
- `pnpm i
15
+ Fangorn is a programmable data framework. It provides tools to register data sources that can be accessed based on owner-defined conditions, like payment.
16
16
 
17
- ### Usage
17
+ ## CLI/Quickstart
18
18
 
19
- Fangorn is a programmable data framework. It provides tools to register data sources that can be accessed based on owner-defined conditions, like payment.
19
+ To install the fangorn-sdk from NPM, run:
20
+
21
+ ```shell
22
+ npm i -g fangorn-sdk
23
+ ```
20
24
 
21
- #### Quickstart
25
+ ### Register a Datasource
22
26
 
23
- ```js
24
- # Coming soon
27
+ First register a datasource
28
+
29
+ ```sh
30
+ fangorn register name-of-your-datasource-agent
25
31
  ```
26
32
 
27
- #### Full Guide
33
+ ### Upload Data
28
34
 
29
- #### Setup
35
+ On upload, data is encrypted under a user-specified **gadget**. For now, the CLI only supports the payment gadget, which is used by specifying the argument `-g "Payment(amount)"`. The minimum amount is `0.000001`.
36
+
37
+ For `-c`, the CLI supports both arbitrumSepolia and baseSepolia.
38
+
39
+ ```sh
40
+ fangorn upload name-of-your-datasource-agent file-to-upload.ext -c arbitrumSepolia -g "Payment(0.0001)"
41
+ ```
42
+
43
+ ### Decrypt and Download
44
+
45
+ ```sh
46
+ fangorn decrypt [owner] [datasourceName] [tag] -c arbitrumSepolia
47
+ ```
48
+
49
+ ## Full Guide
50
+
51
+ ### Build
52
+
53
+ `pnpm i`
54
+
55
+ ### Setup
30
56
 
31
57
  ```js
32
58
  // provide the account, rpcurl, and chain externally
33
59
  // Initalize a wallet client
34
60
  const walletClient = createWalletClient({
35
- account,,
61
+ account,
36
62
  transport: http(rpcUrl),
37
63
  chain,
38
64
  });
39
-
40
65
  // For ArbSep, also supports BaseSepolia (wallet client must match)
41
66
  const config: AppConfig = FangornConfig.ArbitrumSepolia;
42
-
43
- // setup the Lit client (for encryption)
44
- const litClient = await createLitClient({
45
- network: nagaDev,
46
- });
47
67
  // and the encryption service
48
- const encryptionService = new LitEncryptionService(delegateeLitClient, {
49
- chainName: chain,
50
- });
68
+ const encryptionService = new LitEncryptionService(chain);
51
69
 
52
70
  // setup the storage client
53
71
  const pinata = new PinataSDK({
@@ -69,7 +87,7 @@ const fangorn = await Fangorn.init(
69
87
  );
70
88
  ```
71
89
 
72
- ##### Datasource Registration
90
+ ### Datasource Registration
73
91
 
74
92
  Now that you have a Fangorn client, you can create a _datasource_. A datasource is an on-chain asset that stores a commitment to its storage root along with an optional `agentId` field for associating the datasource with an ERC-8004 identity.
75
93
 
@@ -79,7 +97,7 @@ const name = "demo";
79
97
  const id = await this.delegatorFangorn.registerDataSource(name, "");
80
98
  ```
81
99
 
82
- ##### Encryption
100
+ ### Encryption
83
101
 
84
102
  Once a datasource exists, the owner can update its storage root to point it to data. Fangorn leverages Lit protocol for encryption and access control.
85
103
 
@@ -229,7 +247,7 @@ The tests will:
229
247
  To install locally:
230
248
 
231
249
  ```sh
232
- chmod +x update_clci.sh
250
+ chmod +x update_cli.sh
233
251
  ./update_cli.sh
234
252
  ```
235
253
 
@@ -243,8 +261,12 @@ Options:
243
261
  -h, --help display help for command
244
262
 
245
263
  Commands:
264
+ init Configure your Fangorn credentials
246
265
  register [options] <name> Register a new datasource as an agent.
247
266
  upload [options] <name> <files...> Upload file(s) to a data source
267
+ list [options] <name> List contents (index) of a data source
268
+ info [options] <name> Get data source info from contract
269
+ entry [options] <name> <tag> Get info about a specific entry
248
270
  decrypt [options] <owner> <name> <tag> Decrypt a file from a vault
249
271
  help [command] display help for command
250
272
  ```
@@ -1,23 +1,24 @@
1
1
  #!/usr/bin/env node
2
- import getNetwork, { FangornConfig, SupportedNetworks } from "./config.js";
3
- import { Fangorn } from "./fangorn.js";
4
- import { PinataStorage } from "./providers/storage/pinata/index.js";
5
- import { LitEncryptionService } from "./modules/encryption/lit.js";
6
- import { computeTagCommitment, fieldToHex } from "./utils/index.js";
7
- import { PaymentGadget } from "./modules/gadgets/payment.js";
8
- import { agentCardBuilder } from "./builders/a2aCardBuilder.js";
9
- import { Command } from "commander";
10
- import { confirm, intro, isCancel, multiselect, note, outro, select, spinner, text } from "@clack/prompts";
2
+ import { FangornConfig, SupportedNetworks } from "../config.js";
3
+ import { Fangorn } from "../fangorn.js";
4
+ import { PinataStorage } from "../providers/storage/pinata/index.js";
5
+ import { computeTagCommitment, fieldToHex } from "../utils/index.js";
6
+ import { LitEncryptionService } from "../modules/encryption/lit.js";
7
+ import { agentCardBuilder } from "../builders/a2aCardBuilder.js";
8
+ import { getChain, handleCancel, parseGadgetArg, selectChain } from "./index.js";
9
+ import { GADGET_REGISTRY, selectGadget } from "./registry.js";
10
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
11
+ import { basename, extname, join } from "path";
11
12
  import { createWalletClient, http } from "viem";
13
+ import { Command } from "commander";
14
+ import { confirm, intro, multiselect, note, outro, select, spinner, text } from "@clack/prompts";
12
15
  import { privateKeyToAccount } from "viem/accounts";
13
16
  import "dotenv/config";
14
17
  import { PinataSDK } from "pinata";
15
18
  import { SDK } from "agent0-sdk";
16
- import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
17
- import { basename, extname, join } from "path";
18
19
  import { homedir } from "os";
19
20
 
20
- //#region src/cli.ts
21
+ //#region src/cli/cli.ts
21
22
  const CONFIG_DIR = join(homedir(), ".fangorn");
22
23
  const CONFIG_PATH = join(CONFIG_DIR, "config.json");
23
24
  let _config = null;
@@ -78,26 +79,6 @@ async function getFangorn(chain) {
78
79
  _fangorn = await Fangorn.init(walletClient, storage, encryptionService, domain, appConfig);
79
80
  return _fangorn;
80
81
  }
81
- const getChain = (chainStr) => {
82
- return getNetwork(chainStr);
83
- };
84
- const handleCancel = (value) => {
85
- if (isCancel(value)) process.exit(0);
86
- };
87
- const selectChain = async () => {
88
- const chainChoice = await select({
89
- message: "Pick your chain.",
90
- options: [{
91
- value: "arbitrumSepolia",
92
- label: "Arbitrum Sepolia"
93
- }, {
94
- value: "baseSepolia",
95
- label: "Base Sepolia"
96
- }]
97
- });
98
- handleCancel(chainChoice);
99
- return getNetwork(chainChoice.toString());
100
- };
101
82
  const program = new Command();
102
83
  program.name("Fangorn").description("CLI for Fangorn").version("0.0.1");
103
84
  program.command("init").description("Configure your Fangorn credentials").action(async () => {
@@ -395,7 +376,7 @@ program.command("register").description("Register a new datasource as an agent."
395
376
  process.exit(1);
396
377
  }
397
378
  });
398
- program.command("upload").description("Upload file(s) to a data source").argument("<name>", "Data source name").argument("<files...>", "File path(s) to upload").option("-c, --chain <chain>", "The chain to use as the backend (arbitrumSepolia or baseSepolia)").option("-p, --price <price>", "price to access the file").option("--overwrite", "Overwrite existing data source contents").action(async (name, files, options) => {
379
+ program.command("upload").description("Upload file(s) to a data source").argument("<name>", "Data source name").argument("<files...>", "File path(s) to upload").option("-c, --chain <chain>", "The chain to use as the backend (arbitrumSepolia or baseSepolia)").option("-g, --gadget <type(args)>", "Gadget to use (e.g. Payment(0.000001))").option("-o --overwrite", "Overwrite existing data source contents").action(async (name, files, options) => {
399
380
  try {
400
381
  const owner = getAccount().address;
401
382
  const fangorn = await getFangorn(getChain(options.chain));
@@ -412,12 +393,21 @@ program.command("upload").description("Upload file(s) to a data source").argumen
412
393
  };
413
394
  });
414
395
  const cid = await fangorn.upload(name, filedata, async (file) => {
415
- return new PaymentGadget({
416
- commitment: fieldToHex(await computeTagCommitment(owner, name, file.tag, options.price)),
417
- chainName: "arbitrumSepolia",
418
- settlementTrackerContractAddress: "0x7c6ae9eb3398234eb69b2f3acfae69065505ff69",
419
- usdcPrice: options.price
420
- });
396
+ if (options.gadget) {
397
+ const { type, args } = parseGadgetArg(options.gadget);
398
+ const def = GADGET_REGISTRY[type];
399
+ if (!def) throw new Error(`Unknown gadget type: ${type}`);
400
+ const params = {};
401
+ def.argSchema.forEach((key, i) => {
402
+ params[key] = args[i];
403
+ });
404
+ params.commitment = fieldToHex(await computeTagCommitment(owner, name, file.tag, options.price));
405
+ params.chainName = options.chain;
406
+ params.settlementTrackerContractAddress = options.chain === "arbitrumSepolia" ? "0x7c6ae9eb3398234eb69b2f3acfae69065505ff69" : "0x708751829f5f5f584da4142b62cd5cc9235c8a18";
407
+ params.pinataJwt = loadConfig().jwt;
408
+ return def.build(params);
409
+ }
410
+ return selectGadget(owner, name, file.tag, options.price);
421
411
  }, options.overwrite);
422
412
  console.log(`Upload complete! Manifest CID: ${cid}`);
423
413
  process.exit(0);
@@ -476,7 +466,11 @@ program.command("decrypt").description("Decrypt a file from a vault").argument("
476
466
  if (options.output) {
477
467
  writeFileSync(options.output, Buffer.from(decrypted));
478
468
  console.log(`Decrypted file saved to: ${options.output}`);
479
- } else process.stdout.write(Buffer.from(decrypted));
469
+ } else {
470
+ const buf = Buffer.from(decrypted);
471
+ process.stdout.write(atob(buf.toString()));
472
+ process.stdout.write("\n");
473
+ }
480
474
  process.exit(0);
481
475
  } catch (err) {
482
476
  console.error("Failed to decrypt:", err.message);