fangorn-sdk 0.0.0 → 0.0.2

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/lib/fangorn.d.ts CHANGED
@@ -28,7 +28,7 @@ declare class Fangorn {
28
28
  private walletClient;
29
29
  private pinata;
30
30
  private pendingEntries;
31
- constructor(chainName: string, litActionCid: string, circuit: CompiledCircuit, litClient: any, zkGate: any, walletClient: any, pinata: PinataSDK);
31
+ constructor(chainName: string, litActionCid: string, circuit: CompiledCircuit, litClient: any, zkGate: any, walletClient: any, pinata: PinataSDK, config: AppConfig);
32
32
  static init(account: Account | Address, jwt: string, gateway: string, config?: AppConfig | undefined): Promise<Fangorn>;
33
33
  createVault(name: string, password: string): Promise<Hex>;
34
34
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"fangorn.d.ts","names":[],"sources":["../src/fangorn.ts"],"sourcesContent":[],"mappings":";;;;;;;UAwCiB,SAAA;;EAAA,cAAS,EAAA,MAAA;EAeT,qBAAa,EATN,GASM;EAejB,KAAA,EAtBL,KAsBY;EAqBT,SAAA,EAAA,MAAA;EAID,MAAA,EAAA,MAAA;;AAgBW,kBAxDJ,aAAA,CAwDI;EAGV,MAAA,OAAA,EAzDY,SAyDZ;;;;;AAkFY,cA9HV,OAAA,CA8HU;EAAe,QAAA,SAAA;EAyFiC,QAAA,SAAA;EAzFF,QAAA,YAAA;EA4B1D,QAAA,OAAA;EACH,QAAA,MAAA;EAC+B,QAAA,YAAA;EAAnC,QAAA,MAAA;EA2DwB,QAAA,cAAA;EAA2C,WAAA,CAAA,SAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,OAAA,EAlM5D,eAkM4D,EAAA,SAAA,EAAA,GAAA,EAAA,MAAA,EAAA,GAAA,EAAA,YAAA,EAAA,GAAA,EAAA,MAAA,EA9L7D,SA8L6D;EAArC,OAAA,IAAA,CAAA,OAAA,EA9KvB,OA8KuB,GA9Kb,OA8Ka,EAAA,GAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EA3KvB,SA2KuB,GAAA,SAAA,CAAA,EA3KF,OA2KE,CA3KF,OA2KE,CAAA;EAiDE,WAAA,CAAA,IAAA,EAAA,MAAA,EAAA,QAAA,EAAA,MAAA,CAAA,EA7JgB,OA6JhB,CA7JwB,GA6JxB,CAAA;EAuBzB;;;;;;;EAmI2B,MAAA,CAAA,OAAA,EApSf,GAoSe,EAAA,QAAA,EApSA,QAoSA,EAAA,EAAA,SAAA,CAAA,EAAA,OAAA,CAAA,EApS+B,OAoS/B,CAAA;IAKY,WAAA,EAAA,MAAA;IAAR,IAAA,EAhN6B,GAgN7B;EAAO,CAAA,CAAA;;;;;mBA7QtC,WACH,WACJ;;gBAAmC;;;;;;;;;;;;uBA2DX,MAAM;;UAAqC;;;;;kCAiDnC;;;;;;;;uBAuBzB,qCAGP,QAAQ,WAAW;;mBAyHQ;oBAOC,MAAM,QAAQ;8BAKJ,QAAQ"}
1
+ {"version":3,"file":"fangorn.d.ts","names":[],"sources":["../src/fangorn.ts"],"sourcesContent":[],"mappings":";;;;;;;UAyCiB,SAAA;;EAAA,cAAS,EAAA,MAAA;EAeT,qBAAa,EATN,GASM;EAejB,KAAA,EAtBL,KAsBY;EAqBT,SAAA,EAAA,MAAA;EAID,MAAA,EAAA,MAAA;;AAaC,kBArDM,aAAA,CAqDN;EAAU,MAAA,OAAA,EAnDE,SAmDF;;;;;AA4E+B,cAlHvC,OAAA,CAkHuC;EAmB7B,QAAA,SAAA;EAAe,QAAA,SAAA;EAyFiC,QAAA,YAAA;EAzFF,QAAA,OAAA;EA4B1D,QAAA,MAAA;EACH,QAAA,YAAA;EAC+B,QAAA,MAAA;EAAnC,QAAA,cAAA;EA2DwB,WAAA,CAAA,SAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,OAAA,EAzMjB,eAyMiB,EAAA,SAAA,EAAA,GAAA,EAAA,MAAA,EAAA,GAAA,EAAA,YAAA,EAAA,GAAA,EAAA,MAAA,EArMlB,SAqMkB,EAAA,MAAA,EApMlB,SAoMkB;EAA2C,OAAA,IAAA,CAAA,OAAA,EAxL5D,OAwL4D,GAxLlD,OAwLkD,EAAA,GAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EArL5D,SAqL4D,GAAA,SAAA,CAAA,EArLvC,OAqLuC,CArLvC,OAqLuC,CAAA;EAArC,WAAA,CAAA,IAAA,EAAA,MAAA,EAAA,QAAA,EAAA,MAAA,CAAA,EA5GkB,OA4GlB,CA5G0B,GA4G1B,CAAA;EAiDE;;;;;;;EA0JU,MAAA,CAAA,OAAA,EApSvB,GAoSuB,EAAA,QAAA,EApSR,QAoSQ,EAAA,EAAA,SAAA,CAAA,EAAA,OAAA,CAAA,EApSuB,OAoSvB,CAAA;IAAR,WAAA,EAAA,MAAA;IAKY,IAAA,EAhNqB,GAgNrB;EAAR,CAAA,CAAA;EAAO;;;;mBA7QtC,WACH,WACJ;;gBAAmC;;;;;;;;;;;;uBA2DX,MAAM;;UAAqC;;;;;kCAiDnC;;;;;;;;uBAuBzB,qCAGP,QAAQ,WAAW;;mBAyHQ;oBAOC,MAAM,QAAQ;8BAKJ,QAAQ"}
package/lib/fangorn.js CHANGED
@@ -37,13 +37,14 @@ var Fangorn = class Fangorn {
37
37
  walletClient;
38
38
  pinata;
39
39
  pendingEntries = /* @__PURE__ */ new Map();
40
- constructor(chainName, litActionCid, circuit, litClient, zkGate, walletClient, pinata) {
40
+ constructor(chainName, litActionCid, circuit, litClient, zkGate, walletClient, pinata, config) {
41
41
  this.litClient = litClient;
42
42
  this.zkGate = zkGate;
43
43
  this.walletClient = walletClient;
44
44
  this.pinata = pinata;
45
45
  this.litActionCid = litActionCid;
46
46
  this.circuit = circuit;
47
+ this.chainName = chainName;
47
48
  }
48
49
  static async init(account, jwt, gateway, config) {
49
50
  const resolvedConfig = config || FangornConfig.Testnet;
@@ -62,7 +63,7 @@ var Fangorn = class Fangorn {
62
63
  transport: custom(window.ethereum),
63
64
  chain
64
65
  });
65
- await WalletClientAuthenticator.authenticate(walletClient);
66
+ await WalletClientAuthenticator.authenticate(walletClient, "Please sign in to enable LIT functionality.", { domain: "https://vault-demo.fangorn.network" });
66
67
  const litClient = await createLitClient({ network: nagaDev });
67
68
  let zkGateClient = new ZKGate(resolvedConfig.zkGateContractAddress, publicClient, walletClient);
68
69
  const pinata = new PinataSDK({
@@ -70,7 +71,7 @@ var Fangorn = class Fangorn {
70
71
  pinataGateway: gateway
71
72
  });
72
73
  const compiledCircuit = (await pinata.gateways.public.get(resolvedConfig.circuitJsonCid)).data;
73
- return new Fangorn(chainName, resolvedConfig.litActionCid, compiledCircuit, litClient, zkGateClient, walletClient, pinata);
74
+ return new Fangorn(chainName, resolvedConfig.litActionCid, compiledCircuit, litClient, zkGateClient, walletClient, pinata, resolvedConfig);
74
75
  }
75
76
  async createVault(name, password) {
76
77
  let passwordHash = hashPassword(password);
@@ -200,23 +201,23 @@ var Fangorn = class Fangorn {
200
201
  * @returns
201
202
  */
202
203
  async decryptFile(vaultId, tag, password) {
203
- let authManager;
204
- if (typeof window === "undefined") authManager = createAuthManager({ storage: storagePlugins.localStorageNode({
204
+ const isWindowUndefined = typeof window === "undefined";
205
+ const account = isWindowUndefined ? this.walletClient.account : this.walletClient;
206
+ const authManager = isWindowUndefined ? createAuthManager({ storage: storagePlugins.localStorageNode({
205
207
  appName: "fangorn",
206
208
  networkName: nagaDev.getNetworkName(),
207
209
  storagePath: "./lit-auth-storage"
208
- }) });
209
- else authManager = createAuthManager({ storage: storagePlugins.localStorage({
210
+ }) }) : createAuthManager({ storage: storagePlugins.localStorage({
210
211
  appName: "fangorn",
211
212
  networkName: nagaDev.getNetworkName()
212
213
  }) });
213
214
  const litClient = this.litClient;
214
215
  const authContext = await authManager.createEoaAuthContext({
215
216
  litClient,
216
- config: { account: this.walletClient.account },
217
+ config: { account },
217
218
  authConfig: {
218
- domain: "localhost",
219
- statement: "Decrypt test data",
219
+ domain: "https://vault-demo.fangorn.network",
220
+ statement: "Please re-authenticate to enable LIT functionality. ",
220
221
  expiration: new Date(Date.now() + 1e3 * 60 * 60 * 24).toISOString(),
221
222
  resources: [["access-control-condition-decryption", "*"], ["lit-action-execution", "*"]]
222
223
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fangorn.js","names":["manifest: VaultManifest","proofHex: Hex","address: Address"],"sources":["../src/fangorn.ts"],"sourcesContent":["import { createLitClient } from \"@lit-protocol/lit-client\";\nimport { createAccBuilder } from \"@lit-protocol/access-control-conditions\";\nimport { nagaDev } from \"@lit-protocol/networks\";\nimport {\n\tAccount,\n\tAddress,\n\tChain,\n\tcreatePublicClient,\n\tcreateWalletClient,\n\tcustom,\n\tgetAddress,\n\tHex,\n\thttp,\n\ttoHex,\n} from \"viem\";\nimport { baseSepolia, filecoin } from \"viem/chains\";\nimport { Vault, ZKGate } from \"./interface/zkGate.js\";\nimport { hashPassword } from \"./utils/index.js\";\nimport { buildCircuitInputs, computeTagCommitment } from \"./crypto/proof.js\";\nimport {\n\tbuildTreeFromLeaves,\n\tfieldToHex,\n\thexToField,\n} from \"./crypto/merkle.js\";\nimport {\n\tFiledata,\n\tPendingEntry,\n\tVaultEntry,\n\tVaultManifest,\n} from \"./types/types.js\";\nimport { PinataSDK } from \"pinata\";\nimport { Barretenberg, UltraHonkBackend } from \"@aztec/bb.js\";\nimport { CompiledCircuit, Noir } from \"@noir-lang/noir_js\";\nimport { decryptData, encryptData } from \"./crypto/encryption.js\";\nimport {\n\tcreateAuthManager,\n\tstoragePlugins,\n\tWalletClientAuthenticator,\n} from \"@lit-protocol/auth\";\n\nexport interface AppConfig {\n\t// The CID pointing to the expected LIT action\n\tlitActionCid: string;\n\t// The CID pointing to the compiled circuit json\n\tcircuitJsonCid: string;\n\t// The deployed zkGate contract address\n\tzkGateContractAddress: Hex;\n\t// The chain we are deploying to\n\tchain: Chain;\n\t// The name of the chain for LIT action execution (does not always match what is defined by viem)\n\tchainName: string;\n\t// The public rpc address of the chain we are connecting to\n\trpcUrl: string;\n}\n\nexport namespace FangornConfig {\n\t// A testnet config for cotnracts deployed on Base Sepolia\n\texport const Testnet: AppConfig = {\n\t\tlitActionCid: \"QmcDkeo7YnJbuyYnXfxcnB65UCkjFhLDG5qa3hknMmrDmQ\",\n\t\tcircuitJsonCid: \"QmXw1rWUC2Kw52Qi55sfW3bCR7jheCDfSUgVRwvsP8ZZPE\",\n\t\tzkGateContractAddress: \"0x062da4924251c7ed392afc01f57d7ea2c255dc81\",\n\t\tchain: baseSepolia,\n\t\tchainName: \"baseSepolia\",\n\t\trpcUrl: \"https://base-sepolia-public.nodies.app\",\n\t};\n}\n\n/**\n * Fangorn class\n */\nexport class Fangorn {\n\t// The name (for LIT) of the chain we are using\n\tprivate chainName: string;\n\t// The LIT client for interacting with the LIT network\n\tprivate litClient: any;\n\t// The CID of the lit action in storage\n\tprivate litActionCid: string;\n\t// The complied noir circuit (e.g. circuit.json)\n\tprivate circuit: CompiledCircuit;\n\t// The ZKGate Contract instance\n\tprivate zkGate: any;\n\t// The wallet client for signing txs\n\tprivate walletClient: any;\n\t// The storage layer (todo: make this into a genericc storage adapter)\n\tprivate pinata: PinataSDK;\n\t// in-mem state for building manifests\n\tprivate pendingEntries: Map<string, PendingEntry> = new Map();\n\n\tconstructor(\n\t\tchainName: string,\n\t\tlitActionCid: string,\n\t\tcircuit: CompiledCircuit,\n\t\tlitClient: any,\n\t\tzkGate: any,\n\t\twalletClient: any,\n\t\tpinata: PinataSDK,\n\t) {\n\t\tthis.litClient = litClient;\n\n\t\tthis.zkGate = zkGate;\n\n\t\tthis.walletClient = walletClient;\n\n\t\tthis.pinata = pinata;\n\n\t\tthis.litActionCid = litActionCid;\n\n\t\tthis.circuit = circuit;\n\t}\n\n\tpublic static async init(\n\t\taccount: Account | Address,\n\t\tjwt: string,\n\t\tgateway: string,\n\t\tconfig?: AppConfig | undefined,\n\t) {\n\t\tconst resolvedConfig = config || FangornConfig.Testnet;\n\t\tconst rpcUrl = resolvedConfig.rpcUrl;\n\t\tconst chain = resolvedConfig.chain;\n\t\tconst chainName = resolvedConfig.chainName;\n\n\t\tconst publicClient = createPublicClient({ transport: http(rpcUrl) });\n\t\tlet walletClient;\n\n\t\tif (typeof window === \"undefined\") {\n\t\t\twalletClient = createWalletClient({\n\t\t\t\taccount,\n\t\t\t\ttransport: http(rpcUrl),\n\t\t\t\tchain,\n\t\t\t});\n\t\t} else {\n\t\t\twalletClient = createWalletClient({\n\t\t\t\taccount: getAddress(account as Address),\n\t\t\t\ttransport: custom(window.ethereum),\n\t\t\t\tchain,\n\t\t\t});\n\t\t}\n\n\t\tawait WalletClientAuthenticator.authenticate(walletClient);\n\t\t// client to interact with LIT proto\n\t\tconst litClient = await createLitClient({\n\t\t\t// @ts-expect-error - TODO: fix this\n\t\t\tnetwork: nagaDev,\n\t\t});\n\n\t\t// interacts with the zk-gate contract\n\t\tlet zkGateClient = new ZKGate(\n\t\t\tresolvedConfig.zkGateContractAddress,\n\t\t\tpublicClient,\n\t\t\twalletClient,\n\t\t);\n\n\t\t// storage via Pinata\n\t\tconst pinata = new PinataSDK({\n\t\t\tpinataJwt: jwt,\n\t\t\tpinataGateway: gateway,\n\t\t});\n\n\t\t// read the circuit from ipfs\n\t\t// TODO: assumes the circuit exists, no error handling here\n\t\tconst circuitResponse = await pinata.gateways.public.get(\n\t\t\tresolvedConfig.circuitJsonCid,\n\t\t);\n\t\tconst compiledCircuit = circuitResponse.data as unknown as CompiledCircuit;\n\n\t\treturn new Fangorn(\n\t\t\tchainName,\n\t\t\tresolvedConfig.litActionCid,\n\t\t\tcompiledCircuit,\n\t\t\tlitClient,\n\t\t\tzkGateClient,\n\t\t\twalletClient,\n\t\t\tpinata,\n\t\t);\n\t}\n\n\t// TODO: how to ensure password is zeroized?\n\tasync createVault(name: string, password: string): Promise<Hex> {\n\t\tlet passwordHash = hashPassword(password);\n\t\tconst fee = await this.zkGate.getVaultCreationFee();\n\t\tconst { hash: createHash, vaultId } = await this.zkGate.createVault(\n\t\t\tname,\n\t\t\tpasswordHash,\n\t\t\tfee,\n\t\t);\n\t\tawait this.zkGate.waitForTransaction(createHash);\n\t\treturn vaultId;\n\t}\n\n\t/**\n\t * Upload data to an existing vault\n\t * @param vaultId The id of the vault being modified\n\t * @param filedata The file data to insert\n\t * @param overwrite If true, then overwrite the existing vault with new files\n\t * @returns The new manifest CID and Merkle root\n\t */\n\tasync upload(vaultId: Hex, filedata: Filedata[], overwrite?: boolean) {\n\t\t// check if manifest exists or not\n\t\t// load existing manifest\n\t\tconst vault = await this.zkGate.getVault(vaultId);\n\t\t// if the manifest exists and we don't want to overwrite\n\t\tif (vault.manifestCid && !overwrite) {\n\t\t\tconst oldManifest = await this.fetchManifest(vault.manifestCid);\n\t\t\tawait this.loadManifest(oldManifest);\n\t\t\t// try to unpin old manifest\n\t\t\ttry {\n\t\t\t\tawait this.pinata.files.public.delete([vault.manifestCid]);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.warn(\"Failed to unpin old manifest:\", e);\n\t\t\t}\n\t\t}\n\n\t\t// add files\n\t\tfor (let file of filedata) {\n\t\t\tawait this.addFile(vaultId, file);\n\t\t}\n\t\treturn await this.commitVault(vaultId);\n\t}\n\n\t/**\n\t * Encrypts data (with LIT) and uploads ciphertext to IPFS.\n\t * Does NOT update the vault!! You must call commitVault() after adding all files.\n\t */\n\tasync addFile(\n\t\tvaultId: Hex,\n\t\tfile: Filedata,\n\t): Promise<{ cid: string; commitment: Hex }> {\n\t\t// compute commitment to (vaultId, tag)\n\t\tconst tag = file.tag;\n\t\tconst leaf = await computeTagCommitment(vaultId, tag);\n\t\tconst commitmentHex = fieldToHex(leaf);\n\n\t\t// encrypt the actual file contents using AES-GCM locally\n\t\tconst { encryptedData, keyMaterial } = await encryptData(file.data);\n\n\t\t// build ACC\n\t\tconst acc = createAccBuilder()\n\t\t\t.requireLitAction(\n\t\t\t\tthis.litActionCid,\n\t\t\t\t\"go\",\n\t\t\t\t[this.zkGate.getContractAddress(), vaultId, commitmentHex],\n\t\t\t\t\"true\",\n\t\t\t)\n\t\t\t.build();\n\n\t\t// encrypt THE KEY with LIT protocol\n\t\tconst keyEncryptedData = await this.litClient.encrypt({\n\t\t\tdataToEncrypt: keyMaterial,\n\t\t\tunifiedAccessControlConditions: acc,\n\t\t\tchain: this.chainName,\n\t\t});\n\n\t\t// upload ciphertext (pin)\n\t\tconst upload = await this.pinata.upload.public.json(\n\t\t\t{ encryptedData, keyEncryptedData, acc },\n\t\t\t{ metadata: { name: tag } },\n\t\t);\n\n\t\t// stage the entry (not committed yet)\n\t\tthis.pendingEntries.set(tag, {\n\t\t\ttag,\n\t\t\tcid: upload.cid,\n\t\t\tleaf,\n\t\t\tcommitment: commitmentHex,\n\t\t\tacc,\n\t\t\textension: file.extension,\n\t\t\tfileType: file.fileType,\n\t\t});\n\n\t\treturn { cid: upload.cid, commitment: commitmentHex };\n\t}\n\n\t/**\n\t * Removes a file from staging (call before committing)\n\t * @param tag The tag of the file\n\t * @returns bool\n\t */\n\tremoveFile(tag: string): boolean {\n\t\treturn this.pendingEntries.delete(tag);\n\t}\n\n\t/**\n\t * Builds manifest from all staged files and updates the vault on-chain.\n\t * Call this *after* adding all files with addFile().\n\t */\n\tasync commitVault(vaultId: Hex): Promise<{ manifestCid: string; root: Hex }> {\n\t\tif (this.pendingEntries.size === 0) {\n\t\t\tthrow new Error(\"No files to commit\");\n\t\t}\n\n\t\t// build Merkle tree\n\t\tconst entries = Array.from(this.pendingEntries.values());\n\t\tconst leaves = entries.map((e) => e.leaf);\n\t\tconst { root, layers } = await buildTreeFromLeaves(leaves);\n\t\tconst rootHex = fieldToHex(root);\n\n\t\t// construct new manifest\n\t\tconst manifest: VaultManifest = {\n\t\t\tversion: 1,\n\t\t\tposeidon_root: rootHex,\n\t\t\tentries: entries.map((e, i) => ({\n\t\t\t\ttag: e.tag,\n\t\t\t\tcid: e.cid,\n\t\t\t\tindex: i,\n\t\t\t\tleaf: fieldToHex(e.leaf),\n\t\t\t\tcommitment: e.commitment,\n\t\t\t\textension: e.extension,\n\t\t\t\tfileType: e.fileType,\n\t\t\t})),\n\t\t\ttree: layers.map((layer) => layer.map(fieldToHex)),\n\t\t};\n\n\t\t// pin the manifest\n\t\tconst manifestUpload = await this.pinata.upload.public.json(manifest, {\n\t\t\tmetadata: { name: `manifest-${vaultId}` },\n\t\t});\n\n\t\t// update contract\n\t\tconst hash = await this.zkGate.updateVault(\n\t\t\tvaultId,\n\t\t\trootHex,\n\t\t\tmanifestUpload.cid,\n\t\t);\n\t\tawait this.zkGate.waitForTransaction(hash);\n\n\t\t// clear pending entries\n\t\tthis.pendingEntries.clear();\n\n\t\treturn { manifestCid: manifestUpload.cid, root: rootHex };\n\t}\n\n\t/**\n\t * Loads existing manifest\n\t */\n\tasync loadManifest(oldManifest: any) {\n\t\t// load existing entries into pending\n\t\tfor (const entry of oldManifest.entries) {\n\t\t\tthis.pendingEntries.set(entry.tag, {\n\t\t\t\ttag: entry.tag,\n\t\t\t\tcid: entry.cid,\n\t\t\t\tleaf: hexToField(entry.leaf),\n\t\t\t\tcommitment: entry.commitment as Hex,\n\t\t\t\tacc: null,\n\t\t\t\textension: entry.extension,\n\t\t\t\tfileType: entry.fileType,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Attempt to decrypt data identified with a given tag within the given vault\n\t * @param vaultId\n\t * @param tag\n\t * @param password\n\t * @returns\n\t */\n\tasync decryptFile(\n\t\tvaultId: Hex,\n\t\ttag: string,\n\t\tpassword: string,\n\t): Promise<Uint8Array<ArrayBufferLike>> {\n\t\t// load the auth context\n\t\tlet authManager;\n\t\tif (typeof window === \"undefined\") {\n\t\t\tauthManager = createAuthManager({\n\t\t\t\tstorage: storagePlugins.localStorageNode({\n\t\t\t\t\tappName: \"fangorn\",\n\t\t\t\t\tnetworkName: nagaDev.getNetworkName(),\n\t\t\t\t\tstoragePath: \"./lit-auth-storage\",\n\t\t\t\t}),\n\t\t\t});\n\t\t} else {\n\t\t\tauthManager = createAuthManager({\n\t\t\t\tstorage: storagePlugins.localStorage({\n\t\t\t\t\tappName: \"fangorn\",\n\t\t\t\t\tnetworkName: nagaDev.getNetworkName(),\n\t\t\t\t}),\n\t\t\t});\n\t\t}\n\n\t\tconst litClient = this.litClient;\n\n\t\tconst authContext = await authManager.createEoaAuthContext({\n\t\t\tlitClient,\n\t\t\tconfig: {\n\t\t\t\taccount: this.walletClient.account,\n\t\t\t},\n\t\t\tauthConfig: {\n\t\t\t\tdomain: \"localhost\", // TODO: do we need to update this?\n\t\t\t\tstatement: \"Decrypt test data\", // Do we need this?\n\t\t\t\t// is this the right duration for expiry?\n\t\t\t\texpiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(),\n\t\t\t\t// Are resources too open?\n\t\t\t\tresources: [\n\t\t\t\t\t[\"access-control-condition-decryption\", \"*\"],\n\t\t\t\t\t[\"lit-action-execution\", \"*\"],\n\t\t\t\t],\n\t\t\t},\n\t\t});\n\n\t\t// fetch manifest from pinata\n\t\tconst vault = await this.zkGate.getVault(vaultId);\n\t\tconst manifest = await this.fetchManifest(vault.manifestCid);\n\n\t\t// try to find entry\n\t\tconst entry = manifest.entries.find((e) => e.tag === tag);\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Entry not found: ${tag}`);\n\t\t}\n\n\t\t// check if already have access (do not need to reverify)\n\t\tconst userAddress = this.walletClient.account.address;\n\t\tconst hasAccess = await this.zkGate.checkCIDAccess(\n\t\t\tvaultId,\n\t\t\tentry.commitment as Hex,\n\t\t\tuserAddress,\n\t\t);\n\n\t\t// we don't need to request access if we already have it\n\t\tif (!hasAccess) {\n\t\t\tawait this.proveAccess(vaultId, password, entry, manifest);\n\t\t}\n\n\t\t// fetch ciphertext\n\t\tconst response = await this.pinata.gateways.public.get(entry.cid);\n\t\tconst { encryptedData, keyEncryptedData, acc } = response.data as any;\n\n\t\t// request decryption\n\t\tconst decryptedKey = await this.litClient.decrypt({\n\t\t\tciphertext: keyEncryptedData.ciphertext,\n\t\t\tdataToEncryptHash: keyEncryptedData.dataToEncryptHash,\n\t\t\tunifiedAccessControlConditions: acc,\n\t\t\tauthContext,\n\t\t\tchain: this.chainName,\n\t\t});\n\n\t\t// recover the symmetric key\n\t\tconst key = decryptedKey.decryptedData;\n\t\t// actually decrypt the data with the recovered key\n\t\tconst decryptedFile = await decryptData(encryptedData, key);\n\n\t\treturn decryptedFile;\n\t}\n\n\t// proof gen\n\tprivate async proveAccess(\n\t\tvaultId: Hex,\n\t\tpassword: string,\n\t\tentry: VaultEntry,\n\t\tmanifest: VaultManifest,\n\t): Promise<void> {\n\t\tconst userAddress = this.walletClient.account.address;\n\n\t\t// build circuit inputs\n\t\tconst { inputs, nullifier, cidCommitment } = await buildCircuitInputs(\n\t\t\tpassword,\n\t\t\tentry,\n\t\t\tuserAddress,\n\t\t\tvaultId,\n\t\t\tmanifest,\n\t\t);\n\n\t\tconst api = await Barretenberg.new({ threads: 1 });\n\t\tconst backend = new UltraHonkBackend(this.circuit.bytecode, api);\n\t\tconst noir = new Noir(this.circuit);\n\t\tconst { witness } = await noir.execute(inputs);\n\t\tconst proofResult = await backend.generateProof(witness, {\n\t\t\tverifierTarget: \"evm\",\n\t\t});\n\n\t\tconst proofHex: Hex = toHex(proofResult.proof);\n\t\t// submit onchain\n\t\tconst hash = await this.zkGate.submitProof(\n\t\t\tvaultId,\n\t\t\tcidCommitment,\n\t\t\tnullifier,\n\t\t\tproofHex,\n\t\t);\n\t\tawait this.zkGate.waitForTransaction(hash);\n\t}\n\n\tpublic async getUserVaults(): Promise<string[]> {\n\t\tconst address: Address = this.walletClient.account.address;\n\t\tconst vaults = await this.zkGate.getOwnedVaults(address);\n\n\t\treturn vaults;\n\t}\n\n\tpublic async getVault(vaultId: Hex): Promise<Vault> {\n\t\tconst vault: Vault = await this.zkGate.getVault(vaultId);\n\t\treturn vault;\n\t}\n\n\tpublic async fetchManifest(cid: string): Promise<VaultManifest> {\n\t\tconst response = await this.pinata.gateways.public.get(cid);\n\t\treturn response.data as unknown as VaultManifest;\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fangorn.js","names":["manifest: VaultManifest","proofHex: Hex","address: Address"],"sources":["../src/fangorn.ts"],"sourcesContent":["import { createLitClient } from \"@lit-protocol/lit-client\";\nimport { createAccBuilder } from \"@lit-protocol/access-control-conditions\";\nimport { nagaDev } from \"@lit-protocol/networks\";\nimport {\n\tAccount,\n\tAddress,\n\tChain,\n\tcreatePublicClient,\n\tcreateWalletClient,\n\tcustom,\n\tgetAddress,\n\tHex,\n\thttp,\n\ttoHex,\n} from \"viem\";\nimport { baseSepolia, filecoin } from \"viem/chains\";\nimport { Vault, ZKGate } from \"./interface/zkGate.js\";\nimport { hashPassword } from \"./utils/index.js\";\nimport { buildCircuitInputs, computeTagCommitment } from \"./crypto/proof.js\";\nimport {\n\tbuildTreeFromLeaves,\n\tfieldToHex,\n\thexToField,\n} from \"./crypto/merkle.js\";\nimport {\n\tFiledata,\n\tPendingEntry,\n\tVaultEntry,\n\tVaultManifest,\n} from \"./types/types.js\";\nimport { PinataSDK } from \"pinata\";\nimport { Barretenberg, UltraHonkBackend } from \"@aztec/bb.js\";\nimport { CompiledCircuit, Noir } from \"@noir-lang/noir_js\";\nimport { decryptData, encryptData } from \"./crypto/encryption.js\";\nimport {\n\tcreateAuthManager,\n\tstoragePlugins,\n\tWalletClientAuthenticator,\n} from \"@lit-protocol/auth\";\nimport { WalletClientAuthenticateOverrides } from \"@lit-protocol/auth/src/lib/authenticators/WalletClientAuthenticator.js\";\n\nexport interface AppConfig {\n\t// The CID pointing to the expected LIT action\n\tlitActionCid: string;\n\t// The CID pointing to the compiled circuit json\n\tcircuitJsonCid: string;\n\t// The deployed zkGate contract address\n\tzkGateContractAddress: Hex;\n\t// The chain we are deploying to\n\tchain: Chain;\n\t// The name of the chain for LIT action execution (does not always match what is defined by viem)\n\tchainName: string;\n\t// The public rpc address of the chain we are connecting to\n\trpcUrl: string;\n}\n\nexport namespace FangornConfig {\n\t// A testnet config for cotnracts deployed on Base Sepolia\n\texport const Testnet: AppConfig = {\n\t\tlitActionCid: \"QmcDkeo7YnJbuyYnXfxcnB65UCkjFhLDG5qa3hknMmrDmQ\",\n\t\tcircuitJsonCid: \"QmXw1rWUC2Kw52Qi55sfW3bCR7jheCDfSUgVRwvsP8ZZPE\",\n\t\tzkGateContractAddress: \"0x062da4924251c7ed392afc01f57d7ea2c255dc81\",\n\t\tchain: baseSepolia,\n\t\tchainName: \"baseSepolia\",\n\t\trpcUrl: \"https://base-sepolia-public.nodies.app\",\n\t};\n}\n\n/**\n * Fangorn class\n */\nexport class Fangorn {\n\t// The name (for LIT) of the chain we are using\n\tprivate chainName: string;\n\t// The LIT client for interacting with the LIT network\n\tprivate litClient: any;\n\t// The CID of the lit action in storage\n\tprivate litActionCid: string;\n\t// The complied noir circuit (e.g. circuit.json)\n\tprivate circuit: CompiledCircuit;\n\t// The ZKGate Contract instance\n\tprivate zkGate: any;\n\t// The wallet client for signing txs\n\tprivate walletClient: any;\n\t// The storage layer (todo: make this into a genericc storage adapter)\n\tprivate pinata: PinataSDK;\n\t// in-mem state for building manifests\n\tprivate pendingEntries: Map<string, PendingEntry> = new Map();\n\n\tconstructor(\n\t\tchainName: string,\n\t\tlitActionCid: string,\n\t\tcircuit: CompiledCircuit,\n\t\tlitClient: any,\n\t\tzkGate: any,\n\t\twalletClient: any,\n\t\tpinata: PinataSDK,\n\t\tconfig: AppConfig,\n\t) {\n\t\tthis.litClient = litClient;\n\t\tthis.zkGate = zkGate;\n\t\tthis.walletClient = walletClient;\n\t\tthis.pinata = pinata;\n\t\tthis.litActionCid = litActionCid;\n\t\tthis.circuit = circuit;\n\t\tthis.chainName = chainName;\n\t}\n\n\tpublic static async init(\n\t\taccount: Account | Address,\n\t\tjwt: string,\n\t\tgateway: string,\n\t\tconfig?: AppConfig | undefined,\n\t) {\n\t\tconst resolvedConfig = config || FangornConfig.Testnet;\n\t\tconst rpcUrl = resolvedConfig.rpcUrl;\n\t\tconst chain = resolvedConfig.chain;\n\t\tconst chainName = resolvedConfig.chainName;\n\n\t\tconst publicClient = createPublicClient({ transport: http(rpcUrl) });\n\t\tlet walletClient;\n\n\t\tif (typeof window === \"undefined\") {\n\t\t\twalletClient = createWalletClient({\n\t\t\t\taccount,\n\t\t\t\ttransport: http(rpcUrl),\n\t\t\t\tchain: chain,\n\t\t\t});\n\t\t} else {\n\t\t\twalletClient = createWalletClient({\n\t\t\t\taccount: getAddress(account as Address),\n\t\t\t\ttransport: custom(window.ethereum),\n\t\t\t\tchain: chain,\n\t\t\t});\n\t\t}\n\n\t\tconst siweMessageOverrides: WalletClientAuthenticateOverrides = {\n\t\t\tdomain: \"https://vault-demo.fangorn.network\",\n\t\t};\n\t\tconst messageToSign = \"Please sign in to enable LIT functionality.\";\n\n\t\tawait WalletClientAuthenticator.authenticate(\n\t\t\twalletClient,\n\t\t\tmessageToSign,\n\t\t\tsiweMessageOverrides,\n\t\t);\n\t\t// client to interact with LIT proto\n\t\tconst litClient = await createLitClient({\n\t\t\t// @ts-expect-error - TODO: fix this\n\t\t\tnetwork: nagaDev,\n\t\t});\n\n\t\t// interacts with the zk-gate contract\n\t\tlet zkGateClient = new ZKGate(\n\t\t\tresolvedConfig.zkGateContractAddress,\n\t\t\tpublicClient,\n\t\t\twalletClient,\n\t\t);\n\n\t\t// storage via Pinata\n\t\tconst pinata = new PinataSDK({\n\t\t\tpinataJwt: jwt,\n\t\t\tpinataGateway: gateway,\n\t\t});\n\n\t\t// read the circuit from ipfs\n\t\t// TODO: assumes the circuit exists, no error handling here\n\t\tconst circuitResponse = await pinata.gateways.public.get(\n\t\t\tresolvedConfig.circuitJsonCid,\n\t\t);\n\t\tconst compiledCircuit = circuitResponse.data as unknown as CompiledCircuit;\n\n\t\treturn new Fangorn(\n\t\t\tchainName,\n\t\t\tresolvedConfig.litActionCid,\n\t\t\tcompiledCircuit,\n\t\t\tlitClient,\n\t\t\tzkGateClient,\n\t\t\twalletClient,\n\t\t\tpinata,\n\t\t\tresolvedConfig,\n\t\t);\n\t}\n\n\t// TODO: how to ensure password is zeroized?\n\tasync createVault(name: string, password: string): Promise<Hex> {\n\t\tlet passwordHash = hashPassword(password);\n\t\tconst fee = await this.zkGate.getVaultCreationFee();\n\t\tconst { hash: createHash, vaultId } = await this.zkGate.createVault(\n\t\t\tname,\n\t\t\tpasswordHash,\n\t\t\tfee,\n\t\t);\n\t\tawait this.zkGate.waitForTransaction(createHash);\n\t\treturn vaultId;\n\t}\n\n\t/**\n\t * Upload data to an existing vault\n\t * @param vaultId The id of the vault being modified\n\t * @param filedata The file data to insert\n\t * @param overwrite If true, then overwrite the existing vault with new files\n\t * @returns The new manifest CID and Merkle root\n\t */\n\tasync upload(vaultId: Hex, filedata: Filedata[], overwrite?: boolean) {\n\t\t// check if manifest exists or not\n\t\t// load existing manifest\n\t\tconst vault = await this.zkGate.getVault(vaultId);\n\t\t// if the manifest exists and we don't want to overwrite\n\t\tif (vault.manifestCid && !overwrite) {\n\t\t\tconst oldManifest = await this.fetchManifest(vault.manifestCid);\n\t\t\tawait this.loadManifest(oldManifest);\n\t\t\t// try to unpin old manifest\n\t\t\ttry {\n\t\t\t\tawait this.pinata.files.public.delete([vault.manifestCid]);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.warn(\"Failed to unpin old manifest:\", e);\n\t\t\t}\n\t\t}\n\n\t\t// add files\n\t\tfor (let file of filedata) {\n\t\t\tawait this.addFile(vaultId, file);\n\t\t}\n\t\treturn await this.commitVault(vaultId);\n\t}\n\n\t/**\n\t * Encrypts data (with LIT) and uploads ciphertext to IPFS.\n\t * Does NOT update the vault!! You must call commitVault() after adding all files.\n\t */\n\tasync addFile(\n\t\tvaultId: Hex,\n\t\tfile: Filedata,\n\t): Promise<{ cid: string; commitment: Hex }> {\n\t\t// compute commitment to (vaultId, tag)\n\t\tconst tag = file.tag;\n\t\tconst leaf = await computeTagCommitment(vaultId, tag);\n\t\tconst commitmentHex = fieldToHex(leaf);\n\n\t\t// encrypt the actual file contents using AES-GCM locally\n\t\tconst { encryptedData, keyMaterial } = await encryptData(file.data);\n\n\t\t// build ACC\n\t\tconst acc = createAccBuilder()\n\t\t\t.requireLitAction(\n\t\t\t\tthis.litActionCid,\n\t\t\t\t\"go\",\n\t\t\t\t[this.zkGate.getContractAddress(), vaultId, commitmentHex],\n\t\t\t\t\"true\",\n\t\t\t)\n\t\t\t.build();\n\n\t\t// encrypt THE KEY with LIT protocol\n\t\tconst keyEncryptedData = await this.litClient.encrypt({\n\t\t\tdataToEncrypt: keyMaterial,\n\t\t\tunifiedAccessControlConditions: acc,\n\t\t\tchain: this.chainName,\n\t\t});\n\n\t\t// upload ciphertext (pin)\n\t\tconst upload = await this.pinata.upload.public.json(\n\t\t\t{ encryptedData, keyEncryptedData, acc },\n\t\t\t{ metadata: { name: tag } },\n\t\t);\n\n\t\t// stage the entry (not committed yet)\n\t\tthis.pendingEntries.set(tag, {\n\t\t\ttag,\n\t\t\tcid: upload.cid,\n\t\t\tleaf,\n\t\t\tcommitment: commitmentHex,\n\t\t\tacc,\n\t\t\textension: file.extension,\n\t\t\tfileType: file.fileType,\n\t\t});\n\n\t\treturn { cid: upload.cid, commitment: commitmentHex };\n\t}\n\n\t/**\n\t * Removes a file from staging (call before committing)\n\t * @param tag The tag of the file\n\t * @returns bool\n\t */\n\tremoveFile(tag: string): boolean {\n\t\treturn this.pendingEntries.delete(tag);\n\t}\n\n\t/**\n\t * Builds manifest from all staged files and updates the vault on-chain.\n\t * Call this *after* adding all files with addFile().\n\t */\n\tasync commitVault(vaultId: Hex): Promise<{ manifestCid: string; root: Hex }> {\n\t\tif (this.pendingEntries.size === 0) {\n\t\t\tthrow new Error(\"No files to commit\");\n\t\t}\n\n\t\t// build Merkle tree\n\t\tconst entries = Array.from(this.pendingEntries.values());\n\t\tconst leaves = entries.map((e) => e.leaf);\n\t\tconst { root, layers } = await buildTreeFromLeaves(leaves);\n\t\tconst rootHex = fieldToHex(root);\n\n\t\t// construct new manifest\n\t\tconst manifest: VaultManifest = {\n\t\t\tversion: 1,\n\t\t\tposeidon_root: rootHex,\n\t\t\tentries: entries.map((e, i) => ({\n\t\t\t\ttag: e.tag,\n\t\t\t\tcid: e.cid,\n\t\t\t\tindex: i,\n\t\t\t\tleaf: fieldToHex(e.leaf),\n\t\t\t\tcommitment: e.commitment,\n\t\t\t\textension: e.extension,\n\t\t\t\tfileType: e.fileType,\n\t\t\t})),\n\t\t\ttree: layers.map((layer) => layer.map(fieldToHex)),\n\t\t};\n\n\t\t// pin the manifest\n\t\tconst manifestUpload = await this.pinata.upload.public.json(manifest, {\n\t\t\tmetadata: { name: `manifest-${vaultId}` },\n\t\t});\n\n\t\t// update contract\n\t\tconst hash = await this.zkGate.updateVault(\n\t\t\tvaultId,\n\t\t\trootHex,\n\t\t\tmanifestUpload.cid,\n\t\t);\n\t\tawait this.zkGate.waitForTransaction(hash);\n\n\t\t// clear pending entries\n\t\tthis.pendingEntries.clear();\n\n\t\treturn { manifestCid: manifestUpload.cid, root: rootHex };\n\t}\n\n\t/**\n\t * Loads existing manifest\n\t */\n\tasync loadManifest(oldManifest: any) {\n\t\t// load existing entries into pending\n\t\tfor (const entry of oldManifest.entries) {\n\t\t\tthis.pendingEntries.set(entry.tag, {\n\t\t\t\ttag: entry.tag,\n\t\t\t\tcid: entry.cid,\n\t\t\t\tleaf: hexToField(entry.leaf),\n\t\t\t\tcommitment: entry.commitment as Hex,\n\t\t\t\tacc: null,\n\t\t\t\textension: entry.extension,\n\t\t\t\tfileType: entry.fileType,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Attempt to decrypt data identified with a given tag within the given vault\n\t * @param vaultId\n\t * @param tag\n\t * @param password\n\t * @returns\n\t */\n\tasync decryptFile(\n\t\tvaultId: Hex,\n\t\ttag: string,\n\t\tpassword: string,\n\t): Promise<Uint8Array<ArrayBufferLike>> {\n\t\tconst isWindowUndefined = typeof window === \"undefined\";\n\t\tconst account = isWindowUndefined\n\t\t\t? this.walletClient.account\n\t\t\t: this.walletClient;\n\t\t// load the auth context\n\t\tconst authManager = isWindowUndefined\n\t\t\t? // node.js support\n\t\t\t\tcreateAuthManager({\n\t\t\t\t\tstorage: storagePlugins.localStorageNode({\n\t\t\t\t\t\tappName: \"fangorn\",\n\t\t\t\t\t\tnetworkName: nagaDev.getNetworkName(),\n\t\t\t\t\t\tstoragePath: \"./lit-auth-storage\",\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t: // browser support\n\t\t\t\tcreateAuthManager({\n\t\t\t\t\tstorage: storagePlugins.localStorage({\n\t\t\t\t\t\tappName: \"fangorn\",\n\t\t\t\t\t\tnetworkName: nagaDev.getNetworkName(),\n\t\t\t\t\t}),\n\t\t\t\t});\n\n\t\tconst litClient = this.litClient;\n\t\tconst authContext = await authManager.createEoaAuthContext({\n\t\t\tlitClient,\n\t\t\tconfig: { account: account },\n\t\t\tauthConfig: {\n\t\t\t\tdomain: \"https://vault-demo.fangorn.network\",\n\t\t\t\tstatement: \"Please re-authenticate to enable LIT functionality. \",\n\t\t\t\t// is this the right duration for expiry?\n\t\t\t\texpiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(),\n\t\t\t\t// Are resources too open?\n\t\t\t\tresources: [\n\t\t\t\t\t[\"access-control-condition-decryption\", \"*\"],\n\t\t\t\t\t[\"lit-action-execution\", \"*\"],\n\t\t\t\t],\n\t\t\t},\n\t\t});\n\n\t\t// fetch manifest from pinata\n\t\tconst vault = await this.zkGate.getVault(vaultId);\n\t\tconst manifest = await this.fetchManifest(vault.manifestCid);\n\n\t\t// try to find entry\n\t\tconst entry = manifest.entries.find((e) => e.tag === tag);\n\t\tif (!entry) {\n\t\t\tthrow new Error(`Entry not found: ${tag}`);\n\t\t}\n\n\t\t// check if already have access (do not need to reverify)\n\t\tconst userAddress = this.walletClient.account.address;\n\t\tconst hasAccess = await this.zkGate.checkCIDAccess(\n\t\t\tvaultId,\n\t\t\tentry.commitment as Hex,\n\t\t\tuserAddress,\n\t\t);\n\n\t\t// we don't need to request access if we already have it\n\t\tif (!hasAccess) {\n\t\t\tawait this.proveAccess(vaultId, password, entry, manifest);\n\t\t}\n\n\t\t// fetch ciphertext\n\t\tconst response = await this.pinata.gateways.public.get(entry.cid);\n\t\tconst { encryptedData, keyEncryptedData, acc } = response.data as any;\n\n\t\t// request decryption\n\t\tconst decryptedKey = await this.litClient.decrypt({\n\t\t\tciphertext: keyEncryptedData.ciphertext,\n\t\t\tdataToEncryptHash: keyEncryptedData.dataToEncryptHash,\n\t\t\tunifiedAccessControlConditions: acc,\n\t\t\tauthContext,\n\t\t\tchain: this.chainName,\n\t\t});\n\n\t\t// recover the symmetric key\n\t\tconst key = decryptedKey.decryptedData;\n\t\t// actually decrypt the data with the recovered key\n\t\tconst decryptedFile = await decryptData(encryptedData, key);\n\n\t\treturn decryptedFile;\n\t}\n\n\t// proof gen\n\tprivate async proveAccess(\n\t\tvaultId: Hex,\n\t\tpassword: string,\n\t\tentry: VaultEntry,\n\t\tmanifest: VaultManifest,\n\t): Promise<void> {\n\t\tconst userAddress = this.walletClient.account.address;\n\n\t\t// build circuit inputs\n\t\tconst { inputs, nullifier, cidCommitment } = await buildCircuitInputs(\n\t\t\tpassword,\n\t\t\tentry,\n\t\t\tuserAddress,\n\t\t\tvaultId,\n\t\t\tmanifest,\n\t\t);\n\n\t\tconst api = await Barretenberg.new({ threads: 1 });\n\t\tconst backend = new UltraHonkBackend(this.circuit.bytecode, api);\n\t\tconst noir = new Noir(this.circuit);\n\t\tconst { witness } = await noir.execute(inputs);\n\t\tconst proofResult = await backend.generateProof(witness, {\n\t\t\tverifierTarget: \"evm\",\n\t\t});\n\n\t\tconst proofHex: Hex = toHex(proofResult.proof);\n\t\t// submit onchain\n\t\tconst hash = await this.zkGate.submitProof(\n\t\t\tvaultId,\n\t\t\tcidCommitment,\n\t\t\tnullifier,\n\t\t\tproofHex,\n\t\t);\n\t\tawait this.zkGate.waitForTransaction(hash);\n\t}\n\n\tpublic async getUserVaults(): Promise<string[]> {\n\t\tconst address: Address = this.walletClient.account.address;\n\t\tconst vaults = await this.zkGate.getOwnedVaults(address);\n\n\t\treturn vaults;\n\t}\n\n\tpublic async getVault(vaultId: Hex): Promise<Vault> {\n\t\tconst vault: Vault = await this.zkGate.getVault(vaultId);\n\t\treturn vault;\n\t}\n\n\tpublic async fetchManifest(cid: string): Promise<VaultManifest> {\n\t\tconst response = await this.pinata.gateways.public.get(cid);\n\t\treturn response.data as unknown as VaultManifest;\n\t}\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fangorn-sdk",
3
- "version": "0.0.0",
3
+ "version": "0.0.2",
4
4
  "description": "A zero-knowledge conditional access control framework",
5
5
  "repository": {
6
6
  "type": "git",