Mint your DAT in Node.JS

This guide walks through the process of setting up your local environment, connecting your wallet, and minting your first Data Anchoring Token (DAT) using the LazAI Node.JS SDK.

It assumes familiarity with Node.JS, basic blockchain interactions, and access to the LazAI Pre-Testnet. For a guided walkthrough of the entire setup and minting process, watch the official tutorial: ➡️ https://youtu.be/ayD46LALXpo Prerequisites

  • Node.js ≥ 18.x (LTS)

  • A funded Testnet wallet (for gas)

  • Credentials:

    • PRIVATE_KEY – your wallet’s private key (starts with 0x)

    • IPFS_JWT – Pinata (or compatible) IPFS JWT

1) Project setup

mkdir LazAI-contribution
cd LazAI-contribution
npm init -y

2) Install SDK & dependencies

npm install alith@latest axios dotenv node-rsa ts-node typescript
npm install --save-dev @types/node-rsa

dotenv loads env vars, axios sends the proof request, node-rsa encrypts the symmetric key for the verifier.

3) Create files

index.ts

Create a file index.ts and paste:

import { config } from 'dotenv'
import { Client } from 'alith/lazai'
import { PinataIPFS } from 'alith/data/storage'
import { encrypt } from 'alith/data'
import NodeRSA from 'node-rsa'
import axios from 'axios'
import { promises as fs } from 'fs'

// Load environment variables
config()
 
async function main() {
  try {
    // Check for required environment variables
    const privateKey = process.env.PRIVATE_KEY
    const ipfsJwt = process.env.IPFS_JWT
    
    if (!privateKey) {
      throw new Error('PRIVATE_KEY environment variable is required')
    }
    
    if (!ipfsJwt) {
      console.warn('Warning: IPFS_JWT environment variable not set. IPFS operations may fail.')
    }
    
    // Initialize client with private key as third parameter
    const client = new Client(undefined, undefined, privateKey)
    const ipfs = new PinataIPFS()
    
    console.log('✅ Client initialized successfully')
    console.log('✅ IPFS client initialized successfully')
    
    // 1. Prepare your privacy data and encrypt it
    const dataFileName = 'your_encrypted_data.txt'
    const privacyData = 'Your Privacy Data'
    const encryptionSeed = 'Sign to retrieve your encryption key'
    const password = client.getWallet().sign(encryptionSeed).signature
    const encryptedData = await encrypt(Uint8Array.from(privacyData), password)
    
    console.log('✅ Data encrypted successfully')
    
    // 2. Upload the privacy data to IPFS and get the shared url
    const fileMeta = await ipfs.upload({
      name: dataFileName,
      data: Buffer.from(encryptedData),
      token: ipfsJwt || '',
    })
    const url = await ipfs.getShareLink({ token: ipfsJwt || '', id: fileMeta.id })
    
    console.log('✅ File uploaded to IPFS:', url)
    
    // 3. Upload the privacy url to LazAI
    let fileId = await client.getFileIdByUrl(url)
    if (fileId == BigInt(0)) {
      fileId = await client.addFile(url)
    }
    
    console.log('✅ File registered with LazAI, file ID:', fileId.toString())
    
    // 4. Request proof in the verified computing node
    await client.requestProof(fileId, BigInt(100))
    const jobIds = await client.fileJobIds(fileId)
    const jobId = jobIds[jobIds.length - 1]
    const job = await client.getJob(jobId)
    const nodeInfo = await client.getNode(job.nodeAddress)
    const nodeUrl = nodeInfo.url
    const pubKey = nodeInfo.publicKey
    const rsa = new NodeRSA(pubKey, 'pkcs1-public-pem')
    const encryptedKey = rsa.encrypt(password, 'hex')
    const proofRequest = {
      job_id: Number(jobId),
      file_id: Number(fileId),
      file_url: url,
      encryption_key: encryptedKey,
      encryption_seed: encryptionSeed,
      nonce: null,
      proof_url: null,
    }

    console.log('✅ Proof request prepared')

    // Write proof request to file
    await fs.writeFile('proof_request.json', JSON.stringify(proofRequest, null, 2))
    console.log('✅ Proof request saved to proof_request.json')
    
    const response = await axios.post(`${nodeUrl}/proof`, proofRequest, {
      headers: { 'Content-Type': 'application/json' },
    })
   
    if (response.status === 200) {
      console.log('✅ Proof request sent successfully')
    } else {
      console.log('❌ Failed to send proof request:', response.data)
    }
    
    // 5. Request DAT reward
    await client.requestReward(fileId)
    console.log('✅ Reward requested for file id', fileId.toString())
    
    console.log('All operations completed successfully!')
    
  } catch (error) {
    console.error('❌ Error in main function:', error)
    process.exit(1)
  }
}

// Execute the main function
main().catch((error) => {
  console.error('❌ Unhandled error:', error)
  process.exit(1)
})

4) Add tsconfig.json

Create tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "node16",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "allowJs": true,
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "ts-node": {
    "esm": true,
    "experimentalSpecifierResolution": "node"
  },
  "include": ["*.ts"],
  "exclude": ["node_modules"]
}

5) Set environment variables

Create a .env (recommended) or export in your shell:

# .env
PRIVATE_KEY=<your wallet private key>
IPFS_JWT=<your pinata ipfs jwt>

Your PRIVATE_KEY must start with 0x.

The script reads these via dotenv.

6) Run

 node --loader ts-node/esm index.ts

Expected output

✅ Client initialized successfully
✅ IPFS client initialized successfully
✅ Data encrypted successfully
✅ File uploaded to IPFS: https://...
✅ File registered with LazAI, file ID: <id>
✅ Proof request prepared
✅ Proof request saved to proof_request.json
✅ Proof request sent successfully
✅ Reward requested for file id <id>
All operations completed successfully!

Last updated