Skip to main content
Welcome to the Cultura SDK! This toolkit enables developers to interact with Cultura, a Layer 2 Ethereum blockchain serving as the global registry for human creativity and intellectual property. This guide covers installation, initialization, configuration, and a basic usage example. Prerequisites:
  • Node.js and npm/yarn/pnpm installed.
  • Familiarity with TypeScript/JavaScript.
  • (Optional but Recommended) You have already set up your wallet and bridged funds using the main Quick Start Guide.

1. Installation

Install the SDK package into your project:
npm install @cultura/sdk
# or
yarn add @cultura/sdk
# or
pnpm add @cultura/sdk

2. Initialization Methods

The Cultura SDK offers different initialization methods depending on your use case:

Read-Only Access: create()

Use this when you only need to query data or don’t have a connected wallet.
import { CulturaSDK } from '@cultura/sdk';

// Create SDK instance with default configuration (testnet) read-only
const readOnlySdk = CulturaSDK.create();

// Create SDK instance for a specific environment (read-only)
const devnetSdk = CulturaSDK.create({ chain: 'devnet' });
const localSdk = CulturaSDK.create({ chain: 'local' });

Wallet-Connected Access: createWithWallet()

Use this for frontend dApps where the user connects their browser wallet (like MetaMask).
import { CulturaSDK } from '@cultura/sdk';

// Create SDK instance with wallet connection (uses testnet by default)
// Assumes 'window.ethereum' is available
const walletSdk = CulturaSDK.createWithWallet(window.ethereum);

// Create SDK instance with wallet connection and specific chain
const localWalletSdk = CulturaSDK.createWithWallet(window.ethereum, {
  chain: 'local',
});

Account-Specific Access: createWithAccount()

Use this for backend scripts, testing, or when you have direct access to an account address or private key.
import { CulturaSDK } from '@cultura/sdk';
import { privateKeyToAccount } from 'viem/accounts';

// Create SDK instance with a specific account address (limited signing capability)
const addressSdk = CulturaSDK.createWithAccount('0x123...' as `0x${string}`, {
  chain: 'testnet',
}); // Replace with actual address

// Create SDK instance with an account from a private key (full signing capability)
// WARNING: Handle private keys securely, especially in backend environments.
const account = privateKeyToAccount('0xYourPrivateKeyHere'); // Replace with actual private key
const privateKeySdk = CulturaSDK.createWithAccount(account, {
  chain: 'testnet',
});

3. Configuration Options

When creating an SDK instance, you can provide a configuration object:
const config = {
  // Chain identifier: 'local', 'devnet', 'testnet', or a chain ID number
  chain: 'testnet',

  // Optional: Provide a custom Viem Transport (e.g., for custom RPC)
  // transport: http('https://your-custom-rpc.com'),

  // Optional: Provide a pre-configured Viem WalletClient
  // wallet: existingWalletClient,

  // Optional: Specify the account (address or Viem Account object)
  // account: '0x...' or accountObject,

  // Optional: Override default contract addresses for the selected chain
  contracts: {
    attestationService: '0x...',
    culturaDigitalAsset: '0x...',
    // ... other contract addresses if needed
  }
};

const sdk = CulturaSDK.create(config);
// or CulturaSDK.createWithWallet(provider, config);
// or CulturaSDK.createWithAccount(account, config);

Environments

