JavaScript / TypeScript SDK for the Proof of Human network.
Works in Node.js 18+, modern browsers, and Deno.
npm install @poh_network/sdk
import { POHClient } from '@poh_network/sdk'
const poh = new POHClient({
baseUrl: 'https://miner.proofofhuman.ge',
localBaseUrl: 'http://127.0.0.1:3456',
})
const { result, brainKey } = await poh.scan('0xabc...')
const verdict = await poh.pollBrainVerdict(brainKey!)
console.log(verdict.verdict, verdict.confidence)
Skill jobs always require a fee — pass budget (POH), walletAddress, and
privateKeyPem so the SDK can sign the payment. The node verifies the
signature and debits the fee before it will run the job at all; it rejects
the request outright (no job ever runs) without a valid signed payment.
const ref = await poh.submitJob(
'What does vitalik.eth write about on Paragraph?',
{ budget: 0.5, walletAddress: 'poh...', privateKeyPem: myPrivateKey },
)
const result = await poh.pollJobResult(ref.jobId)
console.log(result.output)
console.log(result.nlResponse)
const result = await poh.askAndWait(
'What NFTs does gmoney.eth hold?',
{ budget: 0.5, walletAddress: 'poh...', privateKeyPem: myPrivateKey },
)
Run inference with a model of your choice, optionally grounded in a Hugging
Face dataset already installed on the node. Like skill jobs, compute jobs
are never free — runCompute always signs a fee payment.
const ref = await poh.runCompute('Summarize the top 5 rows', {
model: 'llama3.1:8b',
dataset: 'some-org/some-dataset',
budget: 0.5,
walletAddress: myAddress,
privateKeyPem: myPrivateKey,
})
const result = await poh.pollJobResult(ref.jobId)
console.log(result.output)
Before either of these will work, the wallet's signing key must be
registered with the node once via registerSigningKey() (see
Signing & transactions) — the node has no way to
verify a signature for a key it has never seen.
const { balance } = await poh.getBalance('poh...')
console.log(balance / 1e9, 'POH')
const { nonce } = await poh.getNonce('poh...')
const { entries } = await poh.getTransactionHistory('poh...', 50)
const info = await poh.getMinerInfo()
console.log(info.model, info.reputation)
import {
generateKeyPair,
buildTransfer,
signTransaction,
createSigningProof,
} from '@poh_network/sdk'
const kp = await generateKeyPair()
await poh.registerKeyPair(kp)
const { nonce } = await poh.getNonce(kp.address)
const tx = await buildTransfer(kp.address, recipient, 5.0, nonce + 1)
const signed = await signTransaction(tx, kp.signingPrivateKey)
const result = await poh.submitTransaction(signed)
console.log(result.txHash)
const result = await poh.transfer(kp.address, recipient, 5.0, kp.signingPrivateKey)
const skills = await poh.listSkills()
skills.forEach(s => console.log(s.id, s.feeMin))
const { jobId } = await poh.scanBulk(['0xaaa...', '0xbbb...', '0xccc...'])
const final = await poh.pollJob(jobId, {
interval: 2_000,
onProgress: j => console.log(`${j.percent}% complete`),
})
for await (const snap of poh.watchJob(jobId)) {
process.stdout.write(`\r${snap.percent}% (${snap.done}/${snap.total})`)
}
const { results } = await poh.scanAndWait(['0xaaa...', '0xbbb...'])
const poh = new POHClient({
nodes: [
'https://miner.proofofhuman.ge',
'https://proofofhuman.ge',
'https://poh.assetux.com',
]
})
import { POHClient, POHError } from '@poh_network/sdk'
try {
await poh.scan('0xabc...')
} catch (err) {
if (err instanceof POHError) {
console.error(`HTTP ${err.status}: ${err.message}`)
}
}
| Option |
Type |
Default |
Description |
baseUrl |
string |
— |
Single-node base URL |
nodes |
string[] |
Default public nodes |
Multiple nodes for failover |
apiKey |
string |
— |
API key (paid tier) |
walletAddress |
string |
— |
Wallet for free-tier accounting |
fetch |
FetchFn |
globalThis.fetch |
Custom fetch implementation |
timeout |
number |
30000 |
Per-request timeout (ms) |
localBaseUrl |
string |
— |
Local miner URL for wallet/tx/job writes (http://127.0.0.1:3456) |
| Method |
Description |
scan(input, opts?) |
Single-address scan |
scanBulk(inputs, opts?) |
Submit bulk scan job |
pollJob(jobId, opts?) |
Poll until job completes |
watchJob(jobId, opts?) |
Stream job snapshots |
scanAndWait(inputs, opts?) |
Bulk scan + poll in one call |
getBrainVerdict(brainKey) |
AI verdict for a scan |
pollBrainVerdict(brainKey, opts?) |
Poll until verdict resolves |
scanAndVerdict(input, opts?) |
Scan + verdict in one call |
| Method |
Description |
submitJob(question, opts?) |
Submit NL question. Skill jobs always require a fee — pass budget, walletAddress, privateKeyPem. |
runCompute(prompt, opts) |
Submit a job that runs a specific model (and optional dataset). Always requires a fee. |
getJobStatus(jobId) |
Poll job status |
getJobResult(jobId) |
Fetch completed result |
pollJobResult(jobId, opts?) |
Poll until result ready |
askAndWait(question, opts?) |
Submit + wait in one call |
| Method |
Description |
getBalance(address) |
Wallet balance in μPOH |
getNonce(address) |
Current account nonce |
getTransactionHistory(address, limit?) |
Transaction history |
getPendingTransactions() |
Mempool pending txs |
submitTransaction(tx) |
Submit pre-signed tx |
registerSigningKey(addr, pubKeyPem, proof) |
Register signing key |
transfer(from, to, amountPOH, privateKey, fee?, memo?) |
Full transfer flow |
| Export |
Description |
generateKeyPair() |
Fresh Ed25519 keypair (PKCS8 PEM) |
signData(message, privateKeyPem) |
Sign arbitrary data |
createSigningProof(address, privateKeyPem) |
Proof for key registration |
buildTransfer(from, to, amountPOH, nonce, fee?, memo?) |
Build unsigned tx |
signTransaction(tx, privateKeyPem) |
Sign a tx |
computeTxHash(tx) |
SHA-256 tx hash |
pemToBytes(pem) |
Decode PEM to bytes |
bytesToPem(bytes, type) |
Encode bytes to PEM |
computeJobPaymentHash(params) |
Canonical hash for a job fee payment (used internally by submitJob/runCompute) |
signJobPayment(params, privateKeyPem) |
Sign a job fee payment proof (used internally by submitJob/runCompute) |
| Method |
Description |
getNodeInfo() |
Node metadata (/healthz) |
getMinerInfo() |
Miner details (gas price, model, reputation) |
listSkills() |
Available skills on the node |
MIT