Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kynesys.xyz/llms.txt

Use this file to discover all available pages before exploring further.

TLSNotary API Reference

TLSNotaryService Class

The TLSNotaryService class manages attestation tokens and proof storage. It provides methods for both direct execution and wallet-confirmation flows.
import { TLSNotaryService } from '@kynesyslabs/demosdk/tlsnotary';

const service = new TLSNotaryService(demos);

Methods

requestAttestation()

Requests an attestation token for a target URL. Burns 1 DEM and returns a proxy URL.
const { proxyUrl, tokenId, expiresAt } = await service.requestAttestation({
    targetUrl: 'https://api.example.com/data'
});

requestAttestationWithConfirmation()

Same as requestAttestation() but allows user confirmation before broadcasting. Recommended for wallet extension apps.
const response = await service.requestAttestationWithConfirmation(
    { targetUrl: 'https://api.example.com/data' },
    {
        onConfirm: async (details) => {
            // Show transaction to user for approval
            // details.txHash, details.amount, details.description
            return await showUserConfirmDialog(details);
        }
    }
);

createTLSNotary()

Convenience method that handles the full setup: request token → get proxy → create TLSNotary instance → initialize WASM.
const { tlsn, tokenId, proxyUrl } = await service.createTLSNotary({
    targetUrl: 'https://api.example.com/data'
});

// Ready to attest immediately!
const result = await tlsn.attest({ url: 'https://api.example.com/data' });

createTLSNotaryWithConfirmation()

Same as createTLSNotary() but with user confirmation. Recommended for wallet extension apps.
const { tlsn, tokenId } = await service.createTLSNotaryWithConfirmation(
    { targetUrl: 'https://api.example.com/data' },
    {
        onConfirm: async (details) => {
            return await showUserConfirmDialog(details);
        }
    }
);

storeProof()

Stores an attestation proof on-chain or IPFS.
const { txHash, storageFee } = await service.storeProof(
    tokenId,
    JSON.stringify(presentation),
    { storage: 'onchain' } // or 'ipfs'
);

storeProofWithConfirmation()

Same as storeProof() but with user confirmation. Recommended for wallet extension apps.
const { txHash, storageFee } = await service.storeProofWithConfirmation(
    tokenId,
    JSON.stringify(presentation),
    { storage: 'onchain' },
    {
        onConfirm: async (details) => {
            return await showUserConfirmDialog(details);
        }
    }
);

calculateStorageFee()

Calculate the fee for storing a proof.
const fee = service.calculateStorageFee(5); // 6 DEM for 5KB proof (1 base + 5 per KB)

Response Types

AttestationTokenResponse

interface AttestationTokenResponse {
    proxyUrl: string;      // WebSocket proxy URL for attestation
    tokenId: string;       // Unique token ID
    expiresAt: number;     // Unix timestamp when token expires
    retriesLeft: number;   // Number of retry attempts remaining
}

StoreProofResponse

interface StoreProofResponse {
    txHash: string;          // Transaction hash
    storageFee: number;      // Total fee burned (in DEM)
    broadcastStatus: number; // HTTP status (200 = success)
    broadcastMessage?: string;
}

TransactionDetails (for confirmation callbacks)

interface TransactionDetails {
    transaction: any;      // The signed transaction object
    txHash: string;        // Transaction hash
    amount: number;        // Amount in DEM being burned
    description: string;   // Human-readable description
    targetUrl?: string;    // For attestation requests
    tokenId?: string;      // For store transactions
}

Native Transaction Types

TLSNotary uses two native transaction types:

tlsn_request

Requests a TLSNotary attestation. Creates an access token for the proxy.
// SDK handles this internally
const tx = await demos.createTransaction({
    type: "native",
    data: ["native", {
        nativeOperation: "tlsn_request",
        args: [targetUrl]
    }]
})
Cost: 1 DEM (burned as fee)

tlsn_store

Stores the proof on-chain after notarization completes.
// SDK handles this internally
const tx = await demos.createTransaction({
    type: "native",
    data: ["native", {
        nativeOperation: "tlsn_store",
        args: [proofId, proofData]
    }]
})
Cost: 1 DEM base + 1 DEM per KB (burned as storage fee)

Cost Structure

OperationBase CostVariable CostNotes
tlsn_request1 DEM-Initial request fee
tlsn_store1 DEM+1 DEM/KBStorage fee based on proof size
GasStandard-Network transaction gas
Example costs:
  • Small proof (1KB): 1 + 1 + 1 = 3 DEM + gas
  • Medium proof (5KB): 1 + 1 + 5 = 7 DEM + gas
  • Large proof (20KB): 1 + 1 + 20 = 22 DEM + gas

