Mint your DAT in Node.JS

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 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) Update package.json

Use this minimal setup (versions can float as needed):

{
  "name": "lazai-client",
  "version": "1.0.0",
  "description": "LazAI client implementation",
  "main": "index.ts",
  "type": "module",
  "scripts": {
    "start": "node --loader ts-node/esm index.ts",
    "build": "tsc",
    "dev": "ts-node index.ts"
  },
  "dependencies": {
    "alith": "^0.11.1",
    "axios": "^1.6.7",
    "dotenv": "^17.2.1",
    "node-rsa": "^1.1.1",
    "ts-node": "^10.9.2",
    "typescript": "^5.3.3"
  },
  "devDependencies": {
    "@types/node-rsa": "^1.1.4"
  }
}

6) 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.


7) Run

npm run start

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!

Troubleshooting

  • PRIVATE_KEY environment variable is required

    Set it in .env or export it in your shell and rerun.

  • IPFS upload fails (401/403)

    Verify IPFS_JWT is valid and has pinning permissions.

  • ESM / BigInt / import errors

    Ensure Node.js ≥ 18, and use the provided tsconfig.json + package.json.

  • Insufficient funds or nonce errors

    Refill from the faucet, wait one block, retry.


Last updated