Skip to Content
This project is an early work in progress. Funded by Project Catalyst.
ProviderCoreCore Module - Introduction

Core Module - Introduction

The Core module provides direct, low-level access to Andamio protocol data stored on the Cardano blockchain. It serves as the foundation layer for all higher-level provider functionality, offering precise control over data retrieval and state management.

const sdk = new AndamioSDK("https://preprod.utxorpc-v0.demeter.run:443", "Preprod", "dmtr_utxorpc...") const coreProvider = sdk.provider.core

Overview

The Core module is designed for developers who need direct access to Andamio’s on-chain data structures. It provides unfiltered access to UTXOs, datums, and protocol state without abstraction layers, making it ideal for building custom analytics, debugging protocol interactions, or implementing advanced features.

Key Characteristics

  • Direct Blockchain Access: Raw UTXO and datum retrieval from validators
  • Protocol-Level Operations: Low-level access to Andamio smart contract states
  • Type-Safe Data: Strongly typed interfaces for all Andamio data structures
  • Network Agnostic: Works across all Cardano networks (Mainnet, Preprod, Preview)
  • Performance Optimized: Efficient queries with minimal data processing overhead

Architecture

The Core module is organized into specialized components that handle different aspects of the Andamio protocol:

class Core { // Configuration and network information public readonly andamioConfig: AndamioConfig; public readonly network: string; // Core data access components public aliasIndex: AliasIndex; // User alias management public globalState: GlobalState; // Cross-platform user state public indexReference: IndexReference; // Protocol reference data public userAccessToken: UserAccessToken; // User authentication tokens public localStates: LocalStates; // Course/project specific states }

Component Responsibilities

Alias Index

Manages the platform-wide alias system that provides human-readable identifiers for users.

// Check if an alias is available const availableUtxo = await core.aliasIndex.getUtxoByNewAlias("potential_alias"); // Get existing alias data const aliasData = await core.aliasIndex.getUtxoByExistingAlias("existing_user");

Global State

Tracks user enrollments, completions, and cross-platform achievements.

// Get user's global state const globalStateUtxo = await core.globalState.getUtxoByAlias("student_alice"); // Get all global states (for analytics) const allGlobalStates = await core.globalState.getUtxos();

Index Reference

Provides access to protocol configuration and reference data.

// Get protocol configuration const observerStakeAddress = await core.indexReference.getObserverStakeAddress(); const treasuryAddress = await core.indexReference.getProtocolTreasuryAddress(); const protocolFee = await core.indexReference.getProtocolFeeAmountInLovelace();

User Access Token

Manages user authentication and authorization tokens.

// Get user address from alias const userAddress = await core.userAccessToken.getAddressByAlias("instructor_bob"); // Validate user access const hasValidToken = await core.userAccessToken.validateTokenForAlias("instructor_bob");

Local States

Provides access to course and project-specific state data.

// Course-related states const courseState = await core.localStates.course.courseState.getUtxoByAlias( "blockchain-course", "student_charlie" ); // Project-related states const projectState = await core.localStates.project.contributorState.getUtxoByAlias( "defi-project", "contributor_diana" ); // Instance governance const governance = await core.localStates.instanceGovernance.getUtxoByCourseIdOrProjectId( "advanced-smart-contracts" );

Data Access Patterns

Direct UTXO Retrieval

The Core module returns raw UTXO objects with minimal processing:

interface AndamioUtxo { input: { txHash: string; outputIndex: number; }; output: { address: string; amount: Asset[]; plutusData?: PlutusData; }; parsedValued?: { datum?: { payload: PlutusData; }; script?: Script; }; }

Datum Parsing

While the Core module returns raw data, it includes parsed datum information when available:

const utxo = await core.globalState.getUtxoByAlias("user_alice"); // Raw plutus data const rawDatum = utxo.output.plutusData; // Parsed datum (if available) const parsedDatum = utxo.parsedValued?.datum?.payload; // Use appropriate parser for the datum type const globalStateDatum = parseGlobalStateDatum(parsedDatum);

Common Usage Patterns

User State Investigation

async function investigateUserState(alias: string) { try { // Get all user-related data const globalState = await core.globalState.getUtxoByAlias(alias); const userAddress = await core.userAccessToken.getAddressByAlias(alias); // Parse global state to see enrollments const enrollments = parseGlobalStateDatum(globalState.parsedValued?.datum?.payload); // Get course states for each enrollment const courseStates = await Promise.all( enrollments.courses.map(courseId => core.localStates.course.courseState.getUtxoByAlias(courseId, alias) ) ); return { alias, userAddress, globalState: enrollments, courseStates: courseStates.filter(state => state !== null) }; } catch (error) { console.error(`Error investigating user state for ${alias}:`, error); throw error; } }

Course State Analysis

async function analyzeCourseState(courseId: string) { try { // Get all course-related UTXOs const courseStates = await core.localStates.course.courseState.getUtxos(courseId); const assignmentStates = await core.localStates.course.assignmentState.getUtxos(courseId); const moduleReferences = await core.localStates.course.moduleRef.getUtxos(courseId); const governance = await core.localStates.instanceGovernance.getUtxoByCourseIdOrProjectId(courseId); return { courseId, enrolledStudents: courseStates.length, pendingAssignments: assignmentStates.length, totalModules: moduleReferences.length, governance: governance ? parseInstanceGovernanceDatum(governance.parsedValued?.datum?.payload) : null }; } catch (error) { console.error(`Error analyzing course state for ${courseId}:`, error); throw error; } }

Platform Health Check

async function platformHealthCheck() { try { // Check core protocol components const aliasIndexHealth = await checkAliasIndexHealth(); const globalStateHealth = await checkGlobalStateHealth(); const referenceDataHealth = await checkReferenceDataHealth(); return { status: 'healthy', components: { aliasIndex: aliasIndexHealth, globalState: globalStateHealth, referenceData: referenceDataHealth }, timestamp: new Date().toISOString() }; } catch (error) { return { status: 'unhealthy', error: error.message, timestamp: new Date().toISOString() }; } } async function checkAliasIndexHealth() { try { // Try to query a known alias or check index state const indexUtxos = await core.aliasIndex.getUtxos(); return { status: 'healthy', count: indexUtxos.length }; } catch (error) { return { status: 'error', error: error.message }; } }

Advanced Features

Custom Query Builders

class CustomQueryBuilder { constructor(private core: Core) {} // Build complex queries using core components async getUserCompletionAnalytics(alias: string) { const globalState = await this.core.globalState.getUtxoByAlias(alias); const enrollments = parseGlobalStateDatum(globalState.parsedValued?.datum?.payload); const completionData = await Promise.all( enrollments.courses.map(async (courseId) => { const courseState = await this.core.localStates.course.courseState.getUtxoByAlias(courseId, alias); const modules = await this.core.localStates.course.moduleRef.getUtxos(courseId); return { courseId, totalModules: modules.length, completedModules: courseState ? parseCompletedModules(courseState) : 0 }; }) ); return completionData; } }

Real-time Monitoring

class StateMonitor { private subscriptions = new Map(); constructor(private core: Core) {} async monitorUserState(alias: string, callback: (state: any) => void) { // Implement polling or webhook-based monitoring const monitor = setInterval(async () => { try { const currentState = await this.core.globalState.getUtxoByAlias(alias); callback(currentState); } catch (error) { console.error(`Error monitoring ${alias}:`, error); } }, 30000); // Poll every 30 seconds this.subscriptions.set(alias, monitor); } stopMonitoring(alias: string) { const monitor = this.subscriptions.get(alias); if (monitor) { clearInterval(monitor); this.subscriptions.delete(alias); } } }

Configuration Access

The Core module provides access to the underlying Andamio configuration:

// Network information const network = core.network; // "Mainnet", "Preprod", or "Preview" // Protocol addresses const config = core.andamioConfig; const globalStateAddress = config.globalStateS.sCAddress; const indexAddress = config.indexMS.mSCAddress; // Policy IDs const accessTokenPolicy = config.indexMS.mSCPolicyID; // Reference transaction data const globalStateRefTx = config.globalStateRefMS.mSCTxRef;

Error Handling

Network Errors

try { const data = await core.globalState.getUtxoByAlias("user_alias"); } catch (error) { if (error.message.includes('network')) { // Handle network connectivity issues console.error("Network error:", error); } else if (error.message.includes('not found')) { // Handle data not found scenarios console.warn("Data not found:", error); } else { // Handle other errors console.error("Unexpected error:", error); } }

Data Validation

async function safeDataRetrieval(alias: string) { try { const utxo = await core.globalState.getUtxoByAlias(alias); // Validate data structure if (!utxo.parsedValued?.datum?.payload) { throw new Error("Invalid datum structure"); } return utxo; } catch (error) { console.error("Data retrieval failed:", error); return null; } }

Performance Considerations

Efficient Queries

// Good: Batch queries when possible const allCourseStates = await core.localStates.course.courseState.getUtxos(); // Avoid: Sequential individual queries // const states = []; // for (const alias of aliases) { // const state = await core.localStates.course.courseState.getUtxoByAlias(courseId, alias); // states.push(state); // }

Caching Strategy

class CoreDataCache { private cache = new Map(); private ttl = 60000; // 1 minute TTL async getCachedData(key: string, fetcher: () => Promise<any>) { const cached = this.cache.get(key); if (cached && Date.now() - cached.timestamp < this.ttl) { return cached.data; } const data = await fetcher(); this.cache.set(key, { data, timestamp: Date.now() }); return data; } }

Best Practices

1. Data Validation

  • Always validate returned UTXO structures before processing
  • Check for null/undefined values in parsed data
  • Implement type guards for complex datum structures

2. Error Handling

  • Implement comprehensive error handling for network operations
  • Use specific error types for different failure scenarios
  • Provide fallback mechanisms for critical operations

3. Performance Optimization

  • Use batch queries when fetching related data
  • Implement appropriate caching for frequently accessed data
  • Avoid unnecessary repeated queries in loops

4. Security Considerations

  • Validate all input parameters before querying
  • Handle sensitive data appropriately
  • Implement proper access controls for administrative operations

5. Debugging and Monitoring

  • Log important operations with sufficient detail
  • Monitor query performance and error rates
  • Implement health checks for critical components
Last updated on