Tooling & SDK
Aqua JS SDK API reference and usage guide
Aqua Protocol v3 - Tooling & SDK
The Aqua JS SDK (aqua-js-sdk) is a comprehensive TypeScript library for working with Aqua Protocol v3. It provides a complete API for creating, signing, witnessing, and verifying revision chains across multiple platforms.
Installation
1npm install aqua-js-sdkPlatform-Specific Imports
1// Node.js (default)2import Aquafier from 'aqua-js-sdk';3 4// Web Browser5import Aquafier from 'aqua-js-sdk/web';6 7// React Native8import Aquafier from 'aqua-js-sdk/react-native';Core API
Aquafier Class
The main class providing all Aqua Protocol operations.
Constructor
1const aquafier = new Aquafier();No configuration needed for initialization.
Creating Revisions
createGenesisRevision()
Creates the first revision in a new AquaTree.
Signature:
1async createGenesisRevision(2 fileObject: FileObject,3 isForm?: boolean,4 enableContent?: boolean,5 enableScalar?: boolean6): Promise<Result<AquaOperationData, LogData[]>>Parameters:
fileObject: File data to create revision fromisForm: If true, creates form revision (default: false)enableContent: Include file content in revision (default: false)enableScalar: Use scalar method instead of tree (default: true)
Returns:
- Success:
AquaOperationDatawith new AquaTree - Failure: Array of error logs
Example:
1const fileObject: FileObject = {2 fileName: "contract.pdf",3 fileContent: pdfBuffer, // Uint8Array or string4 path: "/documents/contract.pdf"5};6 7const result = await aquafier.createGenesisRevision(fileObject);8 9if (result.isErr) {10 result.data.logData.forEach(log => console.error(log));11 return;12}13 14const aquaTree = result.data.aquaTree;createNewRevision()
Adds a new file/form revision to an existing AquaTree.
Signature:
1async createNewRevision(2 aquaTree: AquaTree,3 fileObject: FileObject,4 isForm?: boolean,5 enableContent?: boolean,6 enableScalar?: boolean7): Promise<Result<AquaOperationData, LogData[]>>Example:
1const result = await aquafier.createNewRevision(2 existingAquaTree,3 updatedFileObject,4 false, // not a form5 false, // don't embed content6 true // use scalar method7);Signing Revisions
signRevision()
Signs the latest revision in an AquaTree.
Signature:
1async signRevision(2 aquaTree: AquaTree,3 signType: SignType,4 credentials?: CredentialsData,5 inlineOptions?: InlineSignerOptions6): Promise<Result<AquaOperationData, LogData[]>>Parameters:
signType: One of"cli","metamask","did","p12","inline"credentials: Credentials for CLI, DID, or P12 signinginlineOptions: Pre-computed signature for inline mode
Sign Types:
CLI Signing
Uses BIP39 mnemonic to derive wallet and sign.
1const credentials: CredentialsData = {2 mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",3 // ... other fields4};5 6const result = await aquafier.signRevision(7 aquaTree,8 "cli",9 credentials10);MetaMask Signing
Opens MetaMask for user to sign (browser only).
1const result = await aquafier.signRevision(2 aquaTree,3 "metamask"4);React Native MetaMask:
1const result = await aquafier.signRevision(2 aquaTree,3 "metamask",4 undefined,5 {6 deepLinkUrl: "metamask://",7 callbackUrl: "myapp://metamask-callback",8 onDeepLinkReady: (url) => {9 // Open MetaMask app10 Linking.openURL(url);11 }12 }13);DID Signing
Signs with Decentralized Identifier.
1const credentials: CredentialsData = {2 did_key: "your-did-key-here",3 // ... other fields4};5 6const result = await aquafier.signRevision(7 aquaTree,8 "did",9 credentials10);P12 Certificate Signing
Signs with P12 certificate.
1const credentials: CredentialsData = {2 p12_password: "certificate-password",3 p12_content: "base64-encoded-p12-content",4 // ... other fields5};6 7const result = await aquafier.signRevision(8 aquaTree,9 "p12",10 credentials11);Inline Signing
Use pre-computed signature.
1const inlineOptions: InlineSignerOptions = {2 walletAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8",3 signature: "0x8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f..."4};5 6const result = await aquafier.signRevision(7 aquaTree,8 "inline",9 undefined,10 inlineOptions11);Witnessing Revisions
witnessRevision()
Timestamps a revision via blockchain or TSA.
Signature:
1async witnessRevision(2 aquaTree: AquaTree,3 witnessType: WitnessType,4 witnessConfig: WitnessConfig,5 credentials?: CredentialsData,6 witnessPlatform?: WitnessPlatformType,7 inlineOptions?: InlineWitnessOptions8): Promise<Result<AquaOperationData, LogData[]>>Parameters:
witnessType:"eth","nostr", or"tsa"witnessConfig: Network and contract configurationcredentials: Credentials for signing transactionwitnessPlatform:"cli"or"metamask"(Ethereum only)inlineOptions: Pre-computed transaction (inline mode)
Ethereum Witnessing
Configuration:
1const witnessConfig: WitnessConfig = {2 witnessEventVerificationHash: latestRevisionHash,3 witnessNetwork: "sepolia", // or "mainnet", "holesky"4 smartContractAddress: "0x5FbDB2315678afecb367f032d93F642f64180aa3"5};6 7const credentials: CredentialsData = {8 mnemonic: "your mnemonic here",9 // ...10};CLI Method (uses mnemonic):
1const result = await aquafier.witnessRevision(2 aquaTree,3 "eth",4 witnessConfig,5 credentials,6 "cli"7);MetaMask Method (prompts user):
1const result = await aquafier.witnessRevision(2 aquaTree,3 "eth",4 witnessConfig,5 undefined,6 "metamask"7);Nostr Witnessing
1const witnessConfig: WitnessConfig = {2 witnessEventVerificationHash: latestRevisionHash,3 witnessNetwork: "sepolia", // not used for Nostr4 smartContractAddress: "" // not used for Nostr5};6 7const credentials: CredentialsData = {8 nostr_sk: "your-nostr-secret-key",9 // ...10};11 12const result = await aquafier.witnessRevision(13 aquaTree,14 "nostr",15 witnessConfig,16 credentials17);TSA Witnessing
1const result = await aquafier.witnessRevision(2 aquaTree,3 "tsa",4 witnessConfig5);Linking Revisions
linkRevision()
Creates a link revision connecting to other AquaTrees.
Signature:
1async linkRevision(2 aquaTree: AquaTree,3 linkedAquaTrees: AquaTree[],4 linkType?: string5): Promise<Result<AquaOperationData, LogData[]>>Example:
1const result = await aquafier.linkRevision(2 mainAquaTree,3 [dependency1Tree, dependency2Tree, dependency3Tree],4 "dependencies"5);Verification
verifyRevisionChain()
Verifies an entire AquaTree chain.
Signature:
1async verifyRevisionChain(2 aquaTree: AquaTree,3 credentials?: CredentialsData4): Promise<VerificationGraphData>Parameters:
aquaTree: Tree to verifycredentials: Optional, for Ethereum witness lookup
Returns:
VerificationGraphData: Graph structure with verification results
Example:
1const verificationResult = await aquafier.verifyRevisionChain(aquaTree, credentials);2 3// Check overall success4if (verificationResult.isValidationSuccessful) {5 console.log("✓ Chain is valid");6} else {7 console.log("✗ Chain validation failed");8}9 10// Traverse verification graph11function printResults(node: VerificationGraphData, depth = 0) {12 const indent = " ".repeat(depth);13 const status = node.isValidationSuccessful ? "✓" : "✗";14 console.log(`${indent}${status} ${node.revisionType}`);15 16 node.verificationGraphData.forEach(child => printResults(child, depth + 1));17}18 19printResults(verificationResult);verifyFormRevision()
Verifies form-specific data.
Signature:
1async verifyFormRevision(2 aquaTree: AquaTree,3 formData: FormData4): Promise<FormVerificationResponseData>Utility Methods
removeLastRevision()
Removes the most recent revision from an AquaTree.
Signature:
1removeLastRevision(2 aquaTree: AquaTree3): Result<AquaOperationData, LogData[]>Example:
1const result = aquafier.removeLastRevision(aquaTree);2 3if (result.isOk) {4 const updatedTree = result.data.aquaTree;5 console.log("Revision removed successfully");6}checkIfFileAlreadyNotarized()
Checks if a file has already been notarized.
Signature:
1checkIfFileAlreadyNotarized(2 aquaTree: AquaTree,3 fileObject: FileObject4): booleanfetchFilesToBeRead()
Gets list of files that need content loaded.
Signature:
1fetchFilesToBeRead(aquaTree: AquaTree): string[]Type Reference
Core Types
1interface FileObject {2 fileName: string3 fileContent: string | AquaTree | Uint8Array | Record<string, string> | object4 path: string5 fileSize?: number6}7 8interface AquaTree {9 revisions: Revisions10 file_index: FileIndex11 tree?: RevisionTree12 treeMapping?: TreeMapping13}14 15interface Revision {16 previous_verification_hash: string17 local_timestamp: string18 revision_type: RevisionType19 version: string20 // ... type-specific fields21}22 23type RevisionType = "file" | "witness" | "signature" | "form" | "link"24type SignType = "metamask" | "cli" | "did" | "p12" | "inline"25type WitnessType = "tsa" | "eth" | "nostr"26type WitnessNetwork = "sepolia" | "mainnet" | "holesky"Result Type
1type Result<T, E> =2 | { isOk: true; isErr: false; data: T }3 | { isOk: false; isErr: true; data: E }Configuration Types
1interface CredentialsData {2 mnemonic: string3 nostr_sk: string4 did_key: string5 alchemy_key: string6 witness_eth_network: string7 witness_method: string8 p12_password?: string9 p12_content?: string10}11 12interface WitnessConfig {13 witnessEventVerificationHash: string14 witnessNetwork: WitnessNetwork15 smartContractAddress: string16}Platform-Specific Notes
Node.js
Full functionality available:
- All signing methods
- All witnessing methods
- File system access
- HTTP server for MetaMask callback
1import Aquafier from 'aqua-js-sdk';2import fs from 'fs';3 4const aquafier = new Aquafier();5 6// Read file from disk7const fileContent = fs.readFileSync('document.pdf');8 9const fileObject = {10 fileName: 'document.pdf',11 fileContent: fileContent,12 path: './document.pdf'13};Web Browser
Most functionality available:
- MetaMask signing (primary method)
- DID signing
- Ethereum witnessing via MetaMask
- Nostr, TSA witnessing
Limitations:
- No P12 signing (requires file system)
- No CLI signing with mnemonic (security risk in browser)
1import Aquafier from 'aqua-js-sdk/web';2 3const aquafier = new Aquafier();4 5// File from input element6const file = document.getElementById('fileInput').files[0];7const arrayBuffer = await file.arrayBuffer();8 9const fileObject = {10 fileName: file.name,11 fileContent: new Uint8Array(arrayBuffer),12 path: file.name13};React Native
Most functionality with platform adaptations:
- MetaMask via deep linking
- DID signing
- Limited witnessing
Limitations:
- No local HTTP server
- MetaMask requires custom deep linking
- File system needs react-native-fs
1import Aquafier from 'aqua-js-sdk/react-native';2import RNFS from 'react-native-fs';3 4const aquafier = new Aquafier();5 6// Read file7const fileContent = await RNFS.readFile(filePath, 'base64');8 9const fileObject = {10 fileName: 'document.pdf',11 fileContent: Buffer.from(fileContent, 'base64'),12 path: filePath13};Complete Workflow Examples
Document Notarization
1// 1. Create genesis2const fileObject: FileObject = {3 fileName: "contract.pdf",4 fileContent: pdfBuffer,5 path: "/contracts/contract.pdf"6};7 8let result = await aquafier.createGenesisRevision(fileObject);9let aquaTree = result.data.aquaTree;10 11// 2. Sign with CLI12const credentials: CredentialsData = {13 mnemonic: process.env.MNEMONIC,14 // ... other fields15};16 17result = await aquafier.signRevision(aquaTree, "cli", credentials);18aquaTree = result.data.aquaTree;19 20// 3. Witness to Ethereum21const witnessConfig: WitnessConfig = {22 witnessEventVerificationHash: Object.keys(aquaTree.revisions)[Object.keys(aquaTree.revisions).length - 1],23 witnessNetwork: "sepolia",24 smartContractAddress: "0x5FbDB2315678afecb367f032d93F642f64180aa3"25};26 27result = await aquafier.witnessRevision(28 aquaTree,29 "eth",30 witnessConfig,31 credentials,32 "cli"33);34aquaTree = result.data.aquaTree;35 36// 4. Save37fs.writeFileSync('contract.aqua.json', JSON.stringify(aquaTree, null, 2));Multi-Party Approval
1// Party 1: Create and sign2let result = await aquafier.createGenesisRevision(fileObject);3let aquaTree = result.data.aquaTree;4 5result = await aquafier.signRevision(aquaTree, "cli", party1Credentials);6aquaTree = result.data.aquaTree;7 8// Send aquaTree to Party 29 10// Party 2: Add signature11result = await aquafier.signRevision(aquaTree, "metamask");12aquaTree = result.data.aquaTree;13 14// Send back to Party 115 16// Party 1: Witness17result = await aquafier.witnessRevision(18 aquaTree,19 "eth",20 witnessConfig,21 party1Credentials,22 "cli"23);24aquaTree = result.data.aquaTree;Form Submission with Verification
1// 1. Create form genesis2const formData = {3 name: "John Doe",4 email: "john@example.com",5 status: "pending"6};7 8const fileObject: FileObject = {9 fileName: "application.json",10 fileContent: formData,11 path: "/forms/application.json"12};13 14let result = await aquafier.createGenesisRevision(fileObject, true); // isForm=true15let aquaTree = result.data.aquaTree;16 17// 2. Sign18result = await aquafier.signRevision(aquaTree, "did", credentials);19aquaTree = result.data.aquaTree;20 21// 3. Witness22result = await aquafier.witnessRevision(aquaTree, "nostr", witnessConfig, credentials);23aquaTree = result.data.aquaTree;24 25// 4. Verify form26const verifyResult = await aquafier.verifyFormRevision(aquaTree, formData);27console.log("Form valid:", verifyResult.isOk);Error Handling
All methods return Result<T, E> type. Always check for errors:
1const result = await aquafier.createGenesisRevision(fileObject);2 3if (result.isErr) {4 // Handle error5 console.error("Failed to create genesis:");6 result.data.forEach(log => {7 console.error(`[${log.logType}] ${log.log}`);8 });9 return;10}11 12// Success13const aquaTree = result.data.aquaTree;Best Practices
- Always verify results: Check
isErrbefore using data - Store credentials securely: Never commit mnemonic/keys
- Use environment variables: Store sensitive data in
.env - Validate inputs: Check file sizes and formats before processing
- Handle logs: Display or log all LogData for debugging
- Test on testnets: Use Sepolia/Holesky before mainnet
- Save AquaTrees: Persist JSON after each operation
- Verify chains: Run verification after receiving AquaTrees
Testing
Create credentials.json for testing:
1{2 "mnemonic": "your test mnemonic",3 "nostr_sk": "your nostr secret key",4 "did_key": "your did key",5 "alchemy_key": "your alchemy api key",6 "witness_eth_network": "sepolia",7 "witness_method": "cli"8}Run tests:
1npm testRun specific test file:
1npm test -- ./tests/aquafier.test.tsSee Also
- Introduction - Getting started
- Concepts - Core concepts
- Schema Reference - Revision specifications
- GitHub Repository - Source code and examples
