Skip to main content

Getting Started

This guide walks you through using the L{CORE} Attestor SDK to create verified claims from external data sources. Claims can be stored in the L{CORE} privacy layer (via Cartesi rollup on Arbitrum Sepolia) or verified off-chain.

Overview

L{CORE} is built on two core technologies:

flowchart LR
A[Your App] --> B[Attestor SDK]
B --> C[TEE Attestor]
C --> D[Reclaim Protocol]
C --> E[Cartesi Rollup]
E --> F[Arbitrum Sepolia]

Installation

npm install @reclaimprotocol/attestor-core

For NodeJS environments, download the ZK circuit files:

npm run download:zk-files

Creating Your First Claim

A "claim" is a cryptographically signed assertion that data from an external API matches certain criteria. The attestor verifies this without seeing your secrets (passwords, tokens, etc.).

Basic Example

import { createClaimOnAttestor } from '@reclaimprotocol/attestor-core'

const result = await createClaimOnAttestor({
// Provider name - 'http' is the generic HTTP provider
name: 'http',
// Public parameters (visible to attestor and verifiers)
params: {
url: 'https://api.example.com/user/profile',
method: 'GET',
// What to look for in the response
responseMatches: [
{ type: 'contains', value: '"verified": true' }
]
},
// Secret parameters (hidden from attestor via TLS redaction)
secretParams: {
headers: {
'Authorization': 'Bearer your-secret-token'
}
},
// Your wallet private key (signs the claim)
ownerPrivateKey: '0x...',
// Attestor server to use
client: { url: 'wss://attestor.reclaimprotocol.org/ws' }
})

// Check result
if (result.error) {
console.error('Claim failed:', result.error)
} else {
console.log('Claim created successfully!')
console.log('Claim data:', result.claim)
console.log('Attestor signature:', result.signatures.claimSignature)
}

Verifying a Claim

Anyone can verify a claim using the attestor's signature:

import { assertValidClaimSignatures } from '@reclaimprotocol/attestor-core'

// Throws an error if the claim or signature is invalid
await assertValidClaimSignatures(result)

// Or verify just the claim portion
await assertValidClaimSignatures({
claim: result.claim,
signatures: {
claimSignature: result.signatures.claimSignature,
attestorAddress: result.signatures.attestorAddress
}
})

L{CORE} Integration

When L{CORE} is enabled, attestations are automatically stored in the Cartesi rollup for on-chain verification.

Querying L{CORE} Data

Query the Cartesi node directly using the inspect endpoint:

// Query all provider schemas
const query = { type: 'all_provider_schemas', params: {} };
const url = `http://${CARTESI_NODE_IP}:10000/inspect/${encodeURIComponent(JSON.stringify(query))}`;

const response = await fetch(url);
const data = await response.json();

Available Query Types

Query TypeDescription
all_provider_schemasList registered provider schemas
attestations_by_ownerGet attestations for a wallet address
check_accessVerify if a grantee has access
aggregate_by_bucketGet anonymized bucket statistics

Example: Query Attestations by Owner

const query = {
type: 'attestations_by_owner',
params: {
owner: '0x1234567890abcdef1234567890abcdef12345678',
limit: 10,
offset: 0
}
};

const url = `http://${CARTESI_NODE_IP}:10000/inspect/${encodeURIComponent(JSON.stringify(query))}`;
const response = await fetch(url);

Production Endpoints

ServiceEndpoint
Cartesi Nodehttp://${CARTESI_NODE_IP}:10000
Attestor APIhttp://${ATTESTOR_IP}:8001

Contract Addresses (Arbitrum Sepolia)

ContractAddress
DApp0xAE0863401D5B953b89cad8a5E7c98f5136E9C26d
InputBox0x59b22D57D4f067708AB0c00552767405926dc768

Response Matching

The responseMatches parameter defines what the attestor looks for in the API response:

Contains Match

responseMatches: [
{ type: 'contains', value: 'success' }
]

Regex Match with Extraction

Named capture groups extract values into the claim context:

responseMatches: [
{
type: 'regex',
value: '"balance":\\s*(?<balance>\\d+)'
}
]

// Result: claim.context.extractedParameters.balance = "1000"

JSONPath Match

responseMatches: [
{ type: 'jsonPath', value: '$.data.verified' }
]

Response Redactions

Control what parts of the response are visible to the attestor:

JSONPath Redaction

Only reveal specific JSON fields:

params: {
url: 'https://api.example.com/profile',
method: 'GET',
responseRedactions: [
{ jsonPath: '$.email' }, // Reveal email
{ jsonPath: '$.verified' } // Reveal verified status
],
responseMatches: [
{ type: 'contains', value: '"verified": true' }
]
}

TOPRF Hashing

Hash sensitive data consistently (for deduplication without revealing values):

responseRedactions: [
{ jsonPath: '$.userId', hash: 'oprf' }
]

CLI Usage

Create claims from the command line:

# Create a claim using a JSON config file
npm run create:claim -- --json claim-params.json

# Use a specific attestor
npm run create:claim -- --json claim-params.json --attestor wss://attestor.reclaimprotocol.org/ws

# Use local attestor (auto-started)
npm run create:claim -- --json claim-params.json --attestor local

# Use gnark ZK engine (faster on Linux x64/arm64)
npm run create:claim -- --json claim-params.json --zk gnark

Example claim-params.json:

{
"name": "http",
"params": {
"url": "https://api.example.com/verify",
"method": "GET",
"responseMatches": [
{ "type": "contains", "value": "verified" }
]
},
"secretParams": {
"headers": {
"Authorization": "Bearer {{API_TOKEN}}"
}
}
}

Environment variables in {{...}} are replaced from your .env file.

Error Handling

const result = await createClaimOnAttestor({ ... })

if (result.error) {
// Claim verification failed (attestor processed request but data didn't match)
console.error('Verification error:', result.error.message)
console.error('Error code:', result.error.code)
} else {
// Success
console.log('Claim:', result.claim)
}

// Network/connection errors throw exceptions
try {
const result = await createClaimOnAttestor({ ... })
} catch (err) {
// Connection failed, attestor unreachable, etc.
console.error('Connection error:', err)
}

Next Steps