Overview
In this guide, you’ll create your first attestation from scratch using the AttestProtocol SDK. We’ll walk through:
- Setting up your environment
- Initializing the SDK
- Registering as an authority
- Creating a schema
- Issuing an attestation
- Verifying the attestation
This tutorial assumes you’ve already installed the SDK. If not, go back and install it first.
Step 1: Set Up Your Project
Create a new directory and initialize your project:
mkdir my-first-attestation
cd my-first-attestation
npm init -y
npm install @attestprotocol/sdk dotenv
Create your main file:
import { AttestSDK } from '@attestprotocol/sdk';
import 'dotenv/config';
async function main() {
console.log('Starting attestation tutorial...');
// We'll add code here step by step
}
main().catch(console.error);
Step 2: Initialize the SDK
Add your configuration to a .env file:
# Choose your blockchain
STELLAR_SECRET_KEY=SXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
STELLAR_PUBLIC_KEY=GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
STELLAR_RPC_URL=https://soroban-testnet.stellar.org
# Alternative: Solana configuration
# SOLANA_SECRET_KEY=[1,2,3,...]
# SOLANA_RPC_URL=https://api.devnet.solana.com
Get Test Credentials: For Stellar, generate test credentials at laboratory.stellar.org. For Solana, use solana-keygen new.
Initialize the SDK:
import { AttestSDK } from '@attestprotocol/sdk';
import 'dotenv/config';
async function main() {
console.log('Starting attestation tutorial...');
// Initialize Stellar SDK
const sdk = await AttestSDK.initializeStellar({
secretKeyOrCustomSigner: process.env.STELLAR_SECRET_KEY,
publicKey: process.env.STELLAR_PUBLIC_KEY,
url: process.env.STELLAR_RPC_URL || 'https://soroban-testnet.stellar.org'
});
console.log('Stellar SDK initialized');
}
main().catch(console.error);
Step 3: Register as Authority
Before issuing attestations, you need to register as an authority:
// Add this inside your main() function
try {
// Check if already registered
const existingAuthority = await sdk.fetchAuthority();
if (existingAuthority.error) {
console.log('Registering as authority...');
const authResult = await sdk.registerAuthority();
if (authResult.error) {
console.error('Failed to register authority:', authResult.error);
return;
}
console.log('Authority registered successfully');
} else {
console.log('Already registered as authority');
}
} catch (error) {
console.error('Authority registration error:', error);
return;
}
Step 4: Create a Schema
Schemas define the structure of your attestations:
// Add this after authority registration
try {
const schemaResult = await sdk.createSchema({
schemaName: `user-verification-${Date.now()}`,
schemaContent: 'verified:bool,level:string,score:uint8,timestamp:uint64',
revocable: true
});
if (schemaResult.error) {
console.error('Schema creation failed:', schemaResult.error);
return;
}
const schemaUID = schemaResult.data.schemaUID;
console.log('Schema created:', schemaUID);
} catch (error) {
console.error('Schema creation error:', error);
return;
}
Step 5: Issue an Attestation
Now let’s create an attestation using our schema:
// Add this after schema creation
try {
// Example subject address (replace with actual address)
const subjectAddress = 'GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const attestResult = await sdk.attest({
schemaUID: schemaUID,
subject: subjectAddress,
value: 'verified:true,level:enhanced,score:95,timestamp:' + Math.floor(Date.now() / 1000),
reference: `attestation-${Date.now()}`
});
if (attestResult.error) {
console.error('Attestation failed:', attestResult.error);
return;
}
console.log('Attestation created');
console.log('Transaction Hash:', attestResult.data);
} catch (error) {
console.error('Attestation error:', error);
return;
}
Step 6: Verify the Attestation
The most common operation - checking if a subject has a valid attestation:
// Add this after attestation creation
try {
// Wait a moment for indexing
console.log('Waiting for attestation to be indexed...');
await new Promise(resolve => setTimeout(resolve, 10000));
const fetchResult = await sdk.fetchAttestation({
schemaUID: schemaUID,
subject: subjectAddress
});
if (fetchResult.error) {
console.error('Verification failed:', fetchResult.error);
return;
}
if (fetchResult.data && !fetchResult.data.revoked) {
console.log('Attestation verified');
console.log('Attestation data:', fetchResult.data.value);
console.log('Created at:', new Date(fetchResult.data.timestamp * 1000).toLocaleString());
} else {
console.log('No valid attestation found');
}
} catch (error) {
console.error('Verification error:', error);
}
Complete Example
Here’s the complete working example for Stellar:
import { AttestSDK } from '@attestprotocol/sdk';
import 'dotenv/config';
async function main() {
console.log('Starting attestation tutorial...');
try {
// Initialize SDK
const sdk = await AttestSDK.initializeStellar({
secretKeyOrCustomSigner: process.env.STELLAR_SECRET_KEY,
publicKey: process.env.STELLAR_PUBLIC_KEY,
url: 'https://soroban-testnet.stellar.org'
});
console.log('Stellar SDK initialized');
// Register as authority
const existingAuthority = await sdk.fetchAuthority();
if (existingAuthority.error) {
const authResult = await sdk.registerAuthority();
if (authResult.error) throw new Error(authResult.error);
console.log('Authority registered');
} else {
console.log('Already registered as authority');
}
// Create schema
const schemaResult = await sdk.createSchema({
schemaName: `user-verification-${Date.now()}`,
schemaContent: 'verified:bool,level:string,score:uint8,timestamp:uint64',
revocable: true
});
if (schemaResult.error) throw new Error(schemaResult.error);
const schemaUID = schemaResult.data.schemaUID;
console.log('Schema created:', schemaUID);
// Create attestation
const subjectAddress = 'GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const attestResult = await sdk.attest({
schemaUID: schemaUID,
subject: subjectAddress,
value: `verified:true,level:enhanced,score:95,timestamp:${Math.floor(Date.now() / 1000)}`,
reference: `demo-${Date.now()}`
});
if (attestResult.error) throw new Error(attestResult.error);
console.log('Attestation created:', attestResult.data);
// Verify attestation
console.log('Waiting for indexing...');
await new Promise(resolve => setTimeout(resolve, 10000));
const fetchResult = await sdk.fetchAttestation({
schemaUID: schemaUID,
subject: subjectAddress
});
if (fetchResult.data && !fetchResult.data.revoked) {
console.log('Attestation verified');
console.log('Data:', fetchResult.data.value);
}
console.log('Tutorial completed successfully');
} catch (error) {
console.error('Error:', error.message);
}
}
main().catch(console.error);
Run Your Example
Save your code and run it:
You should see output like this:
Starting attestation tutorial...
Stellar SDK initialized
Already registered as authority
Schema created: a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890
Attestation created: 5KJp3F2B1Y8Z...
Waiting for indexing...
Attestation verified
Data: verified:true,level:enhanced,score:95,timestamp:1704067200
Tutorial completed successfully
Understanding the Results
Let’s break down what happened:
- Created a blockchain-specific SDK instance with your credentials
- Connected to the testnet for safe experimentation
- Established connection to the AttestProtocol smart contracts
- Registered your wallet as an authority capable of issuing attestations
- This is a one-time setup per wallet address
- Authorities can create schemas and issue attestations
- Created a reusable template defining the structure of verification data
- Each schema has a unique UID and defines field types and validation rules
- Schemas are stored on-chain and can be reused for multiple attestations
- Created a signed, verifiable claim about a subject’s verification status
- The attestation is stored on-chain with immutable cryptographic proof
- Data follows the schema structure with typed fields
- Retrieved and validated the attestation from the blockchain
- Checked for active status and parsed the structured data
- Confirmed the cryptographic integrity of the claim
Next Steps
Now that you’ve created your first attestation, explore these topics:
Common Issues
If you see “insufficient balance” errors:
- Ensure your wallet has test tokens for transaction fees
- For Stellar: Use the friendbot to fund your account
- For Solana: Use
solana airdrop 2 to get test SOL
- Double-check your secret key format and ensure it’s valid
- For Stellar: Secret keys start with ‘S’ and are 56 characters
- For Solana: Secret keys are 64-number arrays
- Never expose secret keys in production code
If you see “schema already exists”:
- Use a different schema name with a timestamp
- Or reference the existing schema instead of creating a new one
- Schema names must be unique per authority
Network Connection Issues
- Verify your RPC endpoint is accessible
- Check your internet connection
- Try switching to a different RPC provider if available
Pro Tip: Save the schema UID from your first run and reuse it in future attestations. You only need to create each schema once per authority!