@enclave-e3/sdk
v0.1.15
Published
A powerful, type-safe TypeScript SDK for interacting with Enclave smart contracts. This SDK provides real-time event listening, contract interaction methods, and comprehensive error handling.
Readme
Enclave TypeScript SDK
A powerful, type-safe TypeScript SDK for interacting with Enclave smart contracts. This SDK provides real-time event listening, contract interaction methods, and comprehensive error handling.
Features
- Event-driven architecture: Listen to smart contract events in real-time
- Type-safe: Built with TypeScript and uses generated types from contracts
- Easy contract interactions: Simple methods for reading from and writing to contracts
- React integration: Includes React hooks for easy frontend integration
- Error handling: Comprehensive error handling with custom error types
- Gas estimation: Built-in gas estimation for transactions
- Event polling: Support for both WebSocket and polling-based event listening
Installation
pnpm add @enclave-e3/sdkQuick Start
import { EnclaveSDK, EnclaveEventType, RegistryEventType } from '@enclave-e3/sdk'
import { createPublicClient, createWalletClient, http, custom } from 'viem'
// Initialize clients
const publicClient = createPublicClient({
transport: http('YOUR_RPC_URL'),
})
const walletClient = createWalletClient({
transport: custom(window.ethereum),
})
// Create SDK instance
const sdk = new EnclaveSDK({
publicClient,
walletClient,
contracts: {
enclave: '0x...', // Your Enclave contract address
ciphernodeRegistry: '0x...', // Your CiphernodeRegistry contract address
},
chainId: 1, // Optional
})
// Initialize the SDK
await sdk.initialize()
// Listen to events with the unified event system
sdk.onEnclaveEvent(EnclaveEventType.E3_REQUESTED, (event) => {
console.log('E3 Requested:', event.data)
})
sdk.onEnclaveEvent(RegistryEventType.CIPHERNODE_ADDED, (event) => {
console.log('Ciphernode Added:', event.data)
})
// Interact with contracts
const hash = await sdk.requestE3({
threshold: [1, 3],
startWindow: [BigInt(0), BigInt(100)],
duration: BigInt(3600),
e3Program: '0x...',
e3ProgramParams: '0x...',
computeProviderParams: '0x...',
customParams: '0x...',
})Usage within a browser
Usage within a typescript project should work out of the box, however in order to use wasm related functionality of the SDK within the browser vite you must do the following:
- Use
vite - Use the
vite-plugin-top-level-awaitplugin - Use the
vite-plugin-wasmplugin - Exclude the
@enclave-e3/wasmpackage from bundling optimization.
This will enable vite to correctly bundle and serve the wasm bundle we use effectively.
import { defineConfig } from 'vite'
import wasm from 'vite-plugin-wasm'
import topLevelAwait from 'vite-plugin-top-level-await'
export default defineConfig({
// other config ...
optimizeDeps: {
exclude: ['@enclave-e3/wasm'],
},
plugins: [wasm(), topLevelAwait()],
})Event System
The SDK uses a unified event system with TypeScript enums for type safety:
Enclave Events
enum EnclaveEventType {
// E3 Lifecycle
E3_REQUESTED = 'E3Requested',
E3_ACTIVATED = 'E3Activated',
INPUT_PUBLISHED = 'InputPublished',
CIPHERTEXT_OUTPUT_PUBLISHED = 'CiphertextOutputPublished',
PLAINTEXT_OUTPUT_PUBLISHED = 'PlaintextOutputPublished',
// E3 Program Management
E3_PROGRAM_ENABLED = 'E3ProgramEnabled',
E3_PROGRAM_DISABLED = 'E3ProgramDisabled',
// Configuration
CIPHERNODE_REGISTRY_SET = 'CiphernodeRegistrySet',
MAX_DURATION_SET = 'MaxDurationSet',
// ... more events
}Registry Events
enum RegistryEventType {
CIPHERNODE_ADDED = 'CiphernodeAdded',
CIPHERNODE_REMOVED = 'CiphernodeRemoved',
COMMITTEE_REQUESTED = 'CommitteeRequested',
COMMITTEE_PUBLISHED = 'CommitteePublished',
COMMITTEE_FINALIZED = 'CommitteeFinalized',
ENCLAVE_SET = 'EnclaveSet',
// ... more events
}Event Data Structure
Each event follows a consistent structure:
interface EnclaveEvent<T extends AllEventTypes> {
type: T
data: EventData[T] // Typed based on event type
log: Log // Raw viem log
timestamp: Date
blockNumber: bigint
transactionHash: string
}React Integration
The SDK includes a React hook for easy integration:
import { useEnclaveSDK } from "@enclave-e3/contracts/sdk";
function MyComponent() {
const {
sdk,
isInitialized,
isConnecting,
error,
connectWallet,
requestE3,
onEnclaveEvent,
EnclaveEventType,
} = useEnclaveSDK({
contracts: {
enclave: "0x...",
ciphernodeRegistry: "0x...",
},
rpcUrl: "YOUR_RPC_URL",
autoConnect: true,
});
useEffect(() => {
if (isInitialized) {
onEnclaveEvent(EnclaveEventType.E3_REQUESTED, (event) => {
console.log("New E3 request:", event);
});
}
}, [isInitialized]);
return (
<div>
{!isInitialized && (
<button onClick={connectWallet} disabled={isConnecting}>
{isConnecting ? "Connecting..." : "Connect Wallet"}
</button>
)}
{/* Your UI */}
</div>
);
}API Reference
Core Methods
Contract Interactions
// Request a new E3 computation
await sdk.requestE3({
threshold: [number, number],
startWindow: [bigint, bigint],
duration: bigint,
e3Program: `0x${string}`,
e3ProgramParams: `0x${string}`,
computeProviderParams: `0x${string}`,
customParams?: `0x${string}`,
gasLimit?: bigint
});
// Activate an E3 computation
await sdk.activateE3(e3Id: bigint, gasLimit?: bigint);
// Publish input data
await sdk.publishInput(e3Id: bigint, data: `0x${string}`, gasLimit?: bigint);
// Read operations
const e3Data = await sdk.getE3(e3Id: bigint);Event Handling
sdk.onEnclaveEvent(eventType: AllEventTypes, callback: EventCallback);
sdk.off(eventType: AllEventTypes, callback: EventCallback);
const logs = await sdk.getHistoricalEvents(
eventType: AllEventTypes,
fromBlock?: bigint,
toBlock?: bigint
);
// Event polling (if websockets unavailable)
await sdk.startEventPolling();
sdk.stopEventPolling();Utilities
// Gas estimation
const gas = await sdk.estimateGas(functionName, args, contractAddress, abi, value?);
// Transaction waiting
const receipt = await sdk.waitForTransaction(hash);
// Configuration updates
sdk.updateConfig(newConfig: Partial<SDKConfig>);
// Cleanup
sdk.cleanup();Configuration
interface SDKConfig {
publicClient: PublicClient
walletClient?: WalletClient
contracts: {
enclave: `0x${string}`
ciphernodeRegistry: `0x${string}`
}
chainId?: number
}Error Handling
The SDK includes comprehensive error handling:
import { SDKError } from '@enclave-e3/sdk'
try {
await sdk.requestE3(params)
} catch (error) {
if (error instanceof SDKError) {
console.error(`SDK Error (${error.code}): ${error.message}`)
} else {
console.error('Unexpected error:', error)
}
}Development
Building the SDK
cd packages/enclave-contracts
pnpm compileRunning the Demo
cd examples/basic/client
pnpm install
pnpm devThe demo showcases all SDK features including real-time event listening and contract interactions.
Testing
cd packages/enclave-contracts
pnpm testArchitecture
The SDK consists of several key components:
- EnclaveSDK: Main orchestrator class
- ContractClient: Handles contract read/write operations
- EventListener: Manages real-time event listening
- Types: TypeScript definitions with full type safety
- Utils: Helper functions and error classes
License
This project is licensed under the MIT License.
