Aqua ProtocolAqua Protocol
Aqua Protocol
Aqua ProtocolAqua

Documentation

Welcome to Aqua ProtocolQuick StartDevelopment GuideVersion v4 (beta)
Use Cases
Document VerificationIdentity AttestationAqua Protocol Use CasesSupply Chain Tracking
Development Tools
Aqua CLIAqua SDKAquafier API
Schema Reference
Aqua TreeFile IndexAqua Protocol Schema Reference
Revision Types

Documentation

Welcome to Aqua ProtocolQuick StartDevelopment GuideVersion v4 (beta)
Use Cases
Document VerificationIdentity AttestationAqua Protocol Use CasesSupply Chain Tracking
Development Tools
Aqua CLIAqua SDKAquafier API
Schema Reference
Aqua TreeFile IndexAqua Protocol Schema Reference
Revision Types
Docs
Development Guide

Development Guide

This guide covers everything you need to develop applications with Aqua Protocol, including signing methods, witnessing options, and SDK usage.

9 min read
Prerequisites

We recommend completing the Quick Start Guide before diving into development details.

Choose Your SDK

Aqua Protocol offers SDKs for different use cases:

Rust SDK (v4)

Beta - Template system, WASM support, cross-platform

Best for: New projects, performance-critical applications

JavaScript SDK (v3)

Stable - Production-ready, Node.js/Web/React Native

Best for: Web applications, existing JavaScript projects

CLI Tool (v4)

Command-line tool for quick operations

Best for: Testing, CI/CD, scripting

Aquafier API (v3)

Web-based API for notarization

Best for: No-code integration, demos

Signing Methods

Aqua Protocol supports multiple signature types for different use cases:

MethodProtocol VersionUse CaseTrust Model
DID (JWS)v3, v4Decentralized identitiesW3C DID standard
Ethereum (EIP-191)v3, v4Blockchain-native appsEthereum addresses
RSAv4 onlyTraditional PKICertificate authorities
P12 Certificatesv3 onlyEnterprise/legal docsCertificate authorities

Signing Setup Details

What you need: A DID key pair

How to generate:

Option 1: Using JavaScript

Code
bash
1npm install @digitalcredentials/did-method-key
Code
javascript
1import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020';
2import { X25519KeyAgreementKey2020 } from '@digitalcredentials/x25519-key-agreement-key-2020';
3 
4const keyPair = await Ed25519VerificationKey2020.generate();
5const did = `did:key:${keyPair.publicKeyMultibase}`;
6console.log('DID:', did);
7console.log('Private Key:', keyPair.privateKeyMultibase);

Option 2: Online Generator

  • Visit EBSI DID Generator
  • Click "Generate Keys"
  • Save your DID and private key securely

Protocol Support: v3, v4

What you need: Ethereum wallet with private key or mnemonic

Two supported methods:

1. MetaMask Browser Extension (Recommended for development)

  • Install MetaMask in your browser
  • Create or import a wallet
  • The SDK will prompt for signature when needed

2. Mnemonic/Private Key in Credentials File

Create a credentials.json file:

Code
json
1{
2 "mnemonic": "your twelve word mnemonic phrase here...",
3 "wallet_address": "0xYourEthereumAddress"
4}

Or with private key:

Code
json
1{
2 "private_key": "0xYourPrivateKeyHex",
3 "wallet_address": "0xYourEthereumAddress"
4}
Security

Never commit credentials.json to version control! Add it to .gitignore.

Check your SDK documentation (Rust SDK | JavaScript SDK) for how to pass credentials.

Protocol Support: v3, v4

What you need: RSA key pair (2048-bit or higher)

Generate RSA keys:

Code
bash
1# Generate private key (2048-bit)
2openssl genrsa -out private.pem 2048
3 
4# Extract public key
5openssl rsa -in private.pem -pubout -out public.pem
6 
7# View keys
8cat private.pem
9cat public.pem

For production: Use keys from your organization's PKI infrastructure or certificate authority.

Protocol Support: v4 only

What you need: PKCS#12 certificate file (.p12/.pfx) with password

For Development (self-signed certificate):

Code
bash
1# Generate private key
2openssl genrsa -out private.key 2048
3 
4# Create certificate signing request
5openssl req -new -key private.key -out certificate.csr
6 
7# For Windows/Git Bash, specify config:
8# openssl req -new -key private.key -out certificate.csr -config "C:\Program Files\Git\usr\ssl\openssl.cnf"
9 
10# Generate self-signed certificate (valid for 365 days)
11openssl x509 -req -days 365 -in certificate.csr -signkey private.key -out certificate.crt
12 
13# Create P12 file (you'll be prompted for export password)
14openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt

Convert to Base64 (required for SDK):

Code
bash
1# macOS/Linux
2base64 -i certificate.p12 -o certificate_base64.txt
3 
4# Windows (PowerShell)
5[Convert]::ToBase64String([IO.File]::ReadAllBytes("certificate.p12")) | Out-File certificate_base64.txt
6 
7# Linux alternative
8base64 certificate.p12 > certificate_base64.txt