The chain property determines which contract addresses and RPC endpoints to use:
  • local: Local development (e.g., Hardhat node at http://127.0.0.1:8545, Chain ID 31337).
  • devnet: Cultura Devnet (experimental, RPC: https://rpc-yelling-tomato-whale-2ib9sndb39.t.conduit.xyz, Chain ID 26156).
  • testnet (default): Cultura Testnet (stable, RPC: https://sepolia.cultura.xyz, Chain ID 61892).

4. Basic Usage Example (Verify Setup)

After initializing the SDK, you can perform basic operations. Here’s how to check the balance of the connected account (requires a wallet-connected SDK):
async function checkBalance(sdk: CulturaSDK) {
  if (!sdk.walletClient?.account) {
    console.log("Wallet not connected. Cannot fetch balance.");
    // Try a read-only operation instead
    try {
      const totalSupply = await sdk.culturaDigitalAsset.totalSupply();
      console.log(`Read-only check: Total CulturaDigitalAsset supply: ${totalSupply}`);
    } catch (readError) {
      console.error("Failed to perform read-only check:", readError);
    }
    return;
  }

  try {
    const balance = await sdk.getWalletBalance();
    console.log(`Wallet balance: ${balance} wei`);
  } catch (error) {
    console.error("Error fetching wallet balance:", error);
  }
}

// Example with a wallet-connected SDK
// const myWalletSdk = CulturaSDK.createWithWallet(window.ethereum);
// checkBalance(myWalletSdk);

// Example with a read-only SDK (will log the read-only check)
// const myReadOnlySdk = CulturaSDK.create({ chain: 'testnet' });
// checkBalance(myReadOnlySdk);

5. Core Features Overview

The SDK provides access to various modules:
  • sdk.culturaDigitalAsset: Mint and manage original and licensed assets.
  • sdk.attestationService: Create and verify attestations (Levels 0-2).
  • sdk.schemaRegistry: Register and manage attestation schemas.
  • sdk.bondToken: Interact with the ERC20 token used for bonding/payments (approve, check balance).
  • sdk.royalty: Manage royalty reporting and payments (using the reference module).
  • sdk.rightsBoundAccount: Interact directly with an asset’s RBA for claims (requires setRightsBoundAccount).
  • sdk.verifierModule: Manage verifier rewards.
  • sdk.query: Efficiently read indexed data from the Subgraph (assets, verified rights).
  • sdk.mockLicensingProtocol: (Testnets only) Simulate licensing flows.

6. Next Steps

Appendix: Usage with Frontend Frameworks (React Example)

import React, { createContext, useContext, useEffect, useState } from "react";
import { CulturaSDK, getChainName } from "@cultura/sdk";
// Assume you have a hook or library to manage wallet connection (e.g., RainbowKit, Wagmi, Web3Modal)
import { useWallet } from "your-wallet-provider"; // Replace with your actual wallet hook

const SDKContext = createContext<CulturaSDK | null>(null);

export function useSDK() {
  const context = useContext(SDKContext);
  // Return null if used outside the provider, allows for conditional logic
  return context;
}

export function SDKProvider({ children }: { children: React.ReactNode }) {
  // Adapt these based on your wallet provider's state
  const { isConnected, provider, chainId, account } = useWallet();
  const [sdk, setSdk] = useState<CulturaSDK | null>(null);

  useEffect(() => {
    // Only initialize SDK if wallet is connected and provider exists
    if (!isConnected || !provider || !chainId || !account) {
      // Optionally create a read-only SDK as a fallback
      setSdk(CulturaSDK.create({ chain: 'testnet' })); // Fallback to testnet read-only
      console.log("Cultura SDK initialized in read-only mode (wallet not connected).");
      return;
    }

    try {
      // Create SDK with wallet connection
      // Note: 'provider' might need adjustment based on your library (e.g., Ethers provider, Viem transport)
      // The SDK expects an EIP-1193 compliant provider (like window.ethereum or WalletConnect provider)
      const newSdk = CulturaSDK.createWithWallet(provider, {
        chain: getChainName(chainId), // Ensure getChainName handles your supported chain IDs
        account: account as `0x${string}`,
      });
      setSdk(newSdk);
      console.log("Cultura SDK initialized with wallet connection.");
    } catch (error) {
      console.error("Failed to initialize Cultura SDK with wallet:", error);
      // Handle cases where the chainId might not be supported by the SDK
      // Fallback to a read-only instance
      setSdk(CulturaSDK.create({ chain: 'testnet' }));
      console.log("Cultura SDK initialized in read-only mode (wallet connection failed or unsupported chain).");
    }
  }, [isConnected, provider, chainId, account]); // Re-run effect if connection state changes

  return <SDKContext.Provider value={sdk}>{children}</SDKContext.Provider>;
}