GitHub ↗
Verified v1
PF
Integration

Quick start

The safest integration pattern is: create or select an immutable policy, create an exact intent, evaluate it through consensus, wait for the lifecycle point your application requires, then rely on authorization only after an exact currentness read.

Studio Dev is a release-candidate preview on chain 61997 and may reset. Pin the matching GenLayerJS v2 RC when using that network. For durable production-like validation, GenLayer recommends Bradbury after compatible release promotion.

1. Install the matching client

terminal
npm install genlayer-js

For Studio Dev / Consensus v0.6 preview, use the explicit v2.0 release candidate published by GenLayer rather than assuming the default npm tag resolves to a prerelease.

2. Create a Studio Dev client

For browser writes, use the connected wallet address with its EIP-1193 provider and ensure the wallet is on the same Studio Dev chain definition before signing.

client.ts
import { createClient, isSuccessful } from 'genlayer-js';
import { studioDevnet } from 'genlayer-js/chains';

const client = createClient({
  chain: studioDevnet,
  account: walletAddress,
  provider: window.ethereum,
});

const POLICYFUSE = '0xF5066aE61456b1ADEC4871Da1650F64F1aE5C43F';
Fee note: estimateTransactionFeesForWrite is appropriate for development/profiling. For production application flows, GenLayer recommends a measured, checked-in fee profile or Transaction Kit rather than simulating every user click.

3. Create an exact intent

The action core should contain only the consequence-bearing data your policy is written to evaluate. Keep clarification separate so repair can add context without silently replacing the action.

create-intent.ts
const call = {
  address: POLICYFUSE,
  functionName: 'create_intent',
  args: [policyId, consumer, 'VERIFY', actionCoreJson, clarification, deadline],
};

const estimate = await client.estimateTransactionFeesForWrite(call);
const txId = await client.writeContract({
  ...call,
  fees: { distribution: estimate.distribution, feeValue: estimate.feeValue },
});

const createReceipt = await client.waitForFinalization({ hash: txId });
if (!isSuccessful(createReceipt)) {
  throw new Error(`Intent creation failed: ${createReceipt.statusName} / ${createReceipt.txExecutionResultName}`);
}

4. Evaluate through consensus

evaluate.ts
const evaluate = {
  address: POLICYFUSE,
  functionName: 'evaluate_intent',
  args: [intentId],
};

const fees = await client.estimateTransactionFeesForWrite(evaluate);
const evaluationTx = await client.writeContract({
  ...evaluate,
  fees: { distribution: fees.distribution, feeValue: fees.feeValue },
});

const evaluationReceipt = await client.waitForFinalization({ hash: evaluationTx });
if (!isSuccessful(evaluationReceipt)) {
  throw new Error(`Evaluation failed: ${evaluationReceipt.statusName} / ${evaluationReceipt.txExecutionResultName}`);
}

5. Read the verdict from durable state

verdict.ts
import { TransactionHashVariant } from 'genlayer-js/types';

const verdict = await client.readContract({
  address: POLICYFUSE,
  functionName: 'get_verdict',
  args: [intentId],
  transactionHashVariant: TransactionHashVariant.LATEST_FINAL,
});

6. Before acting, verify exact currentness

authorize.ts
const current = await client.readContract({
  address: POLICYFUSE,
  functionName: 'is_authorization_current_for',
  args: [authorizationId, consumer, actionCoreDigest],
  transactionHashVariant: TransactionHashVariant.LATEST_FINAL,
});

if (!current) {
  throw new Error('PolicyFuse authorization is not current');
}

// Only now attach your application's consequence.
Integration rule: PolicyFuse authorizes semantics; your application owns the downstream consequence and any application-specific single-use replay protection.

Official references