Skip to Content
DevelopersNTSNTS Interface

N1TS Runtime Interface

️⚠️
NTS is in active development and currently unstable. It is open to select early developers for exploration but is not yet suitable for production use. Follow developer updates for the latest changes, as performance is not at production level.

The N1TS runtime provides a comprehensive interface for smart contract development. This guide covers the functions and context available to N1TS applications during execution.

Important Note

The functions described here are automatically available within N1TS applications. You don’t need to import them - they are injected into the global scope during execution. This is different from external client interfaces like NAppClient which are used to interact with N1TS apps from outside applications.

Global Functions Available in N1TS Apps

Data Operations

// Read data from current or external app await nread(fieldId: string, appId?: string): Promise<any> // Read data specifically from external app (requires appId) await nread(fieldId: string, appId: string): Promise<any> // Write data to storage nwrite(fieldId: string, value: any, tag?: string, secondary_tag?: string): void

Example Usage:

class DataApp extends NApp { // This is an internal helper method, NOT a transaction action protected async readUserData(userId: string): Promise<any> { // Read from current app const userData = await nread(`user_${userId}`); // Read from external app const externalData = await nread('global_config', 'config_app_id'); return { userData, externalData }; } saveUserPreferences(userId: string, preferences: any): void { // Write with tags for organization nwrite( `preferences_${userId}`, JSON.stringify(preferences), 'user_data', userId ); } }

Token Operations

Note: Token functions must be imported from @n1xyz/nts-compiler

// These functions require import: // import { nmint, nmintEdit, ntransfer } from '@n1xyz/nts-compiler'; // Create a new token mint nmint(totalSupply: BigInt, admin: string, meta: string): void // Edit existing token properties (admin only) nmintEdit(mint: string, freeSupply: BigInt, admin: string, meta: string): void // Transfer tokens ntransfer(origin: string, destination: string, mint: string, amount: BigInt): void

Example Usage:

import { NApp, createExecutableFunctions, nmint, ntransfer } from '@n1xyz/nts-compiler'; class TokenApp extends NApp { createGameToken(): void { nmint( BigInt('1000000'), // 1M total supply this.signer(), // Current user as admin JSON.stringify({ // Metadata name: 'GameCoin', symbol: 'GAME' }) ); this.log('Token creation initiated'); } sendTokens(recipient: string, mintId: string, amount: string): void { ntransfer( this.signer(), // From current user recipient, // To recipient mintId, // Token ID BigInt(amount) // Amount (must be BigInt) ); this.log('Transfer completed'); } }

Logging

// Log messages and data for debugging/auditing log(...args: any[]): void

Example Usage:

class LoggingApp extends NApp { processTransaction(data: any): void { this.log('Processing transaction:', data); try { // Process logic here this.log('Transaction successful', { status: 'success' }); } catch (error) { this.log('Transaction failed:', error.message); throw error; } } }

Context Access

N1TS applications have access to transaction and app context through the NApp base class:

// Get transaction signer this.signer(): string // Get app admin this.appAdmin(): string // Get current app ID this.appId(): string // Get current timestamp this.time(): number

Example Usage:

class ContextApp extends NApp { // This is an internal helper method, NOT a transaction action protected getTransactionInfo(): any { return { signer: this.signer(), // Who sent this transaction appAdmin: this.appAdmin(), // Who manages this app appId: this.appId(), // Current app identifier timestamp: this.time() // When this is executing }; } requireAdmin(): void { if (this.signer() !== this.appAdmin()) { throw new Error('Admin access required'); } } createTimestampedEntry(data: any): void { const entry = { ...data, createdAt: this.time(), createdBy: this.signer() }; nwrite(`entry_${this.time()}`, JSON.stringify(entry), 'timestamped_data'); } }

Field Naming Conventions

N1TS uses specific field naming conventions for system data:

Token Data Fields

// Token balances: _balance_{mintId}_{address} const balance = await nread(`_balance_${mintId}_${userAddress}`); // Token admin: _mint_admin_{mintId} const admin = await nread(`_mint_admin_${mintId}`); // Token metadata: _mint_meta_{mintId} const metadata = await nread(`_mint_meta_${mintId}`); // Account nonces: _nonce_{address} const nonce = await nread(`_nonce_${userAddress}`);

Protected Fields

Fields starting with _ are protected and can only be written by:

  • System functions (like nmint, ntransfer)
  • App admin using admin functions
  • The field’s designated owner
class ProtectedFieldApp extends NApp { // ✅ Regular fields - anyone can write (transaction action) setPublicData(key: string, value: any): void { nwrite(`public_${key}`, value); } // ❌ This will fail - protected fields require admin access (transaction action) trySetProtectedData(): void { try { nwrite('_protected_field', 'value'); // Will throw error } catch (error) { this.log('Cannot write to protected field:', error.message); } } }

State Management Patterns

Automatic Persistence

Properties assigned to this are automatically persisted:

class StateApp extends NApp { counter: number; isActive: boolean; init(): void { this.counter = 0; this.isActive = true; } increment(): void { this.counter++; // Automatically saved this.log('Counter incremented to:', this.counter); } }

Typed Collections with NMap

class CollectionApp extends NApp { users = new NMap<UserProfile>(this, 'users'); scores = new NMap<number>(this, 'scores'); createUser(id: string, profile: UserProfile): void { this.users.set(id, profile, 'user_created', id); } updateScore(userId: string, score: number): void { this.scores.set(userId, score, 'score_update', userId); } // This is an internal helper method, NOT a transaction action protected getUser(id: string): UserProfile | undefined { return this.users.get(id); } }

Error Handling

N1TS provides comprehensive error handling and validation:

class SafeApp extends NApp { safeTokenTransfer( to: string, mintId: string, amount: string ): void { try { // Validation if (!to || !mintId || !amount) { throw new Error('Missing required parameters'); } const amountBig = BigInt(amount); if (amountBig <= 0) { throw new Error('Amount must be positive'); } // Note: In transaction actions, balance checks are handled by the system // Execute transfer ntransfer(this.signer(), to, mintId, amountBig); this.log('Transfer successful'); } catch (error) { this.log('Transfer failed:', error.message); throw error; // Re-throw to fail the transaction } } }

Best Practices

  1. Always use BigInt for token amounts to avoid precision loss
  2. Validate inputs before processing
  3. Use meaningful tags in nwrite calls for data organization
  4. Log important events for debugging and auditing
  5. Handle errors gracefully with try-catch blocks
  6. Check permissions before state modifications
  7. Use proper field naming conventions

This interface provides everything needed to build sophisticated smart contracts on N1TS while maintaining security and reliability.

Last updated on