{"_id":"@allfeat/ats-zkp-wasm","name":"@allfeat/ats-zkp-wasm","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.1":{"name":"@allfeat/ats-zkp-wasm","version":"0.1.1","description":"Allfeat Time Stamp Song Commitment Circuit in Arkworks (BN254, Groth16 + Poseidon)","main":"pkg/allfeat_ats_zkp_wasm.js","types":"pkg/allfeat_ats_zkp_wasm.d.ts","devDependencies":{"wasm-pack":"^0.12.0"},"keywords":["wasm","ats","zkp"],"author":{"name":"Allfeat labs"},"license":"GPL-3.0-only","scripts":{"build":"wasm-pack build --target web --out-dir pkg","build:node":"wasm-pack build --target nodejs --out-dir pkg-node","build:bundler":"wasm-pack build --target bundler --out-dir pkg-bundler","test":"wasm-pack test --headless --firefox"},"_id":"@allfeat/ats-zkp-wasm@0.1.1","_integrity":"sha512-Uypi4aA3nDtiz66iscuwTpMpnCbo/PY1VpB3Q+M4KUj/JJ3i2ODdRvrqgf4/2NfV6Oh7mkcoK9K40S3gXL7H4A==","_resolved":"/tmp/5e7d6f7478740d675158e64539a707ec/allfeat-ats-zkp-wasm-0.1.1.tgz","_from":"file:allfeat-ats-zkp-wasm-0.1.1.tgz","_nodeVersion":"22.19.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-Uypi4aA3nDtiz66iscuwTpMpnCbo/PY1VpB3Q+M4KUj/JJ3i2ODdRvrqgf4/2NfV6Oh7mkcoK9K40S3gXL7H4A==","shasum":"e7dab0146177443ff994c5aa665e379dab89a8f7","tarball":"https://registry.npmjs.org/@allfeat/ats-zkp-wasm/-/ats-zkp-wasm-0.1.1.tgz","fileCount":4,"unpackedSize":38627,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDDuTB9ghoheY4nKQmPlJnJthG3O1R99ru6QPKJ6FSXPwIgMmnGAX6GN4jJX5rreROulUUDLVFtyqSYeW+pvI+B6Nc="}]},"_npmUser":{"name":"sailor_snow","email":"snxwin@pm.me"},"directories":{},"maintainers":[{"name":"sailor_snow","email":"snxwin@pm.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ats-zkp-wasm_0.1.1_1759963671786_0.4462913107622908"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-08T22:47:51.685Z","0.1.1":"2025-10-08T22:47:51.977Z","modified":"2025-10-08T22:47:52.310Z"},"maintainers":[{"name":"sailor_snow","email":"snxwin@pm.me"}],"description":"Allfeat Time Stamp Song Commitment Circuit in Arkworks (BN254, Groth16 + Poseidon)","keywords":["wasm","ats","zkp"],"author":{"name":"Allfeat labs"},"license":"GPL-3.0-only","readme":"# ATS-ZKP-WASM – WebAssembly Bindings for Allfeat ZKP\n\nA WebAssembly module exposing the **ATS-ZKP** cryptographic primitives and zero-knowledge proof helpers to JavaScript/TypeScript applications.\nIt is designed to be used in **Next.js, Node.js, and browser environments** to compute musical metadata hashes, commitments, and zk-SNARK proofs without exposing Arkworks internals.\n\n## Overview\n\nThe `ats-zkp-wasm` crate is a thin WASM façade on top of [`ats-zkp`](../zkp).\nIt provides a minimal, **JS-friendly API** with hex strings and plain objects as inputs/outputs, and gives you four high-level functions:\n\n- **`build_bundle(title, audioBytes, creators, timestampBigInt)` -> `{ bundle }`**\n  Computes:\n  - `hash_title`, `hash_audio`, `hash_creators`\n  - a fresh random `secret`\n  - Poseidon `commitment` and `nullifier`\n  Returns everything as **hex strings**. Note: `bundle.timestamp` is the **timestamp encoded as an `Fr` hex**, ready to pass to proof/verify.\n\n- **`calculate_commitment(title, audioBytes, creators, secretHex)` -> `commitmentHex`**\n  Computes the Poseidon hash commitment from the provided inputs using an **existing secret**:\n  - `hash_title`, `hash_audio`, `hash_creators` (computed internally)\n  - `commitment` = Poseidon(`hash_title`, `hash_audio`, `hash_creators`, `secret`)\n  Returns the **commitment as a hex string**. Use this when you already have a secret (e.g., from a previous `build_bundle` call) and need to recompute or verify the commitment.\n\n- **`prove(pkHex, secretHex, publicsArray)` -> `{ proof, publics }`**\n  Generates a Groth16 proof using the **compressed PK** (0x-hex) and **6 public inputs** in this exact order:\n  `[hash_title, hash_audio, hash_creators, commitment, timestamp, nullifier]`.\n\n- **`verify(vkHex, proofHex, publicsArray)` -> `boolean`**\n  Verifies a proof using the **compressed VK** (0x-hex) and the same 6 publics (0x-hex) in the **same order**.\n\nAll heavy logic remains in `ats-zkp`; this crate only exports the essential functions to JS.\n\n## Prerequisites\n\nInstall `wasm-pack`:\n\n```bash\ncurl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh\n```\n\n## Building\n\n### For Next.js / Bundler (default)\n\n```bash\nwasm-pack build --target bundler --out-dir pkg\n```\n\n### For Node.js\n\n```bash\nwasm-pack build --target nodejs --out-dir pkg-node\n```\n\n### For Browser (ES Modules)\n\n```bash\nwasm-pack build --target web --out-dir pkg-web\n```\n\n## Testing\n\nRun Rust tests:\n\n```bash\ncargo test\n```\n\nRun WASM tests:\n\n```bash\nwasm-pack test --node\n```\n\n## Running the JavaScript Example\n\nAn example script is included in `js-example/example.js`.\n\n1. First, build the Node.js bindings:\n\n```bash\nwasm-pack build --target nodejs --out-dir pkg-node\n```\n\n2. Move into the js-example/ folder:\n\n```bash\ncd js-example\n```\n\n3. Run the example with Node.js:\n\n```bash\nnode example.js\n```\n\nThis will:\n\n- Read a sample audio file (`sample-audio.mp3`)\n- Build a ZKP input bundle (`build_bundle`)\n- Generate and print a Groth16 proof (`prove`)\n\n## Integration in TypeScript/JavaScript Applications\n\n### Next.js Integration\n\n1. Build the WASM module:\n\n```bash\nwasm-pack build --target bundler --out-dir pkg\n```\n\n2. Copy the `pkg` folder to your Next.js project (e.g., `src/lib/ats-cert-generator`)\n\n3. Configure Next.js for WASM support in `next.config.ts`:\n\n```typescript\nimport type { NextConfig } from \"next\";\n\nconst nextConfig: NextConfig = {\n  webpack: (config) => {\n    // Enable async WebAssembly\n    config.experiments = {\n      ...config.experiments,\n      asyncWebAssembly: true,\n    };\n\n    // Ensure .wasm files are handled as async webassembly\n    config.module.rules.push({\n      test: /\\.wasm$/,\n      type: \"webassembly/async\",\n    });\n\n    return config;\n  },\n};\n\nexport default nextConfig;\n```\n\n4. Use in your Next.js components:\n\n```typescript\n// app/components/ZkpDemo.tsx (or any client component)\n\"use client\";\n\nimport { useState, useRef } from \"react\";\n\nexport default function ZkpDemo() {\n  const [loading, setLoading] = useState(false);\n  const [result, setResult] = useState<string>(\"\");\n  const fileRef = useRef<HTMLInputElement | null>(null);\n\n  const onRun = async () => {\n    if (typeof window === \"undefined\") return; // guard SSR\n\n    try {\n      setLoading(true);\n      setResult(\"\");\n\n      // 1) Dynamically load the wasm-bindgen JS and init the WASM\n      const init = (await import(\"@/lib/ats-zkp-wasm/ats_zkp_wasm.js\")).default;\n      const { build_bundle, prove, verify } = await import(\n        \"@/lib/ats-zkp-wasm/ats_zkp_wasm.js\"\n      );\n      await init(); // VERY IMPORTANT: initialize the wasm module\n\n      // 2) Read the audio file as Uint8Array\n      const file = fileRef.current?.files?.[0];\n      if (!file) {\n        setResult(\"Please choose an audio file first.\");\n        return;\n      }\n      const buf = new Uint8Array(await file.arrayBuffer());\n\n      // 3) Prepare inputs (creators must match JsCreator)\n      const creators = [\n        { fullName: \"Alice\", email: \"alice@example.com\", roles: [\"AT\"] },\n      ];\n      const title = \"Song Title\";\n      const timestamp = BigInt(Math.floor(Date.now() / 1000)); // u64-safe\n\n      // 4) Build the bundle (hashes, secret, commitment, nullifier)\n      const { bundle } = build_bundle(title, buf, creators, timestamp);\n\n      // 5) Prove using your PK (hex string, 0x-prefixed, compressed)\n      //    You can import it or fetch it from your API/secrets manager.\n      const { PK } = await import(\"@/lib/ats-zkp-wasm/pk.js\");\n      const publics = [\n        bundle.hash_title,\n        bundle.hash_audio,\n        bundle.hash_creators,\n        bundle.commitment,\n        bundle.timestamp, // already Fr-hex from build_bundle\n        bundle.nullifier,\n      ];\n      const { proof, publics: publicsProof } = prove(PK, bundle.secret, publics);\n\n      // 6) Verify using your VK (hex string, 0x-prefixed, compressed)\n      const { VK } = await import(\"@/lib/ats-zkp-wasm/vk.js\");\n      const ok = verify(VK, proof, publicsProof);\n\n      setResult(\n        [\n          `secret: ${bundle.secret} (keep this PRIVATE)`,\n          `proof: ${proof}`,\n          `verify: ${ok}`,\n        ].join(\"\\n\")\n      );\n    } catch (err) {\n      // Errors are forwarded from Rust via `JsValue::from_str`, so they arrive as strings\n      console.error(\"ZKP flow failed:\", err);\n      setResult(`Error: ${String(err)}`);\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  return (\n    <div className=\"space-y-4\">\n      <input ref={fileRef} type=\"file\" accept=\"audio/*\" />\n      <button onClick={onRun} disabled={loading}>\n        {loading ? \"Running...\" : \"Run ZKP demo\"}\n      </button>\n      <pre style={{ whiteSpace: \"pre-wrap\" }}>{result}</pre>\n    </div>\n  );\n}\n```\n","readmeFilename":"README.md","_rev":"1-932ecac6755736faa462524fef84cb9d"}