For Production (trusted certificate):

1. Purchase from Certificate Authority:

  • DigiCert, Sectigo, GlobalSign, etc.
  • Request "Code Signing" or "Document Signing" certificate
  • They'll provide a .p12/.pfx file directly

2. If you receive separate files (.crt + .key + intermediate):

Code
bash
1openssl pkcs12 -export -out certificate.p12 \
2 -inkey privatekey.key \
3 -in certificate.crt \
4 -certfile intermediate.crt

Usage in SDK:

Code
json
1{
2 "p12_content": "base64_encoded_p12_content_here",
3 "p12_password": "your_export_password"
4}

Protocol Support: v3 only

Witnessing Methods

Witnessing anchors your Aqua revisions to external timestamping services for provable timestamps:

MethodNetworksCostVerification
EthereumMainnet, Sepolia, HoleskyGas fees (testnet: free)Blockchain explorer
TSARFC 3161 servicesFree (public TSAs)TSA verification
NostrNostr relaysFreeNostr event verification

Witnessing Setup Details

What you need: A TSA service URL

Free Public TSA Services:

Code
bash
1# DigiCert
2http://timestamp.digicert.com
3 
4# Sectigo (formerly Comodo)
5http://timestamp.sectigo.com
6http://timestamp.comodoca.com
7 
8# GlobalSign
9http://timestamp.globalsign.com/scripts/timstamp.dll
10http://timestamp.globalsign.com/tsa/r6advanced1
11 
12# Entrust
13http://timestamp.entrust.net/TSS/RFC3161sha2TS

Usage: Simply provide the TSA URL to your SDK when witnessing.

Benefits:

  • No blockchain required
  • Widely accepted standard (RFC 3161)
  • Free for most public TSAs
  • Instant timestamps

Protocol Support: v3, v4

What you need:

  1. Ethereum wallet (MetaMask or mnemonic/private key)
  2. ETH for gas fees (mainnet) or testnet ETH (Sepolia/Holesky)
  3. Alchemy API key for witness verification

Networks Supported:

  • Mainnet: Production use, requires real ETH for gas
  • Sepolia: Testnet, free test ETH from faucets
  • Holesky: Testnet, free test ETH from faucets

Wallet Setup (same as signing):

Option 1: MetaMask

  • Install MetaMask
  • Ensure you're on the correct network (mainnet/sepolia/holesky)
  • Have sufficient ETH for gas fees

Option 2: Credentials File

Code
json
1{
2 "mnemonic": "your twelve word mnemonic phrase here...",
3 "wallet_address": "0xYourEthereumAddress"
4}

Get Test ETH (for testnets):

  • Sepolia: sepoliafaucet.com
  • Holesky: holesky-faucet.pk910.de

Alchemy API Key (for verification):

  1. Visit alchemy.com
  2. Create free account
  3. Create new app
  4. Copy API key
  5. Detailed guide

Protocol Support: v3, v4

What you need: Nostr secret key (nsec)

How to get a Nostr key:

Option 1: Nostr Client App

  1. Download a Nostr app:
    • Damus (iOS)
    • Amethyst (Android)
    • Primal (Web/Mobile)
  2. Create new account or log in
  3. App generates a key pair automatically
  4. Your secret key starts with nsec1...
  5. Save it securely - you'll need it for witnessing

Option 2: Web Generator

  • Visit nostr.com or nostrtool.com
  • Click "Generate Keys"
  • Save your secret key (nsec1...)
Security

Your Nostr secret key is permanent. Anyone with it can post as you on Nostr relays. Keep it secure!

Benefits:

  • Fully decentralized (no blockchain fees)
  • Censorship-resistant
  • Fast propagation across relays
  • Free to use

Protocol Support: v3, v4

JavaScript SDK Usage (v3)

Prerequisites
  • Node.js version 19 or higher
  • Install aqua-js-sdk: npm install aqua-js-sdk

Complete Workflow Example

Follow these steps to notarize a file, sign it, and witness it using the JavaScript SDK (v3):

Create Genesis Revision

Code
typescript
1import Aquafier, { FileObject } from 'aqua-js-sdk';
2import { readFileSync } from 'fs';
3 
4// Read file content
5const testFileContent = readFileSync("./test.txt", 'utf-8');
6 
7// Create file object
8const aquaFileObject: FileObject = {
9 fileName: "test.txt",
10 fileContent: testFileContent,
11 path: "./test.txt"
12};
13 
14// Initialize Aquafier
15const aquafier = new Aquafier();
16 
17// Create genesis revision (notarize the file)
18const genesisResult = await aquafier.createGenesisRevision(aquaFileObject);
19 
20if (genesisResult.isOk()) {
21 console.log("Genesis created successfully!");
22 console.log("Aqua Tree:", genesisResult.data.aquaTree);
23} else {
24 console.error("Error creating genesis:", genesisResult.error);
25}

Sign the Aqua Tree

