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