Node.js and Express
import express from 'express';
import crypto from 'node:crypto';
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
const POL_API = 'https://api.heliusnetwork.app';
const POL_SECRET = process.env.POL_SECRET; // sk_...
async function siteverify(fields) {
const r = await fetch(`${POL_API}/v1/siteverify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ secret: POL_SECRET, ...fields }),
});
return r.json();
}
// PoL Gate on a sign-up form
app.post('/signup', async (req, res) => {
const result = await siteverify({ response: req.body['pol-token'] });
if (!result.success) return res.status(400).send('Please complete the Proof-of-Life check.');
// result.subject is a stable pseudonymous id for this person on your site:
// use it to stop the same person creating many accounts.
res.send('Welcome!');
});
// PoL Step-up before a transfer
const accountHint = (userId) =>
crypto.createHmac('sha256', process.env.HINT_SALT).update(String(userId)).digest('base64url');
app.post('/transfer/start', async (req, res) => {
const r = await fetch(`${POL_API}/v1/stepup/start`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ secret: POL_SECRET, action: 'transfer', account_hint_hash: accountHint(req.user.id) }),
});
res.json(await r.json()); // { client_token } goes to the browser
});
app.post('/transfer/confirm', async (req, res) => {
const result = await siteverify({
response: req.body.token,
expected_action: 'transfer',
expected_account_hint_hash: accountHint(req.user.id),
});
if (!result.success) return res.status(403).json(result);
// perform the transfer
res.json({ ok: true });
});
Browser side of the step-up:
const { client_token } = await (await fetch('/transfer/start', { method: 'POST' })).json();
const token = await PoL.execute('pk_your_site_key', { action: 'transfer', stepup: client_token });
await fetch('/transfer/confirm', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token }) });
Proof-of-Life is in early access. Request keys, read the API reference or the privacy notice.