Code
typescript
1import { AquaTreeWrapper, CredentialsData } from 'aqua-js-sdk';
2 
3// Prepare credentials (for MetaMask, can be empty object)
4const creds: CredentialsData = {};
5 
6// Or for CLI signing with mnemonic:
7// const creds: CredentialsData = {
8// mnemonic: "your twelve word mnemonic here",
9// wallet_address: "0xYourAddress"
10// };
11 
12// Create wrapper (empty string for revision means sign latest)
13const aquaWrapper: AquaTreeWrapper = {
14 aquaTree: genesisResult.data.aquaTree,
15 fileObject: aquaFileObject,
16 revision: "" // Sign latest revision
17};
18 
19// Sign with MetaMask (or use "cli", "did", "p12")
20const signedResult = await aquafier.signAquaTree(
21 aquaWrapper,
22 "metamask", // Signature type
23 creds,
24 true // Auto-increment
25);
26 
27if (signedResult.isOk()) {
28 console.log("Signature added successfully!");
29} else {
30 console.error("Signing failed:", signedResult.error);
31}

Witness on Blockchain

Code
typescript
1// Update wrapper with signed tree
2const witnessWrapper: AquaTreeWrapper = {
3 aquaTree: signedResult.data.aquaTree,
4 fileObject: aquaFileObject,
5 revision: "" // Witness latest revision
6};
7 
8// Witness on Ethereum Sepolia testnet
9const witnessResult = await aquafier.witnessAquaTree(
10 witnessWrapper,
11 "eth", // Witness type (eth, tsa, or nostr)
12 "sepolia", // Network (sepolia, mainnet, holesky)
13 "metamask", // Signing method
14 creds,
15 true // Auto-increment
16);
17 
18if (witnessResult.isOk()) {
19 console.log("Witnessing successful!");
20 console.log("Transaction:", witnessResult.data.witness_transaction_hash);
21} else {
22 console.error("Witnessing failed:", witnessResult.error);
23}

Verify the Aqua Tree

Code
typescript
1// Fetch aqua tree from storage, database, or state
2const aquaTree = witnessResult.data.aquaTree;
3 
4// Prepare credentials for verification (needs Alchemy key for Ethereum witness)
5const verifyCreds: CredentialsData = {
6 alchemy_key: "your_alchemy_api_key"
7};
8 
9// Verify the complete tree
10const verificationResult = await aquafier.verifyAquaTree(
11 aquaTree,
12 [aquaFileObject], // Array of file objects
13 verifyCreds
14);
15 
16if (verificationResult.isOk()) {
17 console.log("✓ Verification successful!");
18 console.log("Details:", JSON.stringify(verificationResult.data, null, 2));
19} else {
20 console.log("✗ Verification failed!");
21 console.log("Details:", JSON.stringify(verificationResult.data, null, 2));
22}

More Examples

Complete Examples

Browse full working examples in the repository

API Documentation

Detailed API reference for JavaScript SDK

Rust SDK Usage (v4)

Prerequisites
  • Rust 1.70 or higher
  • Add to Cargo.toml: aqua-rs-sdk = { git = "https://github.com/inblockio/aqua-verifier-rs" }

Quick Example

Code
rust
1use aqua_rs_sdk::primitives::Method;
2use aqua_rs_sdk::schema::file_data::FileData;
3use aqua_rs_sdk::Aquafier;
4use std::path::PathBuf;
5 
6#[tokio::main]
7async fn main() -> Result<(), Box<dyn std::error::Error>> {
8 // Read file content
9 let filename = "test.txt".to_string();
10 let file_content = tokio::fs::read(&filename).await?;
11 
12 // Create file data
13 let file_data = FileData::new(
14 filename.clone(),
15 file_content,
16 PathBuf::from(format!("./{}", filename)),
17 );
18 
19 // Initialize Aquafier
20 let aquafier = Aquafier::new(None, None);
21 
22 // Create genesis revision (notarize the file)
23 let result = aquafier.create_genesis_revision(file_data, Method::Scalar);
24 
25 match result {
26 Ok(tree) => {
27 println!("✓ Aqua chain created successfully!");
28 println!("{}", serde_json::to_string_pretty(&tree)?);
29 }
30 Err(e) => {
31 eprintln!("Error: {:#?}", e);
32 }
33 }
34 
35 Ok(())
36}

More Resources

Rust SDK Guide

Complete guide for the Rust SDK

Schema Reference

v4 protocol specifications

Next Steps

Use Cases

Explore real-world applications

Quick Start

Build your first Aqua application

Examples Repository

Browse complete examples

Get Support

Need help? Contact our team

Edit this pageReport an issue
Previous
Quick Start
Next
Version v4 (beta)

Documentation

  • Getting Started
  • API Reference

Community

  • GitHub
  • Discord

Copyright © 2024 Aqua. All rights reserved.

On this page

Choose Your SDKSigning MethodsSigning Setup DetailsWitnessing MethodsWitnessing Setup DetailsJavaScript SDK Usage (v3)Complete Workflow ExampleMore ExamplesRust SDK Usage (v4)Quick ExampleMore ResourcesNext Steps