Error Codes

CodeDescriptionResolution
TLSN_INVALID_URLURL is not accessible or malformedVerify URL format and accessibility
TLSN_TIMEOUTNotarization timed outRetry or check target server
TLSN_INSUFFICIENT_BALANCENot enough DEM for feesTop up DEM balance
TLSN_PROOF_TOO_LARGEProof exceeds maximum sizeReduce response size or use redactions
TLSN_TOKEN_EXPIREDAccess token expiredRequest will auto-retry
TLSN_PROXY_UNAVAILABLENo proxy available for domainWait and retry

TLSNotary Class

The TLSNotary class performs the actual WASM-based attestation. Use it after getting a proxy URL from TLSNotaryService.
import { TLSNotary } from '@kynesyslabs/demosdk/tlsnotary';

const tlsn = new TLSNotary({
    notaryUrl: 'http://notary.example.com:7047',
    websocketProxyUrl: proxyUrl, // From TLSNotaryService
});

await tlsn.initialize(); // Load WASM

const result = await tlsn.attest({
    url: 'https://api.example.com/data',
    method: 'GET',
    headers: { 'Accept': 'application/json' },
});

attest() Parameters

ParameterTypeRequiredDescription
urlstringYesThe target HTTPS URL to attest
method"GET" or "POST"NoHTTP method (default: “GET”)
headersRecord<string, string>NoCustom headers to include
bodystringNoRequest body for POST requests
commitCommitRangesNoByte ranges to include in proof
maxSentDatanumberNoMax sent data in bytes (default: 16384)
maxRecvDatanumberNoMax receive data in bytes (default: 16384)

attest() Response

interface AttestResult {
    presentation: PresentationJSON;  // The proof data
    sent: string;                    // Sent request data
    recv: string;                    // Received response data
    time: number;                    // Attestation timestamp
    serverName: string;              // Server hostname
}

verify()

Verify an attestation proof:
const result = await tlsn.verify(presentationJSON);
// result: { time, serverName, sent, recv, notaryKey, verifyingKey }

Wallet Extension Integration

For production dApps, users connect via wallet extensions which handle key management. The SDK supports a 3-step flow for wallet extensions:

The 3-Step Wallet Flow

  1. Generate Transaction: Create the unsigned transaction
  2. Sign & Confirm: Send to wallet extension for user approval and signing
  3. Broadcast: Send the signed transaction to the network
The WithConfirmation methods implement this pattern:
// Example: Full attestation with wallet extension flow
const service = new TLSNotaryService(demos);

// Step 1 & 2: Generate and get user confirmation
const { tlsn, tokenId } = await service.createTLSNotaryWithConfirmation(
    { targetUrl: 'https://api.example.com/data' },
    {
        onConfirm: async (details) => {
            // In a dApp, this would show a modal to the user:
            // "Confirm burning 1 DEM for attestation?"
            // The wallet extension signs when user approves
            return await walletExtension.requestApproval(details.transaction);
        }
    }
);

// Step 3: Perform attestation (no blockchain interaction)
const result = await tlsn.attest({ url: 'https://api.example.com/data' });

// Step 1 & 2 again: Store proof with confirmation
await service.storeProofWithConfirmation(
    tokenId,
    JSON.stringify(result.presentation),
    { storage: 'onchain' },
    {
        onConfirm: async (details) => {
            // "Confirm burning 6 DEM to store proof?"
            return await walletExtension.requestApproval(details.transaction);
        }
    }
);

Custom Headers

const result = await tlsn.attest({
    url: "https://api.example.com/data",
    headers: {
        "Authorization": "Bearer your-token",
        "X-Custom-Header": "value"
    }
});

POST Requests

const result = await tlsn.attest({
    url: "https://api.example.com/submit",
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify({ key: "value" })
});

Commit Ranges (Selective Disclosure)

Control which parts of the request/response to include in the proof:
const result = await tlsn.attest({
    url: "https://api.example.com/data",
    commit: {
        sent: [{ start: 0, end: 100 }],  // Include first 100 bytes of request
        recv: [{ start: 0, end: 500 }],  // Include first 500 bytes of response
    }
});
Larger commit ranges result in larger proofs, which increase storage costs. Only include the data you need to prove.